]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/sunxi/sun4i-codec.c
ASoC: sun4i-codec: Add Mic Playback Volume
[linux.git] / sound / soc / sunxi / sun4i-codec.c
1 /*
2  * Copyright 2014 Emilio López <emilio@elopez.com.ar>
3  * Copyright 2014 Jon Smirl <jonsmirl@gmail.com>
4  * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
5  * Copyright 2015 Adam Sampson <ats@offog.org>
6  * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
7  *
8  * Based on the Allwinner SDK driver, released under the GPL.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  */
20
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/of.h>
28 #include <linux/of_address.h>
29 #include <linux/of_device.h>
30 #include <linux/of_platform.h>
31 #include <linux/clk.h>
32 #include <linux/regmap.h>
33 #include <linux/reset.h>
34 #include <linux/gpio/consumer.h>
35
36 #include <sound/core.h>
37 #include <sound/pcm.h>
38 #include <sound/pcm_params.h>
39 #include <sound/soc.h>
40 #include <sound/tlv.h>
41 #include <sound/initval.h>
42 #include <sound/dmaengine_pcm.h>
43
44 /* Codec DAC digital controls and FIFO registers */
45 #define SUN4I_CODEC_DAC_DPC                     (0x00)
46 #define SUN4I_CODEC_DAC_DPC_EN_DA                       (31)
47 #define SUN4I_CODEC_DAC_DPC_DVOL                        (12)
48 #define SUN4I_CODEC_DAC_FIFOC                   (0x04)
49 #define SUN4I_CODEC_DAC_FIFOC_DAC_FS                    (29)
50 #define SUN4I_CODEC_DAC_FIFOC_FIR_VERSION               (28)
51 #define SUN4I_CODEC_DAC_FIFOC_SEND_LASAT                (26)
52 #define SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE              (24)
53 #define SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT               (21)
54 #define SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL             (8)
55 #define SUN4I_CODEC_DAC_FIFOC_MONO_EN                   (6)
56 #define SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS            (5)
57 #define SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN                (4)
58 #define SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH                (0)
59 #define SUN4I_CODEC_DAC_FIFOS                   (0x08)
60 #define SUN4I_CODEC_DAC_TXDATA                  (0x0c)
61
62 /* Codec DAC side analog signal controls */
63 #define SUN4I_CODEC_DAC_ACTL                    (0x10)
64 #define SUN4I_CODEC_DAC_ACTL_DACAENR                    (31)
65 #define SUN4I_CODEC_DAC_ACTL_DACAENL                    (30)
66 #define SUN4I_CODEC_DAC_ACTL_MIXEN                      (29)
67 #define SUN4I_CODEC_DAC_ACTL_MICG                       (20)
68 #define SUN4I_CODEC_DAC_ACTL_LDACLMIXS                  (15)
69 #define SUN4I_CODEC_DAC_ACTL_RDACRMIXS                  (14)
70 #define SUN4I_CODEC_DAC_ACTL_LDACRMIXS                  (13)
71 #define SUN4I_CODEC_DAC_ACTL_DACPAS                     (8)
72 #define SUN4I_CODEC_DAC_ACTL_MIXPAS                     (7)
73 #define SUN4I_CODEC_DAC_ACTL_PA_MUTE                    (6)
74 #define SUN4I_CODEC_DAC_ACTL_PA_VOL                     (0)
75 #define SUN4I_CODEC_DAC_TUNE                    (0x14)
76 #define SUN4I_CODEC_DAC_DEBUG                   (0x18)
77
78 /* Codec ADC digital controls and FIFO registers */
79 #define SUN4I_CODEC_ADC_FIFOC                   (0x1c)
80 #define SUN4I_CODEC_ADC_FIFOC_ADC_FS                    (29)
81 #define SUN4I_CODEC_ADC_FIFOC_EN_AD                     (28)
82 #define SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE              (24)
83 #define SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL             (8)
84 #define SUN4I_CODEC_ADC_FIFOC_MONO_EN                   (7)
85 #define SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS            (6)
86 #define SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN                (4)
87 #define SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH                (0)
88 #define SUN4I_CODEC_ADC_FIFOS                   (0x20)
89 #define SUN4I_CODEC_ADC_RXDATA                  (0x24)
90
91 /* Codec ADC side analog signal controls */
92 #define SUN4I_CODEC_ADC_ACTL                    (0x28)
93 #define SUN4I_CODEC_ADC_ACTL_ADC_R_EN                   (31)
94 #define SUN4I_CODEC_ADC_ACTL_ADC_L_EN                   (30)
95 #define SUN4I_CODEC_ADC_ACTL_PREG1EN                    (29)
96 #define SUN4I_CODEC_ADC_ACTL_PREG2EN                    (28)
97 #define SUN4I_CODEC_ADC_ACTL_VMICEN                     (27)
98 #define SUN4I_CODEC_ADC_ACTL_VADCG                      (20)
99 #define SUN4I_CODEC_ADC_ACTL_ADCIS                      (17)
100 #define SUN4I_CODEC_ADC_ACTL_PA_EN                      (4)
101 #define SUN4I_CODEC_ADC_ACTL_DDE                        (3)
102 #define SUN4I_CODEC_ADC_DEBUG                   (0x2c)
103
104 /* FIFO counters */
105 #define SUN4I_CODEC_DAC_TXCNT                   (0x30)
106 #define SUN4I_CODEC_ADC_RXCNT                   (0x34)
107
108 /* Calibration register (sun7i only) */
109 #define SUN7I_CODEC_AC_DAC_CAL                  (0x38)
110
111 /* Microphone controls (sun7i only) */
112 #define SUN7I_CODEC_AC_MIC_PHONE_CAL            (0x3c)
113
114 /*
115  * sun6i specific registers
116  *
117  * sun6i shares the same digital control and FIFO registers as sun4i,
118  * but only the DAC digital controls are at the same offset. The others
119  * have been moved around to accommodate extra analog controls.
120  */
121
122 /* Codec DAC digital controls and FIFO registers */
123 #define SUN6I_CODEC_ADC_FIFOC                   (0x10)
124 #define SUN6I_CODEC_ADC_FIFOC_EN_AD                     (28)
125 #define SUN6I_CODEC_ADC_FIFOS                   (0x14)
126 #define SUN6I_CODEC_ADC_RXDATA                  (0x18)
127
128 /* Output mixer and gain controls */
129 #define SUN6I_CODEC_OM_DACA_CTRL                (0x20)
130 #define SUN6I_CODEC_OM_DACA_CTRL_DACAREN                (31)
131 #define SUN6I_CODEC_OM_DACA_CTRL_DACALEN                (30)
132 #define SUN6I_CODEC_OM_DACA_CTRL_RMIXEN                 (29)
133 #define SUN6I_CODEC_OM_DACA_CTRL_LMIXEN                 (28)
134 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC1              (23)
135 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2              (22)
136 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONE             (21)
137 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONEP            (20)
138 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_LINEINR           (19)
139 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR              (18)
140 #define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL              (17)
141 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC1              (16)
142 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC2              (15)
143 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONE             (14)
144 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONEN            (13)
145 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_LINEINL           (12)
146 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL              (11)
147 #define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR              (10)
148 #define SUN6I_CODEC_OM_DACA_CTRL_RHPIS                  (9)
149 #define SUN6I_CODEC_OM_DACA_CTRL_LHPIS                  (8)
150 #define SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE              (7)
151 #define SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE              (6)
152 #define SUN6I_CODEC_OM_DACA_CTRL_HPVOL                  (0)
153 #define SUN6I_CODEC_OM_PA_CTRL                  (0x24)
154 #define SUN6I_CODEC_OM_PA_CTRL_HPPAEN                   (31)
155 #define SUN6I_CODEC_OM_PA_CTRL_HPCOM_CTL                (29)
156 #define SUN6I_CODEC_OM_PA_CTRL_COMPTEN                  (28)
157 #define SUN6I_CODEC_OM_PA_CTRL_MIC1G                    (15)
158 #define SUN6I_CODEC_OM_PA_CTRL_MIC2G                    (12)
159 #define SUN6I_CODEC_OM_PA_CTRL_LINEING                  (9)
160 #define SUN6I_CODEC_OM_PA_CTRL_PHONEG                   (6)
161 #define SUN6I_CODEC_OM_PA_CTRL_PHONEPG                  (3)
162 #define SUN6I_CODEC_OM_PA_CTRL_PHONENG                  (0)
163
164 /* Microphone, line out and phone out controls */
165 #define SUN6I_CODEC_MIC_CTRL                    (0x28)
166 #define SUN6I_CODEC_MIC_CTRL_HBIASEN                    (31)
167 #define SUN6I_CODEC_MIC_CTRL_MBIASEN                    (30)
168 #define SUN6I_CODEC_MIC_CTRL_MIC1AMPEN                  (28)
169 #define SUN6I_CODEC_MIC_CTRL_MIC1BOOST                  (25)
170 #define SUN6I_CODEC_MIC_CTRL_MIC2AMPEN                  (24)
171 #define SUN6I_CODEC_MIC_CTRL_MIC2BOOST                  (21)
172 #define SUN6I_CODEC_MIC_CTRL_MIC2SLT                    (20)
173 #define SUN6I_CODEC_MIC_CTRL_LINEOUTLEN                 (19)
174 #define SUN6I_CODEC_MIC_CTRL_LINEOUTREN                 (18)
175 #define SUN6I_CODEC_MIC_CTRL_LINEOUTLSRC                (17)
176 #define SUN6I_CODEC_MIC_CTRL_LINEOUTRSRC                (16)
177 #define SUN6I_CODEC_MIC_CTRL_LINEOUTVC                  (11)
178 #define SUN6I_CODEC_MIC_CTRL_PHONEPREG                  (8)
179
180 /* ADC mixer controls */
181 #define SUN6I_CODEC_ADC_ACTL                    (0x2c)
182 #define SUN6I_CODEC_ADC_ACTL_ADCREN                     (31)
183 #define SUN6I_CODEC_ADC_ACTL_ADCLEN                     (30)
184 #define SUN6I_CODEC_ADC_ACTL_ADCRG                      (27)
185 #define SUN6I_CODEC_ADC_ACTL_ADCLG                      (24)
186 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1               (13)
187 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2               (12)
188 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONE              (11)
189 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONEP             (10)
190 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR            (9)
191 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR              (8)
192 #define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL              (7)
193 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1               (6)
194 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2               (5)
195 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONE              (4)
196 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONEN             (3)
197 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL            (2)
198 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL              (1)
199 #define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR              (0)
200
201 /* Analog performance tuning controls */
202 #define SUN6I_CODEC_ADDA_TUNE                   (0x30)
203
204 /* Calibration controls */
205 #define SUN6I_CODEC_CALIBRATION                 (0x34)
206
207 /* FIFO counters */
208 #define SUN6I_CODEC_DAC_TXCNT                   (0x40)
209 #define SUN6I_CODEC_ADC_RXCNT                   (0x44)
210
211 /* headset jack detection and button support registers */
212 #define SUN6I_CODEC_HMIC_CTL                    (0x50)
213 #define SUN6I_CODEC_HMIC_DATA                   (0x54)
214
215 /* TODO sun6i DAP (Digital Audio Processing) bits */
216
217 /* FIFO counters moved on A23 */
218 #define SUN8I_A23_CODEC_DAC_TXCNT               (0x1c)
219 #define SUN8I_A23_CODEC_ADC_RXCNT               (0x20)
220
221 /* TX FIFO moved on H3 */
222 #define SUN8I_H3_CODEC_DAC_TXDATA               (0x20)
223 #define SUN8I_H3_CODEC_DAC_DBG                  (0x48)
224 #define SUN8I_H3_CODEC_ADC_DBG                  (0x4c)
225
226 /* TODO H3 DAP (Digital Audio Processing) bits */
227
228 struct sun4i_codec {
229         struct device   *dev;
230         struct regmap   *regmap;
231         struct clk      *clk_apb;
232         struct clk      *clk_module;
233         struct reset_control *rst;
234         struct gpio_desc *gpio_pa;
235
236         /* ADC_FIFOC register is at different offset on different SoCs */
237         struct regmap_field *reg_adc_fifoc;
238
239         struct snd_dmaengine_dai_dma_data       capture_dma_data;
240         struct snd_dmaengine_dai_dma_data       playback_dma_data;
241 };
242
243 static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
244 {
245         /* Flush TX FIFO */
246         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
247                            BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH),
248                            BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
249
250         /* Enable DAC DRQ */
251         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
252                            BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN),
253                            BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
254 }
255
256 static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
257 {
258         /* Disable DAC DRQ */
259         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
260                            BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN),
261                            0);
262 }
263
264 static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
265 {
266         /* Enable ADC DRQ */
267         regmap_field_update_bits(scodec->reg_adc_fifoc,
268                                  BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN),
269                                  BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
270 }
271
272 static void sun4i_codec_stop_capture(struct sun4i_codec *scodec)
273 {
274         /* Disable ADC DRQ */
275         regmap_field_update_bits(scodec->reg_adc_fifoc,
276                                  BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN), 0);
277 }
278
279 static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
280                                struct snd_soc_dai *dai)
281 {
282         struct snd_soc_pcm_runtime *rtd = substream->private_data;
283         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
284
285         switch (cmd) {
286         case SNDRV_PCM_TRIGGER_START:
287         case SNDRV_PCM_TRIGGER_RESUME:
288         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
289                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
290                         sun4i_codec_start_playback(scodec);
291                 else
292                         sun4i_codec_start_capture(scodec);
293                 break;
294
295         case SNDRV_PCM_TRIGGER_STOP:
296         case SNDRV_PCM_TRIGGER_SUSPEND:
297         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
298                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
299                         sun4i_codec_stop_playback(scodec);
300                 else
301                         sun4i_codec_stop_capture(scodec);
302                 break;
303
304         default:
305                 return -EINVAL;
306         }
307
308         return 0;
309 }
310
311 static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
312                                        struct snd_soc_dai *dai)
313 {
314         struct snd_soc_pcm_runtime *rtd = substream->private_data;
315         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
316
317
318         /* Flush RX FIFO */
319         regmap_field_update_bits(scodec->reg_adc_fifoc,
320                                  BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH),
321                                  BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH));
322
323
324         /* Set RX FIFO trigger level */
325         regmap_field_update_bits(scodec->reg_adc_fifoc,
326                                  0xf << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL,
327                                  0x7 << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL);
328
329         /*
330          * FIXME: Undocumented in the datasheet, but
331          *        Allwinner's code mentions that it is related
332          *        related to microphone gain
333          */
334         if (of_device_is_compatible(scodec->dev->of_node,
335                                     "allwinner,sun4i-a10-codec") ||
336             of_device_is_compatible(scodec->dev->of_node,
337                                     "allwinner,sun7i-a20-codec")) {
338                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
339                                    0x3 << 25,
340                                    0x1 << 25);
341         }
342
343         if (of_device_is_compatible(scodec->dev->of_node,
344                                     "allwinner,sun7i-a20-codec"))
345                 /* FIXME: Undocumented bits */
346                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_TUNE,
347                                    0x3 << 8,
348                                    0x1 << 8);
349
350         return 0;
351 }
352
353 static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
354                                         struct snd_soc_dai *dai)
355 {
356         struct snd_soc_pcm_runtime *rtd = substream->private_data;
357         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
358         u32 val;
359
360         /* Flush the TX FIFO */
361         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
362                            BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH),
363                            BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
364
365         /* Set TX FIFO Empty Trigger Level */
366         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
367                            0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
368                            0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
369
370         if (substream->runtime->rate > 32000)
371                 /* Use 64 bits FIR filter */
372                 val = 0;
373         else
374                 /* Use 32 bits FIR filter */
375                 val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION);
376
377         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
378                            BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
379                            val);
380
381         /* Send zeros when we have an underrun */
382         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
383                            BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT),
384                            0);
385
386         return 0;
387 };
388
389 static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
390                                struct snd_soc_dai *dai)
391 {
392         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
393                 return sun4i_codec_prepare_playback(substream, dai);
394
395         return sun4i_codec_prepare_capture(substream, dai);
396 }
397
398 static unsigned long sun4i_codec_get_mod_freq(struct snd_pcm_hw_params *params)
399 {
400         unsigned int rate = params_rate(params);
401
402         switch (rate) {
403         case 176400:
404         case 88200:
405         case 44100:
406         case 33075:
407         case 22050:
408         case 14700:
409         case 11025:
410         case 7350:
411                 return 22579200;
412
413         case 192000:
414         case 96000:
415         case 48000:
416         case 32000:
417         case 24000:
418         case 16000:
419         case 12000:
420         case 8000:
421                 return 24576000;
422
423         default:
424                 return 0;
425         }
426 }
427
428 static int sun4i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
429 {
430         unsigned int rate = params_rate(params);
431
432         switch (rate) {
433         case 192000:
434         case 176400:
435                 return 6;
436
437         case 96000:
438         case 88200:
439                 return 7;
440
441         case 48000:
442         case 44100:
443                 return 0;
444
445         case 32000:
446         case 33075:
447                 return 1;
448
449         case 24000:
450         case 22050:
451                 return 2;
452
453         case 16000:
454         case 14700:
455                 return 3;
456
457         case 12000:
458         case 11025:
459                 return 4;
460
461         case 8000:
462         case 7350:
463                 return 5;
464
465         default:
466                 return -EINVAL;
467         }
468 }
469
470 static int sun4i_codec_hw_params_capture(struct sun4i_codec *scodec,
471                                          struct snd_pcm_hw_params *params,
472                                          unsigned int hwrate)
473 {
474         /* Set ADC sample rate */
475         regmap_field_update_bits(scodec->reg_adc_fifoc,
476                                  7 << SUN4I_CODEC_ADC_FIFOC_ADC_FS,
477                                  hwrate << SUN4I_CODEC_ADC_FIFOC_ADC_FS);
478
479         /* Set the number of channels we want to use */
480         if (params_channels(params) == 1)
481                 regmap_field_update_bits(scodec->reg_adc_fifoc,
482                                          BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN),
483                                          BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
484         else
485                 regmap_field_update_bits(scodec->reg_adc_fifoc,
486                                          BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN),
487                                          0);
488
489         /* Set the number of sample bits to either 16 or 24 bits */
490         if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
491                 regmap_field_update_bits(scodec->reg_adc_fifoc,
492                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS),
493                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS));
494
495                 regmap_field_update_bits(scodec->reg_adc_fifoc,
496                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE),
497                                    0);
498
499                 scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
500         } else {
501                 regmap_field_update_bits(scodec->reg_adc_fifoc,
502                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS),
503                                    0);
504
505                 /* Fill most significant bits with valid data MSB */
506                 regmap_field_update_bits(scodec->reg_adc_fifoc,
507                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE),
508                                    BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
509
510                 scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
511         }
512
513         return 0;
514 }
515
516 static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
517                                           struct snd_pcm_hw_params *params,
518                                           unsigned int hwrate)
519 {
520         u32 val;
521
522         /* Set DAC sample rate */
523         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
524                            7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
525                            hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
526
527         /* Set the number of channels we want to use */
528         if (params_channels(params) == 1)
529                 val = BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN);
530         else
531                 val = 0;
532
533         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
534                            BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
535                            val);
536
537         /* Set the number of sample bits to either 16 or 24 bits */
538         if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
539                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
540                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
541                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
542
543                 /* Set TX FIFO mode to padding the LSBs with 0 */
544                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
545                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
546                                    0);
547
548                 scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
549         } else {
550                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
551                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
552                                    0);
553
554                 /* Set TX FIFO mode to repeat the MSB */
555                 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
556                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
557                                    BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
558
559                 scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
560         }
561
562         return 0;
563 }
564
565 static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
566                                  struct snd_pcm_hw_params *params,
567                                  struct snd_soc_dai *dai)
568 {
569         struct snd_soc_pcm_runtime *rtd = substream->private_data;
570         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
571         unsigned long clk_freq;
572         int ret, hwrate;
573
574         clk_freq = sun4i_codec_get_mod_freq(params);
575         if (!clk_freq)
576                 return -EINVAL;
577
578         ret = clk_set_rate(scodec->clk_module, clk_freq);
579         if (ret)
580                 return ret;
581
582         hwrate = sun4i_codec_get_hw_rate(params);
583         if (hwrate < 0)
584                 return hwrate;
585
586         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
587                 return sun4i_codec_hw_params_playback(scodec, params,
588                                                       hwrate);
589
590         return sun4i_codec_hw_params_capture(scodec, params,
591                                              hwrate);
592 }
593
594
595 static unsigned int sun4i_codec_src_rates[] = {
596         8000, 11025, 12000, 16000, 22050, 24000, 32000,
597         44100, 48000, 96000, 192000
598 };
599
600
601 static struct snd_pcm_hw_constraint_list sun4i_codec_constraints = {
602         .count  = ARRAY_SIZE(sun4i_codec_src_rates),
603         .list   = sun4i_codec_src_rates,
604 };
605
606
607 static int sun4i_codec_startup(struct snd_pcm_substream *substream,
608                                struct snd_soc_dai *dai)
609 {
610         struct snd_soc_pcm_runtime *rtd = substream->private_data;
611         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
612
613         snd_pcm_hw_constraint_list(substream->runtime, 0,
614                                 SNDRV_PCM_HW_PARAM_RATE, &sun4i_codec_constraints);
615
616         /*
617          * Stop issuing DRQ when we have room for less than 16 samples
618          * in our TX FIFO
619          */
620         regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
621                            3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT,
622                            3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
623
624         return clk_prepare_enable(scodec->clk_module);
625 }
626
627 static void sun4i_codec_shutdown(struct snd_pcm_substream *substream,
628                                  struct snd_soc_dai *dai)
629 {
630         struct snd_soc_pcm_runtime *rtd = substream->private_data;
631         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
632
633         clk_disable_unprepare(scodec->clk_module);
634 }
635
636 static const struct snd_soc_dai_ops sun4i_codec_dai_ops = {
637         .startup        = sun4i_codec_startup,
638         .shutdown       = sun4i_codec_shutdown,
639         .trigger        = sun4i_codec_trigger,
640         .hw_params      = sun4i_codec_hw_params,
641         .prepare        = sun4i_codec_prepare,
642 };
643
644 static struct snd_soc_dai_driver sun4i_codec_dai = {
645         .name   = "Codec",
646         .ops    = &sun4i_codec_dai_ops,
647         .playback = {
648                 .stream_name    = "Codec Playback",
649                 .channels_min   = 1,
650                 .channels_max   = 2,
651                 .rate_min       = 8000,
652                 .rate_max       = 192000,
653                 .rates          = SNDRV_PCM_RATE_CONTINUOUS,
654                 .formats        = SNDRV_PCM_FMTBIT_S16_LE |
655                                   SNDRV_PCM_FMTBIT_S32_LE,
656                 .sig_bits       = 24,
657         },
658         .capture = {
659                 .stream_name    = "Codec Capture",
660                 .channels_min   = 1,
661                 .channels_max   = 2,
662                 .rate_min       = 8000,
663                 .rate_max       = 48000,
664                 .rates          = SNDRV_PCM_RATE_CONTINUOUS,
665                 .formats        = SNDRV_PCM_FMTBIT_S16_LE |
666                                   SNDRV_PCM_FMTBIT_S32_LE,
667                 .sig_bits       = 24,
668         },
669 };
670
671 /*** sun4i Codec ***/
672 static const struct snd_kcontrol_new sun4i_codec_pa_mute =
673         SOC_DAPM_SINGLE("Switch", SUN4I_CODEC_DAC_ACTL,
674                         SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
675
676 static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
677 static DECLARE_TLV_DB_SCALE(sun4i_codec_micin_loopback_gain_scale, -450, 150,
678                             0);
679
680 static const struct snd_kcontrol_new sun4i_codec_controls[] = {
681         SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
682                        SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
683                        sun4i_codec_pa_volume_scale),
684         SOC_SINGLE_TLV("Mic Playback Volume", SUN4I_CODEC_DAC_ACTL,
685                        SUN4I_CODEC_DAC_ACTL_MICG, 7, 0,
686                        sun4i_codec_micin_loopback_gain_scale),
687 };
688
689 static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = {
690         SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
691                         SUN4I_CODEC_DAC_ACTL_LDACLMIXS, 1, 0),
692 };
693
694 static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = {
695         SOC_DAPM_SINGLE("Right DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
696                         SUN4I_CODEC_DAC_ACTL_RDACRMIXS, 1, 0),
697         SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
698                         SUN4I_CODEC_DAC_ACTL_LDACRMIXS, 1, 0),
699 };
700
701 static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = {
702         SOC_DAPM_SINGLE("DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
703                         SUN4I_CODEC_DAC_ACTL_DACPAS, 1, 0),
704         SOC_DAPM_SINGLE("Mixer Playback Switch", SUN4I_CODEC_DAC_ACTL,
705                         SUN4I_CODEC_DAC_ACTL_MIXPAS, 1, 0),
706 };
707
708 static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = {
709         /* Digital parts of the ADCs */
710         SND_SOC_DAPM_SUPPLY("ADC", SUN4I_CODEC_ADC_FIFOC,
711                             SUN4I_CODEC_ADC_FIFOC_EN_AD, 0,
712                             NULL, 0),
713
714         /* Digital parts of the DACs */
715         SND_SOC_DAPM_SUPPLY("DAC", SUN4I_CODEC_DAC_DPC,
716                             SUN4I_CODEC_DAC_DPC_EN_DA, 0,
717                             NULL, 0),
718
719         /* Analog parts of the ADCs */
720         SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
721                          SUN4I_CODEC_ADC_ACTL_ADC_L_EN, 0),
722         SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
723                          SUN4I_CODEC_ADC_ACTL_ADC_R_EN, 0),
724
725         /* Analog parts of the DACs */
726         SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
727                          SUN4I_CODEC_DAC_ACTL_DACAENL, 0),
728         SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
729                          SUN4I_CODEC_DAC_ACTL_DACAENR, 0),
730
731         /* Mixers */
732         SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
733                            sun4i_codec_left_mixer_controls,
734                            ARRAY_SIZE(sun4i_codec_left_mixer_controls)),
735         SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
736                            sun4i_codec_right_mixer_controls,
737                            ARRAY_SIZE(sun4i_codec_right_mixer_controls)),
738
739         /* Global Mixer Enable */
740         SND_SOC_DAPM_SUPPLY("Mixer Enable", SUN4I_CODEC_DAC_ACTL,
741                             SUN4I_CODEC_DAC_ACTL_MIXEN, 0, NULL, 0),
742
743         /* VMIC */
744         SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL,
745                             SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
746
747         /* Mic Pre-Amplifiers */
748         SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
749                          SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0),
750         SND_SOC_DAPM_PGA("MIC2 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
751                          SUN4I_CODEC_ADC_ACTL_PREG2EN, 0, NULL, 0),
752
753         /* Power Amplifier */
754         SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL,
755                            SUN4I_CODEC_ADC_ACTL_PA_EN, 0,
756                            sun4i_codec_pa_mixer_controls,
757                            ARRAY_SIZE(sun4i_codec_pa_mixer_controls)),
758         SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0,
759                             &sun4i_codec_pa_mute),
760
761         SND_SOC_DAPM_INPUT("Mic1"),
762         SND_SOC_DAPM_INPUT("Mic2"),
763
764         SND_SOC_DAPM_OUTPUT("HP Right"),
765         SND_SOC_DAPM_OUTPUT("HP Left"),
766 };
767
768 static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
769         /* Left ADC / DAC Routes */
770         { "Left ADC", NULL, "ADC" },
771         { "Left DAC", NULL, "DAC" },
772
773         /* Right ADC / DAC Routes */
774         { "Right ADC", NULL, "ADC" },
775         { "Right DAC", NULL, "DAC" },
776
777         /* Right Mixer Routes */
778         { "Right Mixer", NULL, "Mixer Enable" },
779         { "Right Mixer", "Left DAC Playback Switch", "Left DAC" },
780         { "Right Mixer", "Right DAC Playback Switch", "Right DAC" },
781
782         /* Left Mixer Routes */
783         { "Left Mixer", NULL, "Mixer Enable" },
784         { "Left Mixer", "Left DAC Playback Switch", "Left DAC" },
785
786         /* Power Amplifier Routes */
787         { "Power Amplifier", "Mixer Playback Switch", "Left Mixer" },
788         { "Power Amplifier", "Mixer Playback Switch", "Right Mixer" },
789         { "Power Amplifier", "DAC Playback Switch", "Left DAC" },
790         { "Power Amplifier", "DAC Playback Switch", "Right DAC" },
791
792         /* Headphone Output Routes */
793         { "Power Amplifier Mute", "Switch", "Power Amplifier" },
794         { "HP Right", NULL, "Power Amplifier Mute" },
795         { "HP Left", NULL, "Power Amplifier Mute" },
796
797         /* Mic1 Routes */
798         { "Left ADC", NULL, "MIC1 Pre-Amplifier" },
799         { "Right ADC", NULL, "MIC1 Pre-Amplifier" },
800         { "MIC1 Pre-Amplifier", NULL, "Mic1"},
801         { "Mic1", NULL, "VMIC" },
802
803         /* Mic2 Routes */
804         { "Left ADC", NULL, "MIC2 Pre-Amplifier" },
805         { "Right ADC", NULL, "MIC2 Pre-Amplifier" },
806         { "MIC2 Pre-Amplifier", NULL, "Mic2"},
807         { "Mic2", NULL, "VMIC" },
808 };
809
810 static const struct snd_soc_component_driver sun4i_codec_codec = {
811         .controls               = sun4i_codec_controls,
812         .num_controls           = ARRAY_SIZE(sun4i_codec_controls),
813         .dapm_widgets           = sun4i_codec_codec_dapm_widgets,
814         .num_dapm_widgets       = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
815         .dapm_routes            = sun4i_codec_codec_dapm_routes,
816         .num_dapm_routes        = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
817         .idle_bias_on           = 1,
818         .use_pmdown_time        = 1,
819         .endianness             = 1,
820         .non_legacy_dai_naming  = 1,
821 };
822
823 /*** sun6i Codec ***/
824
825 /* mixer controls */
826 static const struct snd_kcontrol_new sun6i_codec_mixer_controls[] = {
827         SOC_DAPM_DOUBLE("DAC Playback Switch",
828                         SUN6I_CODEC_OM_DACA_CTRL,
829                         SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL,
830                         SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR, 1, 0),
831         SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
832                         SUN6I_CODEC_OM_DACA_CTRL,
833                         SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR,
834                         SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL, 1, 0),
835         SOC_DAPM_DOUBLE("Line In Playback Switch",
836                         SUN6I_CODEC_OM_DACA_CTRL,
837                         SUN6I_CODEC_OM_DACA_CTRL_LMIX_LINEINL,
838                         SUN6I_CODEC_OM_DACA_CTRL_RMIX_LINEINR, 1, 0),
839         SOC_DAPM_DOUBLE("Mic1 Playback Switch",
840                         SUN6I_CODEC_OM_DACA_CTRL,
841                         SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC1,
842                         SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC1, 1, 0),
843         SOC_DAPM_DOUBLE("Mic2 Playback Switch",
844                         SUN6I_CODEC_OM_DACA_CTRL,
845                         SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC2,
846                         SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2, 1, 0),
847 };
848
849 /* ADC mixer controls */
850 static const struct snd_kcontrol_new sun6i_codec_adc_mixer_controls[] = {
851         SOC_DAPM_DOUBLE("Mixer Capture Switch",
852                         SUN6I_CODEC_ADC_ACTL,
853                         SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL,
854                         SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR, 1, 0),
855         SOC_DAPM_DOUBLE("Mixer Reversed Capture Switch",
856                         SUN6I_CODEC_ADC_ACTL,
857                         SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR,
858                         SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL, 1, 0),
859         SOC_DAPM_DOUBLE("Line In Capture Switch",
860                         SUN6I_CODEC_ADC_ACTL,
861                         SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL,
862                         SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR, 1, 0),
863         SOC_DAPM_DOUBLE("Mic1 Capture Switch",
864                         SUN6I_CODEC_ADC_ACTL,
865                         SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1,
866                         SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1, 1, 0),
867         SOC_DAPM_DOUBLE("Mic2 Capture Switch",
868                         SUN6I_CODEC_ADC_ACTL,
869                         SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2,
870                         SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2, 1, 0),
871 };
872
873 /* headphone controls */
874 static const char * const sun6i_codec_hp_src_enum_text[] = {
875         "DAC", "Mixer",
876 };
877
878 static SOC_ENUM_DOUBLE_DECL(sun6i_codec_hp_src_enum,
879                             SUN6I_CODEC_OM_DACA_CTRL,
880                             SUN6I_CODEC_OM_DACA_CTRL_LHPIS,
881                             SUN6I_CODEC_OM_DACA_CTRL_RHPIS,
882                             sun6i_codec_hp_src_enum_text);
883
884 static const struct snd_kcontrol_new sun6i_codec_hp_src[] = {
885         SOC_DAPM_ENUM("Headphone Source Playback Route",
886                       sun6i_codec_hp_src_enum),
887 };
888
889 /* microphone controls */
890 static const char * const sun6i_codec_mic2_src_enum_text[] = {
891         "Mic2", "Mic3",
892 };
893
894 static SOC_ENUM_SINGLE_DECL(sun6i_codec_mic2_src_enum,
895                             SUN6I_CODEC_MIC_CTRL,
896                             SUN6I_CODEC_MIC_CTRL_MIC2SLT,
897                             sun6i_codec_mic2_src_enum_text);
898
899 static const struct snd_kcontrol_new sun6i_codec_mic2_src[] = {
900         SOC_DAPM_ENUM("Mic2 Amplifier Source Route",
901                       sun6i_codec_mic2_src_enum),
902 };
903
904 /* line out controls */
905 static const char * const sun6i_codec_lineout_src_enum_text[] = {
906         "Stereo", "Mono Differential",
907 };
908
909 static SOC_ENUM_DOUBLE_DECL(sun6i_codec_lineout_src_enum,
910                             SUN6I_CODEC_MIC_CTRL,
911                             SUN6I_CODEC_MIC_CTRL_LINEOUTLSRC,
912                             SUN6I_CODEC_MIC_CTRL_LINEOUTRSRC,
913                             sun6i_codec_lineout_src_enum_text);
914
915 static const struct snd_kcontrol_new sun6i_codec_lineout_src[] = {
916         SOC_DAPM_ENUM("Line Out Source Playback Route",
917                       sun6i_codec_lineout_src_enum),
918 };
919
920 /* volume / mute controls */
921 static const DECLARE_TLV_DB_SCALE(sun6i_codec_dvol_scale, -7308, 116, 0);
922 static const DECLARE_TLV_DB_SCALE(sun6i_codec_hp_vol_scale, -6300, 100, 1);
923 static const DECLARE_TLV_DB_SCALE(sun6i_codec_out_mixer_pregain_scale,
924                                   -450, 150, 0);
925 static const DECLARE_TLV_DB_RANGE(sun6i_codec_lineout_vol_scale,
926         0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
927         2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
928 );
929 static const DECLARE_TLV_DB_RANGE(sun6i_codec_mic_gain_scale,
930         0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
931         1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
932 );
933
934 static const struct snd_kcontrol_new sun6i_codec_codec_widgets[] = {
935         SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
936                        SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
937                        sun6i_codec_dvol_scale),
938         SOC_SINGLE_TLV("Headphone Playback Volume",
939                        SUN6I_CODEC_OM_DACA_CTRL,
940                        SUN6I_CODEC_OM_DACA_CTRL_HPVOL, 0x3f, 0,
941                        sun6i_codec_hp_vol_scale),
942         SOC_SINGLE_TLV("Line Out Playback Volume",
943                        SUN6I_CODEC_MIC_CTRL,
944                        SUN6I_CODEC_MIC_CTRL_LINEOUTVC, 0x1f, 0,
945                        sun6i_codec_lineout_vol_scale),
946         SOC_DOUBLE("Headphone Playback Switch",
947                    SUN6I_CODEC_OM_DACA_CTRL,
948                    SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE,
949                    SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE, 1, 0),
950         SOC_DOUBLE("Line Out Playback Switch",
951                    SUN6I_CODEC_MIC_CTRL,
952                    SUN6I_CODEC_MIC_CTRL_LINEOUTLEN,
953                    SUN6I_CODEC_MIC_CTRL_LINEOUTREN, 1, 0),
954         /* Mixer pre-gains */
955         SOC_SINGLE_TLV("Line In Playback Volume",
956                        SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_LINEING,
957                        0x7, 0, sun6i_codec_out_mixer_pregain_scale),
958         SOC_SINGLE_TLV("Mic1 Playback Volume",
959                        SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_MIC1G,
960                        0x7, 0, sun6i_codec_out_mixer_pregain_scale),
961         SOC_SINGLE_TLV("Mic2 Playback Volume",
962                        SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_MIC2G,
963                        0x7, 0, sun6i_codec_out_mixer_pregain_scale),
964
965         /* Microphone Amp boost gains */
966         SOC_SINGLE_TLV("Mic1 Boost Volume", SUN6I_CODEC_MIC_CTRL,
967                        SUN6I_CODEC_MIC_CTRL_MIC1BOOST, 0x7, 0,
968                        sun6i_codec_mic_gain_scale),
969         SOC_SINGLE_TLV("Mic2 Boost Volume", SUN6I_CODEC_MIC_CTRL,
970                        SUN6I_CODEC_MIC_CTRL_MIC2BOOST, 0x7, 0,
971                        sun6i_codec_mic_gain_scale),
972         SOC_DOUBLE_TLV("ADC Capture Volume",
973                        SUN6I_CODEC_ADC_ACTL, SUN6I_CODEC_ADC_ACTL_ADCLG,
974                        SUN6I_CODEC_ADC_ACTL_ADCRG, 0x7, 0,
975                        sun6i_codec_out_mixer_pregain_scale),
976 };
977
978 static const struct snd_soc_dapm_widget sun6i_codec_codec_dapm_widgets[] = {
979         /* Microphone inputs */
980         SND_SOC_DAPM_INPUT("MIC1"),
981         SND_SOC_DAPM_INPUT("MIC2"),
982         SND_SOC_DAPM_INPUT("MIC3"),
983
984         /* Microphone Bias */
985         SND_SOC_DAPM_SUPPLY("HBIAS", SUN6I_CODEC_MIC_CTRL,
986                             SUN6I_CODEC_MIC_CTRL_HBIASEN, 0, NULL, 0),
987         SND_SOC_DAPM_SUPPLY("MBIAS", SUN6I_CODEC_MIC_CTRL,
988                             SUN6I_CODEC_MIC_CTRL_MBIASEN, 0, NULL, 0),
989
990         /* Mic input path */
991         SND_SOC_DAPM_MUX("Mic2 Amplifier Source Route",
992                          SND_SOC_NOPM, 0, 0, sun6i_codec_mic2_src),
993         SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN6I_CODEC_MIC_CTRL,
994                          SUN6I_CODEC_MIC_CTRL_MIC1AMPEN, 0, NULL, 0),
995         SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN6I_CODEC_MIC_CTRL,
996                          SUN6I_CODEC_MIC_CTRL_MIC2AMPEN, 0, NULL, 0),
997
998         /* Line In */
999         SND_SOC_DAPM_INPUT("LINEIN"),
1000
1001         /* Digital parts of the ADCs */
1002         SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
1003                             SUN6I_CODEC_ADC_FIFOC_EN_AD, 0,
1004                             NULL, 0),
1005
1006         /* Analog parts of the ADCs */
1007         SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
1008                          SUN6I_CODEC_ADC_ACTL_ADCLEN, 0),
1009         SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
1010                          SUN6I_CODEC_ADC_ACTL_ADCREN, 0),
1011
1012         /* ADC Mixers */
1013         SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
1014                         sun6i_codec_adc_mixer_controls),
1015         SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
1016                         sun6i_codec_adc_mixer_controls),
1017
1018         /* Digital parts of the DACs */
1019         SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1020                             SUN4I_CODEC_DAC_DPC_EN_DA, 0,
1021                             NULL, 0),
1022
1023         /* Analog parts of the DACs */
1024         SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
1025                          SUN6I_CODEC_OM_DACA_CTRL,
1026                          SUN6I_CODEC_OM_DACA_CTRL_DACALEN, 0),
1027         SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
1028                          SUN6I_CODEC_OM_DACA_CTRL,
1029                          SUN6I_CODEC_OM_DACA_CTRL_DACAREN, 0),
1030
1031         /* Mixers */
1032         SOC_MIXER_ARRAY("Left Mixer", SUN6I_CODEC_OM_DACA_CTRL,
1033                         SUN6I_CODEC_OM_DACA_CTRL_LMIXEN, 0,
1034                         sun6i_codec_mixer_controls),
1035         SOC_MIXER_ARRAY("Right Mixer", SUN6I_CODEC_OM_DACA_CTRL,
1036                         SUN6I_CODEC_OM_DACA_CTRL_RMIXEN, 0,
1037                         sun6i_codec_mixer_controls),
1038
1039         /* Headphone output path */
1040         SND_SOC_DAPM_MUX("Headphone Source Playback Route",
1041                          SND_SOC_NOPM, 0, 0, sun6i_codec_hp_src),
1042         SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN6I_CODEC_OM_PA_CTRL,
1043                              SUN6I_CODEC_OM_PA_CTRL_HPPAEN, 0, NULL, 0),
1044         SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN6I_CODEC_OM_PA_CTRL,
1045                             SUN6I_CODEC_OM_PA_CTRL_COMPTEN, 0, NULL, 0),
1046         SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN6I_CODEC_OM_PA_CTRL,
1047                          SUN6I_CODEC_OM_PA_CTRL_HPCOM_CTL, 0x3, 0x3, 0),
1048         SND_SOC_DAPM_OUTPUT("HP"),
1049
1050         /* Line Out path */
1051         SND_SOC_DAPM_MUX("Line Out Source Playback Route",
1052                          SND_SOC_NOPM, 0, 0, sun6i_codec_lineout_src),
1053         SND_SOC_DAPM_OUTPUT("LINEOUT"),
1054 };
1055
1056 static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
1057         /* DAC Routes */
1058         { "Left DAC", NULL, "DAC Enable" },
1059         { "Right DAC", NULL, "DAC Enable" },
1060
1061         /* Microphone Routes */
1062         { "Mic1 Amplifier", NULL, "MIC1"},
1063         { "Mic2 Amplifier Source Route", "Mic2", "MIC2" },
1064         { "Mic2 Amplifier Source Route", "Mic3", "MIC3" },
1065         { "Mic2 Amplifier", NULL, "Mic2 Amplifier Source Route"},
1066
1067         /* Left Mixer Routes */
1068         { "Left Mixer", "DAC Playback Switch", "Left DAC" },
1069         { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
1070         { "Left Mixer", "Line In Playback Switch", "LINEIN" },
1071         { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
1072         { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
1073
1074         /* Right Mixer Routes */
1075         { "Right Mixer", "DAC Playback Switch", "Right DAC" },
1076         { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
1077         { "Right Mixer", "Line In Playback Switch", "LINEIN" },
1078         { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
1079         { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
1080
1081         /* Left ADC Mixer Routes */
1082         { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
1083         { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
1084         { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
1085         { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
1086         { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
1087
1088         /* Right ADC Mixer Routes */
1089         { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
1090         { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
1091         { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
1092         { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
1093         { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
1094
1095         /* Headphone Routes */
1096         { "Headphone Source Playback Route", "DAC", "Left DAC" },
1097         { "Headphone Source Playback Route", "DAC", "Right DAC" },
1098         { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
1099         { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
1100         { "Headphone Amp", NULL, "Headphone Source Playback Route" },
1101         { "HP", NULL, "Headphone Amp" },
1102         { "HPCOM", NULL, "HPCOM Protection" },
1103
1104         /* Line Out Routes */
1105         { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
1106         { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
1107         { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
1108         { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
1109         { "LINEOUT", NULL, "Line Out Source Playback Route" },
1110
1111         /* ADC Routes */
1112         { "Left ADC", NULL, "ADC Enable" },
1113         { "Right ADC", NULL, "ADC Enable" },
1114         { "Left ADC", NULL, "Left ADC Mixer" },
1115         { "Right ADC", NULL, "Right ADC Mixer" },
1116 };
1117
1118 static const struct snd_soc_component_driver sun6i_codec_codec = {
1119         .controls               = sun6i_codec_codec_widgets,
1120         .num_controls           = ARRAY_SIZE(sun6i_codec_codec_widgets),
1121         .dapm_widgets           = sun6i_codec_codec_dapm_widgets,
1122         .num_dapm_widgets       = ARRAY_SIZE(sun6i_codec_codec_dapm_widgets),
1123         .dapm_routes            = sun6i_codec_codec_dapm_routes,
1124         .num_dapm_routes        = ARRAY_SIZE(sun6i_codec_codec_dapm_routes),
1125         .idle_bias_on           = 1,
1126         .use_pmdown_time        = 1,
1127         .endianness             = 1,
1128         .non_legacy_dai_naming  = 1,
1129 };
1130
1131 /* sun8i A23 codec */
1132 static const struct snd_kcontrol_new sun8i_a23_codec_codec_controls[] = {
1133         SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1134                        SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1135                        sun6i_codec_dvol_scale),
1136 };
1137
1138 static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = {
1139         /* Digital parts of the ADCs */
1140         SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
1141                             SUN6I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0),
1142         /* Digital parts of the DACs */
1143         SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1144                             SUN4I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0),
1145
1146 };
1147
1148 static const struct snd_soc_component_driver sun8i_a23_codec_codec = {
1149         .controls               = sun8i_a23_codec_codec_controls,
1150         .num_controls           = ARRAY_SIZE(sun8i_a23_codec_codec_controls),
1151         .dapm_widgets           = sun8i_a23_codec_codec_widgets,
1152         .num_dapm_widgets       = ARRAY_SIZE(sun8i_a23_codec_codec_widgets),
1153         .idle_bias_on           = 1,
1154         .use_pmdown_time        = 1,
1155         .endianness             = 1,
1156         .non_legacy_dai_naming  = 1,
1157 };
1158
1159 static const struct snd_soc_component_driver sun4i_codec_component = {
1160         .name = "sun4i-codec",
1161 };
1162
1163 #define SUN4I_CODEC_RATES       SNDRV_PCM_RATE_CONTINUOUS
1164 #define SUN4I_CODEC_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE | \
1165                                  SNDRV_PCM_FMTBIT_S32_LE)
1166
1167 static int sun4i_codec_dai_probe(struct snd_soc_dai *dai)
1168 {
1169         struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
1170         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
1171
1172         snd_soc_dai_init_dma_data(dai, &scodec->playback_dma_data,
1173                                   &scodec->capture_dma_data);
1174
1175         return 0;
1176 }
1177
1178 static struct snd_soc_dai_driver dummy_cpu_dai = {
1179         .name   = "sun4i-codec-cpu-dai",
1180         .probe  = sun4i_codec_dai_probe,
1181         .playback = {
1182                 .stream_name    = "Playback",
1183                 .channels_min   = 1,
1184                 .channels_max   = 2,
1185                 .rates          = SUN4I_CODEC_RATES,
1186                 .formats        = SUN4I_CODEC_FORMATS,
1187                 .sig_bits       = 24,
1188         },
1189         .capture = {
1190                 .stream_name    = "Capture",
1191                 .channels_min   = 1,
1192                 .channels_max   = 2,
1193                 .rates          = SUN4I_CODEC_RATES,
1194                 .formats        = SUN4I_CODEC_FORMATS,
1195                 .sig_bits       = 24,
1196          },
1197 };
1198
1199 static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
1200                                                         int *num_links)
1201 {
1202         struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link),
1203                                                      GFP_KERNEL);
1204         if (!link)
1205                 return NULL;
1206
1207         link->name              = "cdc";
1208         link->stream_name       = "CDC PCM";
1209         link->codec_dai_name    = "Codec";
1210         link->cpu_dai_name      = dev_name(dev);
1211         link->codec_name        = dev_name(dev);
1212         link->platform_name     = dev_name(dev);
1213         link->dai_fmt           = SND_SOC_DAIFMT_I2S;
1214
1215         *num_links = 1;
1216
1217         return link;
1218 };
1219
1220 static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
1221                                  struct snd_kcontrol *k, int event)
1222 {
1223         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
1224
1225         gpiod_set_value_cansleep(scodec->gpio_pa,
1226                                  !!SND_SOC_DAPM_EVENT_ON(event));
1227
1228         return 0;
1229 }
1230
1231 static const struct snd_soc_dapm_widget sun4i_codec_card_dapm_widgets[] = {
1232         SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1233 };
1234
1235 static const struct snd_soc_dapm_route sun4i_codec_card_dapm_routes[] = {
1236         { "Speaker", NULL, "HP Right" },
1237         { "Speaker", NULL, "HP Left" },
1238 };
1239
1240 static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
1241 {
1242         struct snd_soc_card *card;
1243
1244         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1245         if (!card)
1246                 return ERR_PTR(-ENOMEM);
1247
1248         card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1249         if (!card->dai_link)
1250                 return ERR_PTR(-ENOMEM);
1251
1252         card->dev               = dev;
1253         card->name              = "sun4i-codec";
1254         card->dapm_widgets      = sun4i_codec_card_dapm_widgets;
1255         card->num_dapm_widgets  = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
1256         card->dapm_routes       = sun4i_codec_card_dapm_routes;
1257         card->num_dapm_routes   = ARRAY_SIZE(sun4i_codec_card_dapm_routes);
1258
1259         return card;
1260 };
1261
1262 static const struct snd_soc_dapm_widget sun6i_codec_card_dapm_widgets[] = {
1263         SND_SOC_DAPM_HP("Headphone", NULL),
1264         SND_SOC_DAPM_LINE("Line In", NULL),
1265         SND_SOC_DAPM_LINE("Line Out", NULL),
1266         SND_SOC_DAPM_MIC("Headset Mic", NULL),
1267         SND_SOC_DAPM_MIC("Mic", NULL),
1268         SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1269 };
1270
1271 static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
1272 {
1273         struct snd_soc_card *card;
1274         int ret;
1275
1276         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1277         if (!card)
1278                 return ERR_PTR(-ENOMEM);
1279
1280         card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1281         if (!card->dai_link)
1282                 return ERR_PTR(-ENOMEM);
1283
1284         card->dev               = dev;
1285         card->name              = "A31 Audio Codec";
1286         card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1287         card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1288         card->fully_routed      = true;
1289
1290         ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1291         if (ret)
1292                 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1293
1294         return card;
1295 };
1296
1297 /* Connect digital side enables to analog side widgets */
1298 static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = {
1299         /* ADC Routes */
1300         { "Left ADC", NULL, "ADC Enable" },
1301         { "Right ADC", NULL, "ADC Enable" },
1302         { "Codec Capture", NULL, "Left ADC" },
1303         { "Codec Capture", NULL, "Right ADC" },
1304
1305         /* DAC Routes */
1306         { "Left DAC", NULL, "DAC Enable" },
1307         { "Right DAC", NULL, "DAC Enable" },
1308         { "Left DAC", NULL, "Codec Playback" },
1309         { "Right DAC", NULL, "Codec Playback" },
1310 };
1311
1312 static struct snd_soc_aux_dev aux_dev = {
1313         .name = "Codec Analog Controls",
1314 };
1315
1316 static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
1317 {
1318         struct snd_soc_card *card;
1319         int ret;
1320
1321         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1322         if (!card)
1323                 return ERR_PTR(-ENOMEM);
1324
1325         aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
1326                                                  "allwinner,codec-analog-controls",
1327                                                  0);
1328         if (!aux_dev.codec_of_node) {
1329                 dev_err(dev, "Can't find analog controls for codec.\n");
1330                 return ERR_PTR(-EINVAL);
1331         };
1332
1333         card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1334         if (!card->dai_link)
1335                 return ERR_PTR(-ENOMEM);
1336
1337         card->dev               = dev;
1338         card->name              = "A23 Audio Codec";
1339         card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1340         card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1341         card->dapm_routes       = sun8i_codec_card_routes;
1342         card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1343         card->aux_dev           = &aux_dev;
1344         card->num_aux_devs      = 1;
1345         card->fully_routed      = true;
1346
1347         ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1348         if (ret)
1349                 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1350
1351         return card;
1352 };
1353
1354 static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
1355 {
1356         struct snd_soc_card *card;
1357         int ret;
1358
1359         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1360         if (!card)
1361                 return ERR_PTR(-ENOMEM);
1362
1363         aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
1364                                                  "allwinner,codec-analog-controls",
1365                                                  0);
1366         if (!aux_dev.codec_of_node) {
1367                 dev_err(dev, "Can't find analog controls for codec.\n");
1368                 return ERR_PTR(-EINVAL);
1369         };
1370
1371         card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1372         if (!card->dai_link)
1373                 return ERR_PTR(-ENOMEM);
1374
1375         card->dev               = dev;
1376         card->name              = "H3 Audio Codec";
1377         card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1378         card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1379         card->dapm_routes       = sun8i_codec_card_routes;
1380         card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1381         card->aux_dev           = &aux_dev;
1382         card->num_aux_devs      = 1;
1383         card->fully_routed      = true;
1384
1385         ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1386         if (ret)
1387                 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1388
1389         return card;
1390 };
1391
1392 static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev)
1393 {
1394         struct snd_soc_card *card;
1395         int ret;
1396
1397         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1398         if (!card)
1399                 return ERR_PTR(-ENOMEM);
1400
1401         aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
1402                                                  "allwinner,codec-analog-controls",
1403                                                  0);
1404         if (!aux_dev.codec_of_node) {
1405                 dev_err(dev, "Can't find analog controls for codec.\n");
1406                 return ERR_PTR(-EINVAL);
1407         };
1408
1409         card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1410         if (!card->dai_link)
1411                 return ERR_PTR(-ENOMEM);
1412
1413         card->dev               = dev;
1414         card->name              = "V3s Audio Codec";
1415         card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1416         card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1417         card->dapm_routes       = sun8i_codec_card_routes;
1418         card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1419         card->aux_dev           = &aux_dev;
1420         card->num_aux_devs      = 1;
1421         card->fully_routed      = true;
1422
1423         ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1424         if (ret)
1425                 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1426
1427         return card;
1428 };
1429
1430 static const struct regmap_config sun4i_codec_regmap_config = {
1431         .reg_bits       = 32,
1432         .reg_stride     = 4,
1433         .val_bits       = 32,
1434         .max_register   = SUN4I_CODEC_ADC_RXCNT,
1435 };
1436
1437 static const struct regmap_config sun6i_codec_regmap_config = {
1438         .reg_bits       = 32,
1439         .reg_stride     = 4,
1440         .val_bits       = 32,
1441         .max_register   = SUN6I_CODEC_HMIC_DATA,
1442 };
1443
1444 static const struct regmap_config sun7i_codec_regmap_config = {
1445         .reg_bits       = 32,
1446         .reg_stride     = 4,
1447         .val_bits       = 32,
1448         .max_register   = SUN7I_CODEC_AC_MIC_PHONE_CAL,
1449 };
1450
1451 static const struct regmap_config sun8i_a23_codec_regmap_config = {
1452         .reg_bits       = 32,
1453         .reg_stride     = 4,
1454         .val_bits       = 32,
1455         .max_register   = SUN8I_A23_CODEC_ADC_RXCNT,
1456 };
1457
1458 static const struct regmap_config sun8i_h3_codec_regmap_config = {
1459         .reg_bits       = 32,
1460         .reg_stride     = 4,
1461         .val_bits       = 32,
1462         .max_register   = SUN8I_H3_CODEC_ADC_DBG,
1463 };
1464
1465 static const struct regmap_config sun8i_v3s_codec_regmap_config = {
1466         .reg_bits       = 32,
1467         .reg_stride     = 4,
1468         .val_bits       = 32,
1469         .max_register   = SUN8I_H3_CODEC_ADC_DBG,
1470 };
1471
1472 struct sun4i_codec_quirks {
1473         const struct regmap_config *regmap_config;
1474         const struct snd_soc_component_driver *codec;
1475         struct snd_soc_card * (*create_card)(struct device *dev);
1476         struct reg_field reg_adc_fifoc; /* used for regmap_field */
1477         unsigned int reg_dac_txdata;    /* TX FIFO offset for DMA config */
1478         unsigned int reg_adc_rxdata;    /* RX FIFO offset for DMA config */
1479         bool has_reset;
1480 };
1481
1482 static const struct sun4i_codec_quirks sun4i_codec_quirks = {
1483         .regmap_config  = &sun4i_codec_regmap_config,
1484         .codec          = &sun4i_codec_codec,
1485         .create_card    = sun4i_codec_create_card,
1486         .reg_adc_fifoc  = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
1487         .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
1488         .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
1489 };
1490
1491 static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
1492         .regmap_config  = &sun6i_codec_regmap_config,
1493         .codec          = &sun6i_codec_codec,
1494         .create_card    = sun6i_codec_create_card,
1495         .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
1496         .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
1497         .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
1498         .has_reset      = true,
1499 };
1500
1501 static const struct sun4i_codec_quirks sun7i_codec_quirks = {
1502         .regmap_config  = &sun7i_codec_regmap_config,
1503         .codec          = &sun4i_codec_codec,
1504         .create_card    = sun4i_codec_create_card,
1505         .reg_adc_fifoc  = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
1506         .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
1507         .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
1508 };
1509
1510 static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
1511         .regmap_config  = &sun8i_a23_codec_regmap_config,
1512         .codec          = &sun8i_a23_codec_codec,
1513         .create_card    = sun8i_a23_codec_create_card,
1514         .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
1515         .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
1516         .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
1517         .has_reset      = true,
1518 };
1519
1520 static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
1521         .regmap_config  = &sun8i_h3_codec_regmap_config,
1522         /*
1523          * TODO Share the codec structure with A23 for now.
1524          * This should be split out when adding digital audio
1525          * processing support for the H3.
1526          */
1527         .codec          = &sun8i_a23_codec_codec,
1528         .create_card    = sun8i_h3_codec_create_card,
1529         .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
1530         .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
1531         .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
1532         .has_reset      = true,
1533 };
1534
1535 static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = {
1536         .regmap_config  = &sun8i_v3s_codec_regmap_config,
1537         /*
1538          * TODO The codec structure should be split out, like
1539          * H3, when adding digital audio processing support.
1540          */
1541         .codec          = &sun8i_a23_codec_codec,
1542         .create_card    = sun8i_v3s_codec_create_card,
1543         .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
1544         .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
1545         .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
1546         .has_reset      = true,
1547 };
1548
1549 static const struct of_device_id sun4i_codec_of_match[] = {
1550         {
1551                 .compatible = "allwinner,sun4i-a10-codec",
1552                 .data = &sun4i_codec_quirks,
1553         },
1554         {
1555                 .compatible = "allwinner,sun6i-a31-codec",
1556                 .data = &sun6i_a31_codec_quirks,
1557         },
1558         {
1559                 .compatible = "allwinner,sun7i-a20-codec",
1560                 .data = &sun7i_codec_quirks,
1561         },
1562         {
1563                 .compatible = "allwinner,sun8i-a23-codec",
1564                 .data = &sun8i_a23_codec_quirks,
1565         },
1566         {
1567                 .compatible = "allwinner,sun8i-h3-codec",
1568                 .data = &sun8i_h3_codec_quirks,
1569         },
1570         {
1571                 .compatible = "allwinner,sun8i-v3s-codec",
1572                 .data = &sun8i_v3s_codec_quirks,
1573         },
1574         {}
1575 };
1576 MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
1577
1578 static int sun4i_codec_probe(struct platform_device *pdev)
1579 {
1580         struct snd_soc_card *card;
1581         struct sun4i_codec *scodec;
1582         const struct sun4i_codec_quirks *quirks;
1583         struct resource *res;
1584         void __iomem *base;
1585         int ret;
1586
1587         scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
1588         if (!scodec)
1589                 return -ENOMEM;
1590
1591         scodec->dev = &pdev->dev;
1592
1593         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1594         base = devm_ioremap_resource(&pdev->dev, res);
1595         if (IS_ERR(base)) {
1596                 dev_err(&pdev->dev, "Failed to map the registers\n");
1597                 return PTR_ERR(base);
1598         }
1599
1600         quirks = of_device_get_match_data(&pdev->dev);
1601         if (quirks == NULL) {
1602                 dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
1603                 return -ENODEV;
1604         }
1605
1606         scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
1607                                                quirks->regmap_config);
1608         if (IS_ERR(scodec->regmap)) {
1609                 dev_err(&pdev->dev, "Failed to create our regmap\n");
1610                 return PTR_ERR(scodec->regmap);
1611         }
1612
1613         /* Get the clocks from the DT */
1614         scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
1615         if (IS_ERR(scodec->clk_apb)) {
1616                 dev_err(&pdev->dev, "Failed to get the APB clock\n");
1617                 return PTR_ERR(scodec->clk_apb);
1618         }
1619
1620         scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
1621         if (IS_ERR(scodec->clk_module)) {
1622                 dev_err(&pdev->dev, "Failed to get the module clock\n");
1623                 return PTR_ERR(scodec->clk_module);
1624         }
1625
1626         if (quirks->has_reset) {
1627                 scodec->rst = devm_reset_control_get_exclusive(&pdev->dev,
1628                                                                NULL);
1629                 if (IS_ERR(scodec->rst)) {
1630                         dev_err(&pdev->dev, "Failed to get reset control\n");
1631                         return PTR_ERR(scodec->rst);
1632                 }
1633         }
1634
1635         scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
1636                                                   GPIOD_OUT_LOW);
1637         if (IS_ERR(scodec->gpio_pa)) {
1638                 ret = PTR_ERR(scodec->gpio_pa);
1639                 if (ret != -EPROBE_DEFER)
1640                         dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
1641                 return ret;
1642         }
1643
1644         /* reg_field setup */
1645         scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
1646                                                         scodec->regmap,
1647                                                         quirks->reg_adc_fifoc);
1648         if (IS_ERR(scodec->reg_adc_fifoc)) {
1649                 ret = PTR_ERR(scodec->reg_adc_fifoc);
1650                 dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
1651                         ret);
1652                 return ret;
1653         }
1654
1655         /* Enable the bus clock */
1656         if (clk_prepare_enable(scodec->clk_apb)) {
1657                 dev_err(&pdev->dev, "Failed to enable the APB clock\n");
1658                 return -EINVAL;
1659         }
1660
1661         /* Deassert the reset control */
1662         if (scodec->rst) {
1663                 ret = reset_control_deassert(scodec->rst);
1664                 if (ret) {
1665                         dev_err(&pdev->dev,
1666                                 "Failed to deassert the reset control\n");
1667                         goto err_clk_disable;
1668                 }
1669         }
1670
1671         /* DMA configuration for TX FIFO */
1672         scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata;
1673         scodec->playback_dma_data.maxburst = 8;
1674         scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
1675
1676         /* DMA configuration for RX FIFO */
1677         scodec->capture_dma_data.addr = res->start + quirks->reg_adc_rxdata;
1678         scodec->capture_dma_data.maxburst = 8;
1679         scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
1680
1681         ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec,
1682                                      &sun4i_codec_dai, 1);
1683         if (ret) {
1684                 dev_err(&pdev->dev, "Failed to register our codec\n");
1685                 goto err_assert_reset;
1686         }
1687
1688         ret = devm_snd_soc_register_component(&pdev->dev,
1689                                               &sun4i_codec_component,
1690                                               &dummy_cpu_dai, 1);
1691         if (ret) {
1692                 dev_err(&pdev->dev, "Failed to register our DAI\n");
1693                 goto err_assert_reset;
1694         }
1695
1696         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1697         if (ret) {
1698                 dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
1699                 goto err_assert_reset;
1700         }
1701
1702         card = quirks->create_card(&pdev->dev);
1703         if (IS_ERR(card)) {
1704                 ret = PTR_ERR(card);
1705                 dev_err(&pdev->dev, "Failed to create our card\n");
1706                 goto err_assert_reset;
1707         }
1708
1709         snd_soc_card_set_drvdata(card, scodec);
1710
1711         ret = snd_soc_register_card(card);
1712         if (ret) {
1713                 dev_err(&pdev->dev, "Failed to register our card\n");
1714                 goto err_assert_reset;
1715         }
1716
1717         return 0;
1718
1719 err_assert_reset:
1720         if (scodec->rst)
1721                 reset_control_assert(scodec->rst);
1722 err_clk_disable:
1723         clk_disable_unprepare(scodec->clk_apb);
1724         return ret;
1725 }
1726
1727 static int sun4i_codec_remove(struct platform_device *pdev)
1728 {
1729         struct snd_soc_card *card = platform_get_drvdata(pdev);
1730         struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
1731
1732         snd_soc_unregister_card(card);
1733         if (scodec->rst)
1734                 reset_control_assert(scodec->rst);
1735         clk_disable_unprepare(scodec->clk_apb);
1736
1737         return 0;
1738 }
1739
1740 static struct platform_driver sun4i_codec_driver = {
1741         .driver = {
1742                 .name = "sun4i-codec",
1743                 .of_match_table = sun4i_codec_of_match,
1744         },
1745         .probe = sun4i_codec_probe,
1746         .remove = sun4i_codec_remove,
1747 };
1748 module_platform_driver(sun4i_codec_driver);
1749
1750 MODULE_DESCRIPTION("Allwinner A10 codec driver");
1751 MODULE_AUTHOR("Emilio López <emilio@elopez.com.ar>");
1752 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
1753 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1754 MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
1755 MODULE_LICENSE("GPL");