]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/sunxi/sun50i-codec-analog.c
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux.git] / sound / soc / sunxi / sun50i-codec-analog.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * This driver supports the analog controls for the internal codec
4  * found in Allwinner's A64 SoC.
5  *
6  * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org>
7  * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.com>
8  * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
9  *
10  * Based on sun8i-codec-analog.c
11  *
12  */
13
14 #include <linux/io.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/of_device.h>
19 #include <linux/platform_device.h>
20 #include <linux/regmap.h>
21
22 #include <sound/soc.h>
23 #include <sound/soc-dapm.h>
24 #include <sound/tlv.h>
25
26 #include "sun8i-adda-pr-regmap.h"
27
28 /* Codec analog control register offsets and bit fields */
29 #define SUN50I_ADDA_HP_CTRL             0x00
30 #define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE         7
31 #define SUN50I_ADDA_HP_CTRL_HPPA_EN             6
32 #define SUN50I_ADDA_HP_CTRL_HPVOL               0
33
34 #define SUN50I_ADDA_OL_MIX_CTRL         0x01
35 #define SUN50I_ADDA_OL_MIX_CTRL_MIC1            6
36 #define SUN50I_ADDA_OL_MIX_CTRL_MIC2            5
37 #define SUN50I_ADDA_OL_MIX_CTRL_PHONE           4
38 #define SUN50I_ADDA_OL_MIX_CTRL_PHONEN          3
39 #define SUN50I_ADDA_OL_MIX_CTRL_LINEINL         2
40 #define SUN50I_ADDA_OL_MIX_CTRL_DACL            1
41 #define SUN50I_ADDA_OL_MIX_CTRL_DACR            0
42
43 #define SUN50I_ADDA_OR_MIX_CTRL         0x02
44 #define SUN50I_ADDA_OR_MIX_CTRL_MIC1            6
45 #define SUN50I_ADDA_OR_MIX_CTRL_MIC2            5
46 #define SUN50I_ADDA_OR_MIX_CTRL_PHONE           4
47 #define SUN50I_ADDA_OR_MIX_CTRL_PHONEP          3
48 #define SUN50I_ADDA_OR_MIX_CTRL_LINEINR         2
49 #define SUN50I_ADDA_OR_MIX_CTRL_DACR            1
50 #define SUN50I_ADDA_OR_MIX_CTRL_DACL            0
51
52 #define SUN50I_ADDA_LINEOUT_CTRL0       0x05
53 #define SUN50I_ADDA_LINEOUT_CTRL0_LEN           7
54 #define SUN50I_ADDA_LINEOUT_CTRL0_REN           6
55 #define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL      5
56 #define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL      4
57
58 #define SUN50I_ADDA_LINEOUT_CTRL1       0x06
59 #define SUN50I_ADDA_LINEOUT_CTRL1_VOL           0
60
61 #define SUN50I_ADDA_MIC1_CTRL           0x07
62 #define SUN50I_ADDA_MIC1_CTRL_MIC1G             4
63 #define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN         3
64 #define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST         0
65
66 #define SUN50I_ADDA_MIC2_CTRL           0x08
67 #define SUN50I_ADDA_MIC2_CTRL_MIC2G             4
68 #define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN         3
69 #define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST         0
70
71 #define SUN50I_ADDA_LINEIN_CTRL         0x09
72 #define SUN50I_ADDA_LINEIN_CTRL_LINEING         0
73
74 #define SUN50I_ADDA_MIX_DAC_CTRL        0x0a
75 #define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN        7
76 #define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN        6
77 #define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN         5
78 #define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN         4
79 #define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE      3
80 #define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE      2
81 #define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS          1
82 #define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS          0
83
84 #define SUN50I_ADDA_L_ADCMIX_SRC        0x0b
85 #define SUN50I_ADDA_L_ADCMIX_SRC_MIC1           6
86 #define SUN50I_ADDA_L_ADCMIX_SRC_MIC2           5
87 #define SUN50I_ADDA_L_ADCMIX_SRC_PHONE          4
88 #define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN         3
89 #define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL        2
90 #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL         1
91 #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR         0
92
93 #define SUN50I_ADDA_R_ADCMIX_SRC        0x0c
94 #define SUN50I_ADDA_R_ADCMIX_SRC_MIC1           6
95 #define SUN50I_ADDA_R_ADCMIX_SRC_MIC2           5
96 #define SUN50I_ADDA_R_ADCMIX_SRC_PHONE          4
97 #define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP         3
98 #define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR        2
99 #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR          1
100 #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL          0
101
102 #define SUN50I_ADDA_ADC_CTRL            0x0d
103 #define SUN50I_ADDA_ADC_CTRL_ADCREN             7
104 #define SUN50I_ADDA_ADC_CTRL_ADCLEN             6
105 #define SUN50I_ADDA_ADC_CTRL_ADCG               0
106
107 #define SUN50I_ADDA_HS_MBIAS_CTRL       0x0e
108 #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN    7
109
110 #define SUN50I_ADDA_JACK_MIC_CTRL       0x1d
111 #define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN    5
112
113 /* mixer controls */
114 static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = {
115         SOC_DAPM_DOUBLE_R("DAC Playback Switch",
116                           SUN50I_ADDA_OL_MIX_CTRL,
117                           SUN50I_ADDA_OR_MIX_CTRL,
118                           SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
119         SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
120                           SUN50I_ADDA_OL_MIX_CTRL,
121                           SUN50I_ADDA_OR_MIX_CTRL,
122                           SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
123         SOC_DAPM_DOUBLE_R("Line In Playback Switch",
124                           SUN50I_ADDA_OL_MIX_CTRL,
125                           SUN50I_ADDA_OR_MIX_CTRL,
126                           SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0),
127         SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
128                           SUN50I_ADDA_OL_MIX_CTRL,
129                           SUN50I_ADDA_OR_MIX_CTRL,
130                           SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
131         SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
132                           SUN50I_ADDA_OL_MIX_CTRL,
133                           SUN50I_ADDA_OR_MIX_CTRL,
134                           SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
135 };
136
137 /* ADC mixer controls */
138 static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = {
139         SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
140                           SUN50I_ADDA_L_ADCMIX_SRC,
141                           SUN50I_ADDA_R_ADCMIX_SRC,
142                           SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
143         SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
144                           SUN50I_ADDA_L_ADCMIX_SRC,
145                           SUN50I_ADDA_R_ADCMIX_SRC,
146                           SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
147         SOC_DAPM_DOUBLE_R("Line In Capture Switch",
148                           SUN50I_ADDA_L_ADCMIX_SRC,
149                           SUN50I_ADDA_R_ADCMIX_SRC,
150                           SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0),
151         SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
152                           SUN50I_ADDA_L_ADCMIX_SRC,
153                           SUN50I_ADDA_R_ADCMIX_SRC,
154                           SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
155         SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
156                           SUN50I_ADDA_L_ADCMIX_SRC,
157                           SUN50I_ADDA_R_ADCMIX_SRC,
158                           SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
159 };
160
161 static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale,
162                                   -450, 150, 0);
163 static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale,
164         0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
165         1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
166 );
167
168 static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1);
169
170 static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale,
171         0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
172         2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
173 );
174
175
176 /* volume / mute controls */
177 static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
178         SOC_SINGLE_TLV("Headphone Playback Volume",
179                        SUN50I_ADDA_HP_CTRL,
180                        SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0,
181                        sun50i_codec_hp_vol_scale),
182
183         SOC_DOUBLE("Headphone Playback Switch",
184                    SUN50I_ADDA_MIX_DAC_CTRL,
185                    SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
186                    SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0),
187
188         /* Mixer pre-gain */
189         SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL,
190                        SUN50I_ADDA_MIC1_CTRL_MIC1G,
191                        0x7, 0, sun50i_codec_out_mixer_pregain_scale),
192
193         /* Microphone Amp boost gain */
194         SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL,
195                        SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0,
196                        sun50i_codec_mic_gain_scale),
197
198         /* Mixer pre-gain */
199         SOC_SINGLE_TLV("Mic2 Playback Volume",
200                        SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G,
201                        0x7, 0, sun50i_codec_out_mixer_pregain_scale),
202
203         /* Microphone Amp boost gain */
204         SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL,
205                        SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0,
206                        sun50i_codec_mic_gain_scale),
207
208         /* ADC */
209         SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL,
210                        SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0,
211                        sun50i_codec_out_mixer_pregain_scale),
212
213         /* Mixer pre-gain */
214         SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL,
215                        SUN50I_ADDA_LINEIN_CTRL_LINEING,
216                        0x7, 0, sun50i_codec_out_mixer_pregain_scale),
217
218         SOC_SINGLE_TLV("Line Out Playback Volume",
219                        SUN50I_ADDA_LINEOUT_CTRL1,
220                        SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0,
221                        sun50i_codec_lineout_vol_scale),
222
223         SOC_DOUBLE("Line Out Playback Switch",
224                    SUN50I_ADDA_LINEOUT_CTRL0,
225                    SUN50I_ADDA_LINEOUT_CTRL0_LEN,
226                    SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0),
227
228 };
229
230 static const char * const sun50i_codec_hp_src_enum_text[] = {
231         "DAC", "Mixer",
232 };
233
234 static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum,
235                             SUN50I_ADDA_MIX_DAC_CTRL,
236                             SUN50I_ADDA_MIX_DAC_CTRL_LHPIS,
237                             SUN50I_ADDA_MIX_DAC_CTRL_RHPIS,
238                             sun50i_codec_hp_src_enum_text);
239
240 static const struct snd_kcontrol_new sun50i_codec_hp_src[] = {
241         SOC_DAPM_ENUM("Headphone Source Playback Route",
242                       sun50i_codec_hp_src_enum),
243 };
244
245 static const char * const sun50i_codec_lineout_src_enum_text[] = {
246         "Stereo", "Mono Differential",
247 };
248
249 static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum,
250                             SUN50I_ADDA_LINEOUT_CTRL0,
251                             SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL,
252                             SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL,
253                             sun50i_codec_lineout_src_enum_text);
254
255 static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = {
256         SOC_DAPM_ENUM("Line Out Source Playback Route",
257                       sun50i_codec_lineout_src_enum),
258 };
259
260 static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
261         /* DAC */
262         SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
263                          SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0),
264         SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
265                          SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0),
266         /* ADC */
267         SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL,
268                          SUN50I_ADDA_ADC_CTRL_ADCLEN, 0),
269         SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL,
270                          SUN50I_ADDA_ADC_CTRL_ADCREN, 0),
271         /*
272          * Due to this component and the codec belonging to separate DAPM
273          * contexts, we need to manually link the above widgets to their
274          * stream widgets at the card level.
275          */
276
277         SND_SOC_DAPM_MUX("Headphone Source Playback Route",
278                          SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
279         SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL,
280                              SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0),
281         SND_SOC_DAPM_OUTPUT("HP"),
282
283         SND_SOC_DAPM_MUX("Line Out Source Playback Route",
284                          SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
285         SND_SOC_DAPM_OUTPUT("LINEOUT"),
286
287         /* Microphone inputs */
288         SND_SOC_DAPM_INPUT("MIC1"),
289
290         /* Microphone Bias */
291         SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL,
292                             SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN,
293                             0, NULL, 0),
294
295         /* Mic input path */
296         SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL,
297                          SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0),
298
299         /* Microphone input */
300         SND_SOC_DAPM_INPUT("MIC2"),
301
302         /* Microphone Bias */
303         SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL,
304                             SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN,
305                             0, NULL, 0),
306
307         /* Mic input path */
308         SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL,
309                          SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0),
310
311         /* Line input */
312         SND_SOC_DAPM_INPUT("LINEIN"),
313
314         /* Mixers */
315         SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
316                            SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0,
317                            sun50i_a64_codec_mixer_controls,
318                            ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
319         SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
320                            SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0,
321                            sun50i_a64_codec_mixer_controls,
322                            ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
323         SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL,
324                            SUN50I_ADDA_ADC_CTRL_ADCLEN, 0,
325                            sun50i_codec_adc_mixer_controls,
326                            ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
327         SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL,
328                            SUN50I_ADDA_ADC_CTRL_ADCREN, 0,
329                            sun50i_codec_adc_mixer_controls,
330                            ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
331 };
332
333 static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = {
334         /* Left Mixer Routes */
335         { "Left Mixer", "DAC Playback Switch", "Left DAC" },
336         { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
337         { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
338
339         /* Right Mixer Routes */
340         { "Right Mixer", "DAC Playback Switch", "Right DAC" },
341         { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
342         { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
343
344         /* Left ADC Mixer Routes */
345         { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
346         { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
347         { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
348
349         /* Right ADC Mixer Routes */
350         { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
351         { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
352         { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
353
354         /* ADC Routes */
355         { "Left ADC", NULL, "Left ADC Mixer" },
356         { "Right ADC", NULL, "Right ADC Mixer" },
357
358         /* Headphone Routes */
359         { "Headphone Source Playback Route", "DAC", "Left DAC" },
360         { "Headphone Source Playback Route", "DAC", "Right DAC" },
361         { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
362         { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
363         { "Headphone Amp", NULL, "Headphone Source Playback Route" },
364         { "HP", NULL, "Headphone Amp" },
365
366         /* Microphone Routes */
367         { "Mic1 Amplifier", NULL, "MIC1"},
368
369         /* Microphone Routes */
370         { "Mic2 Amplifier", NULL, "MIC2"},
371         { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
372         { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
373         { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
374         { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
375
376         /* Line-in Routes */
377         { "Left Mixer", "Line In Playback Switch", "LINEIN" },
378         { "Right Mixer", "Line In Playback Switch", "LINEIN" },
379         { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
380         { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
381
382         /* Line-out Routes */
383         { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
384         { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
385         { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
386         { "Line Out Source Playback Route", "Mono Differential",
387                 "Right Mixer" },
388         { "LINEOUT", NULL, "Line Out Source Playback Route" },
389 };
390
391 static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
392         .controls               = sun50i_a64_codec_controls,
393         .num_controls           = ARRAY_SIZE(sun50i_a64_codec_controls),
394         .dapm_widgets           = sun50i_a64_codec_widgets,
395         .num_dapm_widgets       = ARRAY_SIZE(sun50i_a64_codec_widgets),
396         .dapm_routes            = sun50i_a64_codec_routes,
397         .num_dapm_routes        = ARRAY_SIZE(sun50i_a64_codec_routes),
398 };
399
400 static const struct of_device_id sun50i_codec_analog_of_match[] = {
401         {
402                 .compatible = "allwinner,sun50i-a64-codec-analog",
403         },
404         {}
405 };
406 MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match);
407
408 static int sun50i_codec_analog_probe(struct platform_device *pdev)
409 {
410         struct resource *res;
411         struct regmap *regmap;
412         void __iomem *base;
413
414         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
415         base = devm_ioremap_resource(&pdev->dev, res);
416         if (IS_ERR(base)) {
417                 dev_err(&pdev->dev, "Failed to map the registers\n");
418                 return PTR_ERR(base);
419         }
420
421         regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base);
422         if (IS_ERR(regmap)) {
423                 dev_err(&pdev->dev, "Failed to create regmap\n");
424                 return PTR_ERR(regmap);
425         }
426
427         return devm_snd_soc_register_component(&pdev->dev,
428                                                &sun50i_codec_analog_cmpnt_drv,
429                                                NULL, 0);
430 }
431
432 static struct platform_driver sun50i_codec_analog_driver = {
433         .driver = {
434                 .name = "sun50i-codec-analog",
435                 .of_match_table = sun50i_codec_analog_of_match,
436         },
437         .probe = sun50i_codec_analog_probe,
438 };
439 module_platform_driver(sun50i_codec_analog_driver);
440
441 MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64");
442 MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
443 MODULE_LICENSE("GPL");
444 MODULE_ALIAS("platform:sun50i-codec-analog");