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