1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * This driver supports the digital controls for the internal codec
4 * found in Allwinner's A33 SoCs.
5 *
6 * (C) Copyright 2010-2016
7 * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
8 * huangxin <huangxin@Reuuimllatech.com>
9 * Mylène Josserand <mylene.josserand@free-electrons.com>
10 */
11
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/clk.h>
15#include <linux/input.h>
16#include <linux/io.h>
17#include <linux/irq.h>
18#include <linux/mutex.h>
19#include <linux/of.h>
20#include <linux/pm_runtime.h>
21#include <linux/regmap.h>
22#include <linux/log2.h>
23
24#include <sound/jack.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/tlv.h>
29
30#define SUN8I_SYSCLK_CTL 0x00c
31#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11
32#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL (0x2 << 8)
33#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 7
34#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4)
35#define SUN8I_SYSCLK_CTL_SYSCLK_ENA 3
36#define SUN8I_SYSCLK_CTL_SYSCLK_SRC 0
37#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK (0x0 << 0)
38#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK (0x1 << 0)
39#define SUN8I_MOD_CLK_ENA 0x010
40#define SUN8I_MOD_CLK_ENA_AIF1 15
41#define SUN8I_MOD_CLK_ENA_AIF2 14
42#define SUN8I_MOD_CLK_ENA_AIF3 13
43#define SUN8I_MOD_CLK_ENA_ADC 3
44#define SUN8I_MOD_CLK_ENA_DAC 2
45#define SUN8I_MOD_RST_CTL 0x014
46#define SUN8I_MOD_RST_CTL_AIF1 15
47#define SUN8I_MOD_RST_CTL_AIF2 14
48#define SUN8I_MOD_RST_CTL_AIF3 13
49#define SUN8I_MOD_RST_CTL_ADC 3
50#define SUN8I_MOD_RST_CTL_DAC 2
51#define SUN8I_SYS_SR_CTRL 0x018
52#define SUN8I_SYS_SR_CTRL_AIF1_FS 12
53#define SUN8I_SYS_SR_CTRL_AIF2_FS 8
54#define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n)))
55#define SUN8I_AIF_CLK_CTRL_MSTR_MOD 15
56#define SUN8I_AIF_CLK_CTRL_CLK_INV 13
57#define SUN8I_AIF_CLK_CTRL_BCLK_DIV 9
58#define SUN8I_AIF_CLK_CTRL_LRCK_DIV 6
59#define SUN8I_AIF_CLK_CTRL_WORD_SIZ 4
60#define SUN8I_AIF_CLK_CTRL_DATA_FMT 2
61#define SUN8I_AIF1_ADCDAT_CTRL 0x044
62#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15
63#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14
64#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10
65#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8
66#define SUN8I_AIF1_DACDAT_CTRL 0x048
67#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15
68#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14
69#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC 10
70#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC 8
71#define SUN8I_AIF1_MXR_SRC 0x04c
72#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 15
73#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 14
74#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 13
75#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 12
76#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 11
77#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10
78#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9
79#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8
80#define SUN8I_AIF1_VOL_CTRL1 0x050
81#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL 8
82#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL 0
83#define SUN8I_AIF1_VOL_CTRL3 0x058
84#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL 8
85#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL 0
86#define SUN8I_AIF2_ADCDAT_CTRL 0x084
87#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA 15
88#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA 14
89#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC 10
90#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC 8
91#define SUN8I_AIF2_DACDAT_CTRL 0x088
92#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA 15
93#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA 14
94#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC 10
95#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC 8
96#define SUN8I_AIF2_MXR_SRC 0x08c
97#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L 15
98#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L 14
99#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR 13
100#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL 12
101#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R 11
102#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10
103#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9
104#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8
105#define SUN8I_AIF2_VOL_CTRL1 0x090
106#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL 8
107#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL 0
108#define SUN8I_AIF2_VOL_CTRL2 0x098
109#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL 8
110#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL 0
111#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 (0x0 << 0)
112#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 (0x1 << 0)
113#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK (0x2 << 0)
114#define SUN8I_AIF3_PATH_CTRL 0x0cc
115#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC 10
116#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC 8
117#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7
118#define SUN8I_ADC_DIG_CTRL 0x100
119#define SUN8I_ADC_DIG_CTRL_ENAD 15
120#define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2
121#define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1
122#define SUN8I_ADC_VOL_CTRL 0x104
123#define SUN8I_ADC_VOL_CTRL_ADCL_VOL 8
124#define SUN8I_ADC_VOL_CTRL_ADCR_VOL 0
125#define SUN8I_HMIC_CTRL1 0x110
126#define SUN8I_HMIC_CTRL1_HMIC_M 12
127#define SUN8I_HMIC_CTRL1_HMIC_N 8
128#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB 5
129#define SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN 4
130#define SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN 3
131#define SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN 0
132#define SUN8I_HMIC_CTRL2 0x114
133#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE 14
134#define SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD 8
135#define SUN8I_HMIC_CTRL2_HMIC_SF 6
136#define SUN8I_HMIC_STS 0x118
137#define SUN8I_HMIC_STS_MDATA_DISCARD 13
138#define SUN8I_HMIC_STS_HMIC_DATA 8
139#define SUN8I_HMIC_STS_JACK_OUT_IRQ_ST 4
140#define SUN8I_HMIC_STS_JACK_IN_IRQ_ST 3
141#define SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST 0
142#define SUN8I_DAC_DIG_CTRL 0x120
143#define SUN8I_DAC_DIG_CTRL_ENDA 15
144#define SUN8I_DAC_VOL_CTRL 0x124
145#define SUN8I_DAC_VOL_CTRL_DACL_VOL 8
146#define SUN8I_DAC_VOL_CTRL_DACR_VOL 0
147#define SUN8I_DAC_MXR_SRC 0x130
148#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15
149#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14
150#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13
151#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL 12
152#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11
153#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10
154#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9
155#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8
156
157#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8)
158#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4)
159#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
160#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
161#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK GENMASK(14, 13)
162#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK GENMASK(12, 9)
163#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK GENMASK(8, 6)
164#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4)
165#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2)
166#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK GENMASK(1, 0)
167#define SUN8I_HMIC_CTRL1_HMIC_M_MASK GENMASK(15, 12)
168#define SUN8I_HMIC_CTRL1_HMIC_N_MASK GENMASK(11, 8)
169#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB_MASK GENMASK(6, 5)
170#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE_MASK GENMASK(15, 14)
171#define SUN8I_HMIC_CTRL2_HMIC_SF_MASK GENMASK(7, 6)
172#define SUN8I_HMIC_STS_HMIC_DATA_MASK GENMASK(12, 8)
173
174#define SUN8I_CODEC_BUTTONS (SND_JACK_BTN_0|\
175 SND_JACK_BTN_1|\
176 SND_JACK_BTN_2|\
177 SND_JACK_BTN_3)
178
179#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
180
181#define SUN8I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 |\
182 SNDRV_PCM_FMTBIT_S16_LE |\
183 SNDRV_PCM_FMTBIT_S20_LE |\
184 SNDRV_PCM_FMTBIT_S24_LE |\
185 SNDRV_PCM_FMTBIT_S20_3LE|\
186 SNDRV_PCM_FMTBIT_S24_3LE)
187
188#define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\
189 SNDRV_PCM_RATE_88200 |\
190 SNDRV_PCM_RATE_96000 |\
191 SNDRV_PCM_RATE_176400 |\
192 SNDRV_PCM_RATE_192000 |\
193 SNDRV_PCM_RATE_KNOT)
194
195enum {
196 SUN8I_CODEC_AIF1,
197 SUN8I_CODEC_AIF2,
198 SUN8I_CODEC_AIF3,
199 SUN8I_CODEC_NAIFS
200};
201
202struct sun8i_codec_aif {
203 unsigned int lrck_div_order;
204 unsigned int sample_rate;
205 unsigned int slots;
206 unsigned int slot_width;
207 unsigned int active_streams : 2;
208 unsigned int open_streams : 2;
209};
210
211struct sun8i_codec_quirks {
212 bool bus_clock : 1;
213 bool jack_detection : 1;
214 bool legacy_widgets : 1;
215 bool lrck_inversion : 1;
216};
217
218enum {
219 SUN8I_JACK_STATUS_DISCONNECTED,
220 SUN8I_JACK_STATUS_WAITING_HBIAS,
221 SUN8I_JACK_STATUS_CONNECTED,
222};
223
224struct sun8i_codec {
225 struct snd_soc_component *component;
226 struct regmap *regmap;
227 struct clk *clk_bus;
228 struct clk *clk_module;
229 const struct sun8i_codec_quirks *quirks;
230 struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS];
231 struct snd_soc_jack *jack;
232 struct delayed_work jack_work;
233 int jack_irq;
234 int jack_status;
235 int jack_type;
236 int jack_last_sample;
237 ktime_t jack_hbias_ready;
238 struct mutex jack_mutex;
239 int last_hmic_irq;
240 unsigned int sysclk_rate;
241 int sysclk_refcnt;
242};
243
244static struct snd_soc_dai_driver sun8i_codec_dais[];
245
246static int sun8i_codec_runtime_resume(struct device *dev)
247{
248 struct sun8i_codec *scodec = dev_get_drvdata(dev);
249 int ret;
250
251 ret = clk_prepare_enable(clk: scodec->clk_bus);
252 if (ret) {
253 dev_err(dev, "Failed to enable the bus clock\n");
254 return ret;
255 }
256
257 regcache_cache_only(map: scodec->regmap, enable: false);
258
259 ret = regcache_sync(map: scodec->regmap);
260 if (ret) {
261 dev_err(dev, "Failed to sync regmap cache\n");
262 return ret;
263 }
264
265 return 0;
266}
267
268static int sun8i_codec_runtime_suspend(struct device *dev)
269{
270 struct sun8i_codec *scodec = dev_get_drvdata(dev);
271
272 regcache_cache_only(map: scodec->regmap, enable: true);
273 regcache_mark_dirty(map: scodec->regmap);
274
275 clk_disable_unprepare(clk: scodec->clk_bus);
276
277 return 0;
278}
279
280static int sun8i_codec_get_hw_rate(unsigned int sample_rate)
281{
282 switch (sample_rate) {
283 case 7350:
284 case 8000:
285 return 0x0;
286 case 11025:
287 return 0x1;
288 case 12000:
289 return 0x2;
290 case 14700:
291 case 16000:
292 return 0x3;
293 case 22050:
294 return 0x4;
295 case 24000:
296 return 0x5;
297 case 29400:
298 case 32000:
299 return 0x6;
300 case 44100:
301 return 0x7;
302 case 48000:
303 return 0x8;
304 case 88200:
305 case 96000:
306 return 0x9;
307 case 176400:
308 case 192000:
309 return 0xa;
310 default:
311 return -EINVAL;
312 }
313}
314
315static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)
316{
317 unsigned int max_rate = 0;
318 int hw_rate, i;
319
320 for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) {
321 struct sun8i_codec_aif *aif = &scodec->aifs[i];
322
323 if (aif->active_streams)
324 max_rate = max(max_rate, aif->sample_rate);
325 }
326
327 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */
328 if (!max_rate)
329 max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE;
330
331 hw_rate = sun8i_codec_get_hw_rate(sample_rate: max_rate);
332 if (hw_rate < 0)
333 return hw_rate;
334
335 regmap_update_bits(map: scodec->regmap, SUN8I_SYS_SR_CTRL,
336 SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
337 val: hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
338
339 return 0;
340}
341
342static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
343{
344 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
345 u32 dsp_format, format, invert, value;
346
347 /* clock masters */
348 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
349 case SND_SOC_DAIFMT_CBC_CFC: /* Codec slave, DAI master */
350 value = 0x1;
351 break;
352 case SND_SOC_DAIFMT_CBP_CFP: /* Codec Master, DAI slave */
353 value = 0x0;
354 break;
355 default:
356 return -EINVAL;
357 }
358
359 if (dai->id == SUN8I_CODEC_AIF3) {
360 /* AIF3 only supports master mode. */
361 if (value)
362 return -EINVAL;
363
364 /* Use the AIF2 BCLK and LRCK for AIF3. */
365 regmap_update_bits(map: scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
366 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK,
367 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2);
368 } else {
369 regmap_update_bits(map: scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
370 BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD),
371 val: value << SUN8I_AIF_CLK_CTRL_MSTR_MOD);
372 }
373
374 /* DAI format */
375 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
376 case SND_SOC_DAIFMT_I2S:
377 format = 0x0;
378 break;
379 case SND_SOC_DAIFMT_LEFT_J:
380 format = 0x1;
381 break;
382 case SND_SOC_DAIFMT_RIGHT_J:
383 format = 0x2;
384 break;
385 case SND_SOC_DAIFMT_DSP_A:
386 format = 0x3;
387 dsp_format = 0x0; /* Set LRCK_INV to 0 */
388 break;
389 case SND_SOC_DAIFMT_DSP_B:
390 format = 0x3;
391 dsp_format = 0x1; /* Set LRCK_INV to 1 */
392 break;
393 default:
394 return -EINVAL;
395 }
396
397 if (dai->id == SUN8I_CODEC_AIF3) {
398 /* AIF3 only supports DSP mode. */
399 if (format != 3)
400 return -EINVAL;
401 } else {
402 regmap_update_bits(map: scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
403 SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK,
404 val: format << SUN8I_AIF_CLK_CTRL_DATA_FMT);
405 }
406
407 /* clock inversion */
408 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
409 case SND_SOC_DAIFMT_NB_NF: /* Normal */
410 invert = 0x0;
411 break;
412 case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */
413 invert = 0x1;
414 break;
415 case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */
416 invert = 0x2;
417 break;
418 case SND_SOC_DAIFMT_IB_IF: /* Both inverted */
419 invert = 0x3;
420 break;
421 default:
422 return -EINVAL;
423 }
424
425 if (format == 0x3) {
426 /* Inverted LRCK is not available in DSP mode. */
427 if (invert & BIT(0))
428 return -EINVAL;
429
430 /* Instead, the bit selects between DSP A/B formats. */
431 invert |= dsp_format;
432 } else {
433 /*
434 * It appears that the DAI and the codec in the A33 SoC don't
435 * share the same polarity for the LRCK signal when they mean
436 * 'normal' and 'inverted' in the datasheet.
437 *
438 * Since the DAI here is our regular i2s driver that have been
439 * tested with way more codecs than just this one, it means
440 * that the codec probably gets it backward, and we have to
441 * invert the value here.
442 */
443 invert ^= scodec->quirks->lrck_inversion;
444 }
445
446 regmap_update_bits(map: scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
447 SUN8I_AIF_CLK_CTRL_CLK_INV_MASK,
448 val: invert << SUN8I_AIF_CLK_CTRL_CLK_INV);
449
450 return 0;
451}
452
453static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,
454 unsigned int tx_mask, unsigned int rx_mask,
455 int slots, int slot_width)
456{
457 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
458 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
459
460 if (slot_width && !is_power_of_2(n: slot_width))
461 return -EINVAL;
462
463 aif->slots = slots;
464 aif->slot_width = slot_width;
465
466 return 0;
467}
468
469static const unsigned int sun8i_codec_rates[] = {
470 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000,
471 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000,
472};
473
474static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = {
475 .list = sun8i_codec_rates,
476 .count = ARRAY_SIZE(sun8i_codec_rates),
477};
478
479static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = {
480 .list = sun8i_codec_rates,
481 .count = ARRAY_SIZE(sun8i_codec_rates),
482 .mask = 0x5555,
483};
484
485static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = {
486 .list = sun8i_codec_rates,
487 .count = ARRAY_SIZE(sun8i_codec_rates),
488 .mask = 0xaaaa,
489};
490
491static int sun8i_codec_startup(struct snd_pcm_substream *substream,
492 struct snd_soc_dai *dai)
493{
494 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
495 const struct snd_pcm_hw_constraint_list *list;
496
497 /* hw_constraints is not relevant for codec2codec DAIs. */
498 if (dai->id != SUN8I_CODEC_AIF1)
499 return 0;
500
501 if (!scodec->sysclk_refcnt)
502 list = &sun8i_codec_all_rates;
503 else if (scodec->sysclk_rate == 22579200)
504 list = &sun8i_codec_22M_rates;
505 else if (scodec->sysclk_rate == 24576000)
506 list = &sun8i_codec_24M_rates;
507 else
508 return -EINVAL;
509
510 return snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0,
511 SNDRV_PCM_HW_PARAM_RATE, l: list);
512}
513
514struct sun8i_codec_clk_div {
515 u8 div;
516 u8 val;
517};
518
519static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
520 { .div = 1, .val = 0 },
521 { .div = 2, .val = 1 },
522 { .div = 4, .val = 2 },
523 { .div = 6, .val = 3 },
524 { .div = 8, .val = 4 },
525 { .div = 12, .val = 5 },
526 { .div = 16, .val = 6 },
527 { .div = 24, .val = 7 },
528 { .div = 32, .val = 8 },
529 { .div = 48, .val = 9 },
530 { .div = 64, .val = 10 },
531 { .div = 96, .val = 11 },
532 { .div = 128, .val = 12 },
533 { .div = 192, .val = 13 },
534};
535
536static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
537 unsigned int lrck_div_order,
538 unsigned int sample_rate)
539{
540 unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;
541 int i;
542
543 for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
544 const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i];
545
546 if (bdiv->div == div)
547 return bdiv->val;
548 }
549
550 return -EINVAL;
551}
552
553static int sun8i_codec_get_lrck_div_order(unsigned int slots,
554 unsigned int slot_width)
555{
556 unsigned int div = slots * slot_width;
557
558 if (div < 16 || div > 256)
559 return -EINVAL;
560
561 return order_base_2(div);
562}
563
564static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)
565{
566 return (sample_rate % 4000) ? 22579200 : 24576000;
567}
568
569static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
570 struct snd_pcm_hw_params *params,
571 struct snd_soc_dai *dai)
572{
573 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
574 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
575 unsigned int sample_rate = params_rate(p: params);
576 unsigned int slots = aif->slots ?: params_channels(p: params);
577 unsigned int slot_width = aif->slot_width ?: params_width(p: params);
578 unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);
579 int bclk_div, lrck_div_order, ret, word_size;
580 u32 clk_reg;
581
582 /* word size */
583 switch (params_width(p: params)) {
584 case 8:
585 word_size = 0x0;
586 break;
587 case 16:
588 word_size = 0x1;
589 break;
590 case 20:
591 word_size = 0x2;
592 break;
593 case 24:
594 word_size = 0x3;
595 break;
596 default:
597 return -EINVAL;
598 }
599
600 regmap_update_bits(map: scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
601 SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK,
602 val: word_size << SUN8I_AIF_CLK_CTRL_WORD_SIZ);
603
604 /* LRCK divider (BCLK/LRCK ratio) */
605 lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);
606 if (lrck_div_order < 0)
607 return lrck_div_order;
608
609 if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) {
610 /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */
611 int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id;
612 const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner];
613 const char *partner_name = sun8i_codec_dais[partner].name;
614
615 if (partner_aif->open_streams &&
616 (lrck_div_order != partner_aif->lrck_div_order ||
617 sample_rate != partner_aif->sample_rate)) {
618 dev_err(dai->dev,
619 "%s sample and bit rates must match %s when both are used\n",
620 dai->name, partner_name);
621 return -EBUSY;
622 }
623
624 clk_reg = SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2);
625 } else {
626 clk_reg = SUN8I_AIF_CLK_CTRL(dai->id);
627 }
628
629 regmap_update_bits(map: scodec->regmap, reg: clk_reg,
630 SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK,
631 val: (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV);
632
633 /* BCLK divider (SYSCLK/BCLK ratio) */
634 bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate);
635 if (bclk_div < 0)
636 return bclk_div;
637
638 regmap_update_bits(map: scodec->regmap, reg: clk_reg,
639 SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK,
640 val: bclk_div << SUN8I_AIF_CLK_CTRL_BCLK_DIV);
641
642 /*
643 * SYSCLK rate
644 *
645 * Clock rate protection is reference counted; but hw_params may be
646 * called many times per substream, without matching calls to hw_free.
647 * Protect the clock rate once per AIF, on the first hw_params call
648 * for the first substream. clk_set_rate() will allow clock rate
649 * changes on subsequent calls if only one AIF has open streams.
650 */
651 ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module,
652 sysclk_rate);
653 if (ret == -EBUSY)
654 dev_err(dai->dev,
655 "%s sample rate (%u Hz) conflicts with other audio streams\n",
656 dai->name, sample_rate);
657 if (ret < 0)
658 return ret;
659
660 if (!aif->open_streams)
661 scodec->sysclk_refcnt++;
662 scodec->sysclk_rate = sysclk_rate;
663
664 aif->lrck_div_order = lrck_div_order;
665 aif->sample_rate = sample_rate;
666 aif->open_streams |= BIT(substream->stream);
667
668 return sun8i_codec_update_sample_rate(scodec);
669}
670
671static int sun8i_codec_hw_free(struct snd_pcm_substream *substream,
672 struct snd_soc_dai *dai)
673{
674 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
675 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
676
677 /* Drop references when the last substream for the AIF is freed. */
678 if (aif->open_streams != BIT(substream->stream))
679 goto done;
680
681 clk_rate_exclusive_put(clk: scodec->clk_module);
682 scodec->sysclk_refcnt--;
683 aif->lrck_div_order = 0;
684 aif->sample_rate = 0;
685
686done:
687 aif->open_streams &= ~BIT(substream->stream);
688 return 0;
689}
690
691static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
692 .set_fmt = sun8i_codec_set_fmt,
693 .set_tdm_slot = sun8i_codec_set_tdm_slot,
694 .startup = sun8i_codec_startup,
695 .hw_params = sun8i_codec_hw_params,
696 .hw_free = sun8i_codec_hw_free,
697};
698
699static struct snd_soc_dai_driver sun8i_codec_dais[] = {
700 {
701 .name = "sun8i-codec-aif1",
702 .id = SUN8I_CODEC_AIF1,
703 .ops = &sun8i_codec_dai_ops,
704 /* capture capabilities */
705 .capture = {
706 .stream_name = "AIF1 Capture",
707 .channels_min = 1,
708 .channels_max = 2,
709 .rates = SUN8I_CODEC_PCM_RATES,
710 .formats = SUN8I_CODEC_PCM_FORMATS,
711 .sig_bits = 24,
712 },
713 /* playback capabilities */
714 .playback = {
715 .stream_name = "AIF1 Playback",
716 .channels_min = 1,
717 .channels_max = 2,
718 .rates = SUN8I_CODEC_PCM_RATES,
719 .formats = SUN8I_CODEC_PCM_FORMATS,
720 },
721 .symmetric_rate = true,
722 .symmetric_channels = true,
723 .symmetric_sample_bits = true,
724 },
725 {
726 .name = "sun8i-codec-aif2",
727 .id = SUN8I_CODEC_AIF2,
728 .ops = &sun8i_codec_dai_ops,
729 /* capture capabilities */
730 .capture = {
731 .stream_name = "AIF2 Capture",
732 .channels_min = 1,
733 .channels_max = 2,
734 .rates = SUN8I_CODEC_PCM_RATES,
735 .formats = SUN8I_CODEC_PCM_FORMATS,
736 .sig_bits = 24,
737 },
738 /* playback capabilities */
739 .playback = {
740 .stream_name = "AIF2 Playback",
741 .channels_min = 1,
742 .channels_max = 2,
743 .rates = SUN8I_CODEC_PCM_RATES,
744 .formats = SUN8I_CODEC_PCM_FORMATS,
745 },
746 .symmetric_rate = true,
747 .symmetric_channels = true,
748 .symmetric_sample_bits = true,
749 },
750 {
751 .name = "sun8i-codec-aif3",
752 .id = SUN8I_CODEC_AIF3,
753 .ops = &sun8i_codec_dai_ops,
754 /* capture capabilities */
755 .capture = {
756 .stream_name = "AIF3 Capture",
757 .channels_min = 1,
758 .channels_max = 1,
759 .rates = SUN8I_CODEC_PCM_RATES,
760 .formats = SUN8I_CODEC_PCM_FORMATS,
761 .sig_bits = 24,
762 },
763 /* playback capabilities */
764 .playback = {
765 .stream_name = "AIF3 Playback",
766 .channels_min = 1,
767 .channels_max = 1,
768 .rates = SUN8I_CODEC_PCM_RATES,
769 .formats = SUN8I_CODEC_PCM_FORMATS,
770 },
771 .symmetric_rate = true,
772 .symmetric_channels = true,
773 .symmetric_sample_bits = true,
774 },
775};
776
777static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);
778
779static const struct snd_kcontrol_new sun8i_codec_controls[] = {
780 SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume",
781 SUN8I_AIF1_VOL_CTRL1,
782 SUN8I_AIF1_VOL_CTRL1_AD0L_VOL,
783 SUN8I_AIF1_VOL_CTRL1_AD0R_VOL,
784 0xc0, 0, sun8i_codec_vol_scale),
785 SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume",
786 SUN8I_AIF1_VOL_CTRL3,
787 SUN8I_AIF1_VOL_CTRL3_DA0L_VOL,
788 SUN8I_AIF1_VOL_CTRL3_DA0R_VOL,
789 0xc0, 0, sun8i_codec_vol_scale),
790 SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",
791 SUN8I_AIF2_VOL_CTRL1,
792 SUN8I_AIF2_VOL_CTRL1_ADCL_VOL,
793 SUN8I_AIF2_VOL_CTRL1_ADCR_VOL,
794 0xc0, 0, sun8i_codec_vol_scale),
795 SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",
796 SUN8I_AIF2_VOL_CTRL2,
797 SUN8I_AIF2_VOL_CTRL2_DACL_VOL,
798 SUN8I_AIF2_VOL_CTRL2_DACR_VOL,
799 0xc0, 0, sun8i_codec_vol_scale),
800 SOC_DOUBLE_TLV("ADC Capture Volume",
801 SUN8I_ADC_VOL_CTRL,
802 SUN8I_ADC_VOL_CTRL_ADCL_VOL,
803 SUN8I_ADC_VOL_CTRL_ADCR_VOL,
804 0xc0, 0, sun8i_codec_vol_scale),
805 SOC_DOUBLE_TLV("DAC Playback Volume",
806 SUN8I_DAC_VOL_CTRL,
807 SUN8I_DAC_VOL_CTRL_DACL_VOL,
808 SUN8I_DAC_VOL_CTRL_DACR_VOL,
809 0xc0, 0, sun8i_codec_vol_scale),
810};
811
812static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,
813 struct snd_kcontrol *kcontrol, int event)
814{
815 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm);
816 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(c: component);
817 struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1'];
818 int stream = w->id == snd_soc_dapm_aif_out;
819
820 if (SND_SOC_DAPM_EVENT_ON(event))
821 aif->active_streams |= BIT(stream);
822 else
823 aif->active_streams &= ~BIT(stream);
824
825 return sun8i_codec_update_sample_rate(scodec);
826}
827
828static const char *const sun8i_aif_stereo_mux_enum_values[] = {
829 "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
830};
831
832static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
833 SUN8I_AIF1_ADCDAT_CTRL,
834 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
835 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
836 sun8i_aif_stereo_mux_enum_values);
837
838static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control =
839 SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",
840 sun8i_aif1_ad0_stereo_mux_enum);
841
842static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum,
843 SUN8I_AIF2_ADCDAT_CTRL,
844 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC,
845 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC,
846 sun8i_aif_stereo_mux_enum_values);
847
848static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control =
849 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
850 sun8i_aif2_adc_stereo_mux_enum);
851
852static const char *const sun8i_aif3_adc_mux_enum_values[] = {
853 "None", "AIF2 ADCL", "AIF2 ADCR"
854};
855
856static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum,
857 SUN8I_AIF3_PATH_CTRL,
858 SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC,
859 sun8i_aif3_adc_mux_enum_values);
860
861static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control =
862 SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",
863 sun8i_aif3_adc_mux_enum);
864
865static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {
866 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
867 SUN8I_AIF1_MXR_SRC,
868 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
869 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
870 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
871 SUN8I_AIF1_MXR_SRC,
872 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
873 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
874 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
875 SUN8I_AIF1_MXR_SRC,
876 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
877 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
878 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
879 SUN8I_AIF1_MXR_SRC,
880 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
881 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
882};
883
884static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = {
885 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
886 SUN8I_AIF2_MXR_SRC,
887 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L,
888 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R, 1, 0),
889 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
890 SUN8I_AIF2_MXR_SRC,
891 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L,
892 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R, 1, 0),
893 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
894 SUN8I_AIF2_MXR_SRC,
895 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR,
896 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL, 1, 0),
897 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
898 SUN8I_AIF2_MXR_SRC,
899 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL,
900 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR, 1, 0),
901};
902
903static const char *const sun8i_aif2_dac_mux_enum_values[] = {
904 "AIF2", "AIF3+2", "AIF2+3"
905};
906
907static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum,
908 SUN8I_AIF3_PATH_CTRL,
909 SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC,
910 sun8i_aif2_dac_mux_enum_values);
911
912static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control =
913 SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",
914 sun8i_aif2_dac_mux_enum);
915
916static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,
917 SUN8I_AIF1_DACDAT_CTRL,
918 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,
919 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,
920 sun8i_aif_stereo_mux_enum_values);
921
922static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control =
923 SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",
924 sun8i_aif1_da0_stereo_mux_enum);
925
926static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum,
927 SUN8I_AIF2_DACDAT_CTRL,
928 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC,
929 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC,
930 sun8i_aif_stereo_mux_enum_values);
931
932static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control =
933 SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",
934 sun8i_aif2_dac_stereo_mux_enum);
935
936static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
937 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
938 SUN8I_DAC_MXR_SRC,
939 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
940 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
941 SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
942 SUN8I_DAC_MXR_SRC,
943 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
944 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
945 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
946 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
947 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
948 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
949 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
950 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
951};
952
953static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
954 /* System Clocks */
955 SND_SOC_DAPM_CLOCK_SUPPLY("mod"),
956
957 SND_SOC_DAPM_SUPPLY("AIF1CLK",
958 SUN8I_SYSCLK_CTL,
959 SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
960 SND_SOC_DAPM_SUPPLY("AIF2CLK",
961 SUN8I_SYSCLK_CTL,
962 SUN8I_SYSCLK_CTL_AIF2CLK_ENA, 0, NULL, 0),
963 SND_SOC_DAPM_SUPPLY("SYSCLK",
964 SUN8I_SYSCLK_CTL,
965 SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
966
967 /* Module Clocks */
968 SND_SOC_DAPM_SUPPLY("CLK AIF1",
969 SUN8I_MOD_CLK_ENA,
970 SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
971 SND_SOC_DAPM_SUPPLY("CLK AIF2",
972 SUN8I_MOD_CLK_ENA,
973 SUN8I_MOD_CLK_ENA_AIF2, 0, NULL, 0),
974 SND_SOC_DAPM_SUPPLY("CLK AIF3",
975 SUN8I_MOD_CLK_ENA,
976 SUN8I_MOD_CLK_ENA_AIF3, 0, NULL, 0),
977 SND_SOC_DAPM_SUPPLY("CLK ADC",
978 SUN8I_MOD_CLK_ENA,
979 SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
980 SND_SOC_DAPM_SUPPLY("CLK DAC",
981 SUN8I_MOD_CLK_ENA,
982 SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
983
984 /* Module Resets */
985 SND_SOC_DAPM_SUPPLY("RST AIF1",
986 SUN8I_MOD_RST_CTL,
987 SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
988 SND_SOC_DAPM_SUPPLY("RST AIF2",
989 SUN8I_MOD_RST_CTL,
990 SUN8I_MOD_RST_CTL_AIF2, 0, NULL, 0),
991 SND_SOC_DAPM_SUPPLY("RST AIF3",
992 SUN8I_MOD_RST_CTL,
993 SUN8I_MOD_RST_CTL_AIF3, 0, NULL, 0),
994 SND_SOC_DAPM_SUPPLY("RST ADC",
995 SUN8I_MOD_RST_CTL,
996 SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
997 SND_SOC_DAPM_SUPPLY("RST DAC",
998 SUN8I_MOD_RST_CTL,
999 SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
1000
1001 /* Module Supplies */
1002 SND_SOC_DAPM_SUPPLY("ADC",
1003 SUN8I_ADC_DIG_CTRL,
1004 SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
1005 SND_SOC_DAPM_SUPPLY("DAC",
1006 SUN8I_DAC_DIG_CTRL,
1007 SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
1008
1009 /* AIF "ADC" Outputs */
1010 SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0,
1011 SUN8I_AIF1_ADCDAT_CTRL,
1012 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0,
1013 sun8i_codec_aif_event,
1014 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1015 SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
1016 SUN8I_AIF1_ADCDAT_CTRL,
1017 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
1018
1019 SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,
1020 SUN8I_AIF2_ADCDAT_CTRL,
1021 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA, 0,
1022 sun8i_codec_aif_event,
1023 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1024 SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,
1025 SUN8I_AIF2_ADCDAT_CTRL,
1026 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA, 0),
1027
1028 SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,
1029 SND_SOC_NOPM, 0, 0,
1030 sun8i_codec_aif_event,
1031 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1032
1033 /* AIF "ADC" Mono/Stereo Muxes */
1034 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,
1035 &sun8i_aif1_ad0_stereo_mux_control),
1036 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,
1037 &sun8i_aif1_ad0_stereo_mux_control),
1038
1039 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,
1040 &sun8i_aif2_adc_stereo_mux_control),
1041 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,
1042 &sun8i_aif2_adc_stereo_mux_control),
1043
1044 /* AIF "ADC" Output Muxes */
1045 SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
1046 &sun8i_aif3_adc_mux_control),
1047
1048 /* AIF "ADC" Mixers */
1049 SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
1050 sun8i_aif1_ad0_mixer_controls),
1051 SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
1052 sun8i_aif1_ad0_mixer_controls),
1053
1054 SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0,
1055 sun8i_aif2_adc_mixer_controls),
1056 SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0,
1057 sun8i_aif2_adc_mixer_controls),
1058
1059 /* AIF "DAC" Input Muxes */
1060 SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM, 0, 0,
1061 &sun8i_aif2_dac_mux_control),
1062 SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM, 0, 0,
1063 &sun8i_aif2_dac_mux_control),
1064
1065 /* AIF "DAC" Mono/Stereo Muxes */
1066 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0,
1067 &sun8i_aif1_da0_stereo_mux_control),
1068 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0,
1069 &sun8i_aif1_da0_stereo_mux_control),
1070
1071 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0,
1072 &sun8i_aif2_dac_stereo_mux_control),
1073 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0,
1074 &sun8i_aif2_dac_stereo_mux_control),
1075
1076 /* AIF "DAC" Inputs */
1077 SND_SOC_DAPM_AIF_IN_E("AIF1 DA0L", "AIF1 Playback", 0,
1078 SUN8I_AIF1_DACDAT_CTRL,
1079 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0,
1080 sun8i_codec_aif_event,
1081 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1082 SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1,
1083 SUN8I_AIF1_DACDAT_CTRL,
1084 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
1085
1086 SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0,
1087 SUN8I_AIF2_DACDAT_CTRL,
1088 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA, 0,
1089 sun8i_codec_aif_event,
1090 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1091 SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1,
1092 SUN8I_AIF2_DACDAT_CTRL,
1093 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA, 0),
1094
1095 SND_SOC_DAPM_AIF_IN_E("AIF3 DAC", "AIF3 Playback", 0,
1096 SND_SOC_NOPM, 0, 0,
1097 sun8i_codec_aif_event,
1098 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1099
1100 /* ADC Inputs (connected to analog codec DAPM context) */
1101 SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),
1102 SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1103
1104 /* DAC Outputs (connected to analog codec DAPM context) */
1105 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
1106 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
1107
1108 /* DAC Mixers */
1109 SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0,
1110 sun8i_dac_mixer_controls),
1111 SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0,
1112 sun8i_dac_mixer_controls),
1113};
1114
1115static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
1116 /* Clock Routes */
1117 { "AIF1CLK", NULL, "mod" },
1118
1119 { "SYSCLK", NULL, "AIF1CLK" },
1120
1121 { "CLK AIF1", NULL, "AIF1CLK" },
1122 { "CLK AIF1", NULL, "SYSCLK" },
1123 { "RST AIF1", NULL, "CLK AIF1" },
1124 { "AIF1 AD0L", NULL, "RST AIF1" },
1125 { "AIF1 AD0R", NULL, "RST AIF1" },
1126 { "AIF1 DA0L", NULL, "RST AIF1" },
1127 { "AIF1 DA0R", NULL, "RST AIF1" },
1128
1129 { "CLK AIF2", NULL, "AIF2CLK" },
1130 { "CLK AIF2", NULL, "SYSCLK" },
1131 { "RST AIF2", NULL, "CLK AIF2" },
1132 { "AIF2 ADCL", NULL, "RST AIF2" },
1133 { "AIF2 ADCR", NULL, "RST AIF2" },
1134 { "AIF2 DACL", NULL, "RST AIF2" },
1135 { "AIF2 DACR", NULL, "RST AIF2" },
1136
1137 { "CLK AIF3", NULL, "AIF1CLK" },
1138 { "CLK AIF3", NULL, "SYSCLK" },
1139 { "RST AIF3", NULL, "CLK AIF3" },
1140 { "AIF3 ADC", NULL, "RST AIF3" },
1141 { "AIF3 DAC", NULL, "RST AIF3" },
1142
1143 { "CLK ADC", NULL, "SYSCLK" },
1144 { "RST ADC", NULL, "CLK ADC" },
1145 { "ADC", NULL, "RST ADC" },
1146 { "ADCL", NULL, "ADC" },
1147 { "ADCR", NULL, "ADC" },
1148
1149 { "CLK DAC", NULL, "SYSCLK" },
1150 { "RST DAC", NULL, "CLK DAC" },
1151 { "DAC", NULL, "RST DAC" },
1152 { "DACL", NULL, "DAC" },
1153 { "DACR", NULL, "DAC" },
1154
1155 /* AIF "ADC" Output Routes */
1156 { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" },
1157 { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" },
1158
1159 { "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" },
1160 { "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" },
1161
1162 { "AIF3 ADC", NULL, "AIF3 ADC Source Capture Route" },
1163
1164 /* AIF "ADC" Mono/Stereo Mux Routes */
1165 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" },
1166 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" },
1167 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1168 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1169 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1170 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1171
1172 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" },
1173 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" },
1174 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1175 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1176 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1177 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1178
1179 { "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" },
1180 { "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" },
1181 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1182 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1183 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1184 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1185
1186 { "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" },
1187 { "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" },
1188 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1189 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1190 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1191 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1192
1193 /* AIF "ADC" Output Mux Routes */
1194 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },
1195 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },
1196
1197 /* AIF "ADC" Mixer Routes */
1198 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" },
1199 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },
1200 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },
1201 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },
1202
1203 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" },
1204 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },
1205 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },
1206 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },
1207
1208 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" },
1209 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" },
1210 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" },
1211
1212 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" },
1213 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" },
1214 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" },
1215
1216 /* AIF "DAC" Input Mux Routes */
1217 { "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" },
1218 { "AIF2 DACL Source", "AIF3+2", "AIF3 DAC" },
1219 { "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" },
1220
1221 { "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" },
1222 { "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" },
1223 { "AIF2 DACR Source", "AIF2+3", "AIF3 DAC" },
1224
1225 /* AIF "DAC" Mono/Stereo Mux Routes */
1226 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" },
1227 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" },
1228 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1229 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1230 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1231 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1232
1233 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" },
1234 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" },
1235 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1236 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1237 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1238 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1239
1240 { "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" },
1241 { "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" },
1242 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" },
1243 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" },
1244 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" },
1245 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" },
1246
1247 { "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" },
1248 { "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" },
1249 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" },
1250 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" },
1251 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" },
1252 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" },
1253
1254 /* DAC Output Routes */
1255 { "DACL", NULL, "DACL Mixer" },
1256 { "DACR", NULL, "DACR Mixer" },
1257
1258 /* DAC Mixer Routes */
1259 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" },
1260 { "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" },
1261 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
1262
1263 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" },
1264 { "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" },
1265 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" },
1266};
1267
1268static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = {
1269 /* Legacy ADC Inputs (connected to analog codec DAPM context) */
1270 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0),
1271 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0),
1272
1273 /* Legacy DAC Outputs (connected to analog codec DAPM context) */
1274 SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0),
1275 SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0),
1276};
1277
1278static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = {
1279 /* Legacy ADC Routes */
1280 { "ADCL", NULL, "AIF1 Slot 0 Left ADC" },
1281 { "ADCR", NULL, "AIF1 Slot 0 Right ADC" },
1282
1283 /* Legacy DAC Routes */
1284 { "AIF1 Slot 0 Left", NULL, "DACL" },
1285 { "AIF1 Slot 0 Right", NULL, "DACR" },
1286};
1287
1288static int sun8i_codec_component_probe(struct snd_soc_component *component)
1289{
1290 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
1291 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(c: component);
1292 int ret;
1293
1294 scodec->component = component;
1295
1296 /* Add widgets for backward compatibility with old device trees. */
1297 if (scodec->quirks->legacy_widgets) {
1298 ret = snd_soc_dapm_new_controls(dapm, widget: sun8i_codec_legacy_widgets,
1299 ARRAY_SIZE(sun8i_codec_legacy_widgets));
1300 if (ret)
1301 return ret;
1302
1303 ret = snd_soc_dapm_add_routes(dapm, route: sun8i_codec_legacy_routes,
1304 ARRAY_SIZE(sun8i_codec_legacy_routes));
1305 if (ret)
1306 return ret;
1307 }
1308
1309 /*
1310 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod")
1311 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also
1312 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO
1313 * directly to simplify the clock tree.
1314 */
1315 regmap_update_bits(map: scodec->regmap, SUN8I_SYSCLK_CTL,
1316 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK |
1317 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK,
1318 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL |
1319 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL);
1320
1321 /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */
1322 regmap_update_bits(map: scodec->regmap, SUN8I_SYSCLK_CTL,
1323 BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC),
1324 SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK);
1325
1326 /* Program the default sample rate. */
1327 sun8i_codec_update_sample_rate(scodec);
1328
1329 return 0;
1330}
1331
1332static void sun8i_codec_set_hmic_bias(struct sun8i_codec *scodec, bool enable)
1333{
1334 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card: scodec->component->card);
1335 int irq_mask = BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN);
1336
1337 if (enable)
1338 snd_soc_dapm_force_enable_pin(dapm, pin: "HBIAS");
1339 else
1340 snd_soc_dapm_disable_pin(dapm, pin: "HBIAS");
1341
1342 snd_soc_dapm_sync(dapm);
1343
1344 regmap_update_bits(map: scodec->regmap, SUN8I_HMIC_CTRL1,
1345 mask: irq_mask, val: enable ? irq_mask : 0);
1346}
1347
1348static void sun8i_codec_jack_work(struct work_struct *work)
1349{
1350 struct sun8i_codec *scodec = container_of(work, struct sun8i_codec,
1351 jack_work.work);
1352 unsigned int mdata;
1353 int type;
1354
1355 guard(mutex)(T: &scodec->jack_mutex);
1356
1357 if (scodec->jack_status == SUN8I_JACK_STATUS_DISCONNECTED) {
1358 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_IN_IRQ_ST)
1359 return;
1360
1361 scodec->jack_last_sample = -1;
1362
1363 if (scodec->jack_type & SND_JACK_MICROPHONE) {
1364 /*
1365 * If we were in disconnected state, we enable HBIAS and
1366 * wait 600ms before reading initial HDATA value.
1367 */
1368 scodec->jack_hbias_ready = ktime_add_ms(kt: ktime_get(), msec: 600);
1369 sun8i_codec_set_hmic_bias(scodec, enable: true);
1370 queue_delayed_work(wq: system_power_efficient_wq,
1371 dwork: &scodec->jack_work,
1372 delay: msecs_to_jiffies(m: 610));
1373 scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS;
1374 } else {
1375 snd_soc_jack_report(jack: scodec->jack, status: SND_JACK_HEADPHONE,
1376 mask: scodec->jack_type);
1377 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;
1378 }
1379 } else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) {
1380 /*
1381 * If we're waiting for HBIAS to stabilize, and we get plug-out
1382 * interrupt and nothing more for > 100ms, just cancel the
1383 * initialization.
1384 */
1385 if (scodec->last_hmic_irq == SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) {
1386 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED;
1387 sun8i_codec_set_hmic_bias(scodec, enable: false);
1388 return;
1389 }
1390
1391 /*
1392 * If we're not done waiting for HBIAS to stabilize, wait more.
1393 */
1394 if (!ktime_after(cmp1: ktime_get(), cmp2: scodec->jack_hbias_ready)) {
1395 s64 msecs = ktime_ms_delta(later: scodec->jack_hbias_ready,
1396 earlier: ktime_get());
1397
1398 queue_delayed_work(wq: system_power_efficient_wq,
1399 dwork: &scodec->jack_work,
1400 delay: msecs_to_jiffies(m: msecs + 10));
1401 return;
1402 }
1403
1404 /*
1405 * Everything is stabilized, determine jack type and report it.
1406 */
1407 regmap_read(map: scodec->regmap, SUN8I_HMIC_STS, val: &mdata);
1408 mdata &= SUN8I_HMIC_STS_HMIC_DATA_MASK;
1409 mdata >>= SUN8I_HMIC_STS_HMIC_DATA;
1410
1411 regmap_write(map: scodec->regmap, SUN8I_HMIC_STS, val: 0);
1412
1413 type = mdata < 16 ? SND_JACK_HEADPHONE : SND_JACK_HEADSET;
1414 if (type == SND_JACK_HEADPHONE)
1415 sun8i_codec_set_hmic_bias(scodec, enable: false);
1416
1417 snd_soc_jack_report(jack: scodec->jack, status: type, mask: scodec->jack_type);
1418 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;
1419 } else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) {
1420 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)
1421 return;
1422
1423 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED;
1424 if (scodec->jack_type & SND_JACK_MICROPHONE)
1425 sun8i_codec_set_hmic_bias(scodec, enable: false);
1426
1427 snd_soc_jack_report(jack: scodec->jack, status: 0, mask: scodec->jack_type);
1428 }
1429}
1430
1431static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id)
1432{
1433 struct sun8i_codec *scodec = dev_id;
1434 int type = SND_JACK_HEADSET;
1435 unsigned int status, value;
1436
1437 guard(mutex)(T: &scodec->jack_mutex);
1438
1439 regmap_read(map: scodec->regmap, SUN8I_HMIC_STS, val: &status);
1440 regmap_write(map: scodec->regmap, SUN8I_HMIC_STS, val: status);
1441
1442 /*
1443 * De-bounce in/out interrupts via a delayed work re-scheduling to
1444 * 100ms after each interrupt..
1445 */
1446 if (status & BIT(SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)) {
1447 /*
1448 * Out interrupt has priority over in interrupt so that if
1449 * we get both, we assume the disconnected state, which is
1450 * safer.
1451 */
1452 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_OUT_IRQ_ST;
1453 mod_delayed_work(wq: system_power_efficient_wq, dwork: &scodec->jack_work,
1454 delay: msecs_to_jiffies(m: 100));
1455 } else if (status & BIT(SUN8I_HMIC_STS_JACK_IN_IRQ_ST)) {
1456 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_IN_IRQ_ST;
1457 mod_delayed_work(wq: system_power_efficient_wq, dwork: &scodec->jack_work,
1458 delay: msecs_to_jiffies(m: 100));
1459 } else if (status & BIT(SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST)) {
1460 /*
1461 * Ignore data interrupts until jack status turns to connected
1462 * state, which is after HMIC enable stabilization is completed.
1463 * Until then tha data are bogus.
1464 */
1465 if (scodec->jack_status != SUN8I_JACK_STATUS_CONNECTED)
1466 return IRQ_HANDLED;
1467
1468 value = (status & SUN8I_HMIC_STS_HMIC_DATA_MASK) >>
1469 SUN8I_HMIC_STS_HMIC_DATA;
1470
1471 /*
1472 * Assumes 60 mV per ADC LSB increment, 2V bias voltage, 2.2kOhm
1473 * bias resistor.
1474 */
1475 if (value == 0)
1476 type |= SND_JACK_BTN_0;
1477 else if (value == 1)
1478 type |= SND_JACK_BTN_3;
1479 else if (value <= 3)
1480 type |= SND_JACK_BTN_1;
1481 else if (value <= 8)
1482 type |= SND_JACK_BTN_2;
1483
1484 /*
1485 * De-bounce. Only report button after two consecutive A/D
1486 * samples are identical.
1487 */
1488 if (scodec->jack_last_sample >= 0 &&
1489 scodec->jack_last_sample == value)
1490 snd_soc_jack_report(jack: scodec->jack, status: type,
1491 mask: scodec->jack_type);
1492
1493 scodec->jack_last_sample = value;
1494 }
1495
1496 return IRQ_HANDLED;
1497}
1498
1499static int sun8i_codec_enable_jack_detect(struct snd_soc_component *component,
1500 struct snd_soc_jack *jack, void *data)
1501{
1502 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(c: component);
1503 struct platform_device *pdev = to_platform_device(component->dev);
1504 int ret;
1505
1506 if (!scodec->quirks->jack_detection)
1507 return 0;
1508
1509 scodec->jack = jack;
1510
1511 scodec->jack_irq = platform_get_irq(pdev, 0);
1512 if (scodec->jack_irq < 0)
1513 return scodec->jack_irq;
1514
1515 /* Reserved value required for jack IRQs to trigger. */
1516 regmap_write(map: scodec->regmap, SUN8I_HMIC_CTRL1,
1517 val: 0xf << SUN8I_HMIC_CTRL1_HMIC_N |
1518 0x0 << SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB |
1519 0x4 << SUN8I_HMIC_CTRL1_HMIC_M);
1520
1521 /* Sample the ADC at 128 Hz; bypass smooth filter. */
1522 regmap_write(map: scodec->regmap, SUN8I_HMIC_CTRL2,
1523 val: 0x0 << SUN8I_HMIC_CTRL2_HMIC_SAMPLE |
1524 0x17 << SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD |
1525 0x0 << SUN8I_HMIC_CTRL2_HMIC_SF);
1526
1527 /* Do not discard any MDATA, enable user written MDATA threshold. */
1528 regmap_write(map: scodec->regmap, SUN8I_HMIC_STS, val: 0);
1529
1530 regmap_set_bits(map: scodec->regmap, SUN8I_HMIC_CTRL1,
1531 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) |
1532 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN));
1533
1534 ret = devm_request_threaded_irq(dev: &pdev->dev, irq: scodec->jack_irq,
1535 NULL, thread_fn: sun8i_codec_jack_irq,
1536 IRQF_ONESHOT,
1537 devname: dev_name(dev: &pdev->dev), dev_id: scodec);
1538 if (ret)
1539 return ret;
1540
1541 return 0;
1542}
1543
1544static void sun8i_codec_disable_jack_detect(struct snd_soc_component *component)
1545{
1546 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(c: component);
1547
1548 if (!scodec->quirks->jack_detection)
1549 return;
1550
1551 devm_free_irq(dev: component->dev, irq: scodec->jack_irq, dev_id: scodec);
1552
1553 cancel_delayed_work_sync(dwork: &scodec->jack_work);
1554
1555 regmap_clear_bits(map: scodec->regmap, SUN8I_HMIC_CTRL1,
1556 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) |
1557 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN) |
1558 BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN));
1559
1560 scodec->jack = NULL;
1561}
1562
1563static int sun8i_codec_component_set_jack(struct snd_soc_component *component,
1564 struct snd_soc_jack *jack, void *data)
1565{
1566 int ret = 0;
1567
1568 if (jack)
1569 ret = sun8i_codec_enable_jack_detect(component, jack, data);
1570 else
1571 sun8i_codec_disable_jack_detect(component);
1572
1573 return ret;
1574}
1575
1576static const struct snd_soc_component_driver sun8i_soc_component = {
1577 .controls = sun8i_codec_controls,
1578 .num_controls = ARRAY_SIZE(sun8i_codec_controls),
1579 .dapm_widgets = sun8i_codec_dapm_widgets,
1580 .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),
1581 .dapm_routes = sun8i_codec_dapm_routes,
1582 .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes),
1583 .set_jack = sun8i_codec_component_set_jack,
1584 .probe = sun8i_codec_component_probe,
1585 .idle_bias_on = 1,
1586 .suspend_bias_off = 1,
1587 .endianness = 1,
1588};
1589
1590static bool sun8i_codec_volatile_reg(struct device *dev, unsigned int reg)
1591{
1592 return reg == SUN8I_HMIC_STS;
1593}
1594
1595static const struct regmap_config sun8i_codec_regmap_config = {
1596 .reg_bits = 32,
1597 .reg_stride = 4,
1598 .val_bits = 32,
1599 .volatile_reg = sun8i_codec_volatile_reg,
1600 .max_register = SUN8I_DAC_MXR_SRC,
1601
1602 .cache_type = REGCACHE_FLAT,
1603};
1604
1605static int sun8i_codec_probe(struct platform_device *pdev)
1606{
1607 struct sun8i_codec *scodec;
1608 void __iomem *base;
1609 int ret;
1610
1611 scodec = devm_kzalloc(dev: &pdev->dev, size: sizeof(*scodec), GFP_KERNEL);
1612 if (!scodec)
1613 return -ENOMEM;
1614
1615 scodec->quirks = of_device_get_match_data(dev: &pdev->dev);
1616 INIT_DELAYED_WORK(&scodec->jack_work, sun8i_codec_jack_work);
1617 mutex_init(&scodec->jack_mutex);
1618
1619 platform_set_drvdata(pdev, data: scodec);
1620
1621 if (scodec->quirks->bus_clock) {
1622 scodec->clk_bus = devm_clk_get(dev: &pdev->dev, id: "bus");
1623 if (IS_ERR(ptr: scodec->clk_bus)) {
1624 dev_err(&pdev->dev, "Failed to get the bus clock\n");
1625 return PTR_ERR(ptr: scodec->clk_bus);
1626 }
1627 }
1628
1629 scodec->clk_module = devm_clk_get(dev: &pdev->dev, id: "mod");
1630 if (IS_ERR(ptr: scodec->clk_module)) {
1631 dev_err(&pdev->dev, "Failed to get the module clock\n");
1632 return PTR_ERR(ptr: scodec->clk_module);
1633 }
1634
1635 base = devm_platform_ioremap_resource(pdev, index: 0);
1636 if (IS_ERR(ptr: base)) {
1637 dev_err(&pdev->dev, "Failed to map the registers\n");
1638 return PTR_ERR(ptr: base);
1639 }
1640
1641 scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
1642 &sun8i_codec_regmap_config);
1643 if (IS_ERR(ptr: scodec->regmap)) {
1644 dev_err(&pdev->dev, "Failed to create our regmap\n");
1645 return PTR_ERR(ptr: scodec->regmap);
1646 }
1647
1648 regcache_cache_only(map: scodec->regmap, enable: true);
1649 pm_runtime_enable(dev: &pdev->dev);
1650 if (!pm_runtime_enabled(dev: &pdev->dev)) {
1651 ret = sun8i_codec_runtime_resume(dev: &pdev->dev);
1652 if (ret)
1653 goto err_pm_disable;
1654 }
1655
1656 ret = devm_snd_soc_register_component(dev: &pdev->dev, component_driver: &sun8i_soc_component,
1657 dai_drv: sun8i_codec_dais,
1658 ARRAY_SIZE(sun8i_codec_dais));
1659 if (ret) {
1660 dev_err(&pdev->dev, "Failed to register codec\n");
1661 goto err_suspend;
1662 }
1663
1664 return ret;
1665
1666err_suspend:
1667 if (!pm_runtime_status_suspended(dev: &pdev->dev))
1668 sun8i_codec_runtime_suspend(dev: &pdev->dev);
1669
1670err_pm_disable:
1671 pm_runtime_disable(dev: &pdev->dev);
1672
1673 return ret;
1674}
1675
1676static void sun8i_codec_remove(struct platform_device *pdev)
1677{
1678 pm_runtime_disable(dev: &pdev->dev);
1679 if (!pm_runtime_status_suspended(dev: &pdev->dev))
1680 sun8i_codec_runtime_suspend(dev: &pdev->dev);
1681}
1682
1683static const struct sun8i_codec_quirks sun8i_a33_quirks = {
1684 .bus_clock = true,
1685 .legacy_widgets = true,
1686 .lrck_inversion = true,
1687};
1688
1689static const struct sun8i_codec_quirks sun50i_a64_quirks = {
1690 .bus_clock = true,
1691 .jack_detection = true,
1692};
1693
1694static const struct of_device_id sun8i_codec_of_match[] = {
1695 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },
1696 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },
1697 {}
1698};
1699MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
1700
1701static const struct dev_pm_ops sun8i_codec_pm_ops = {
1702 RUNTIME_PM_OPS(sun8i_codec_runtime_suspend,
1703 sun8i_codec_runtime_resume, NULL)
1704};
1705
1706static struct platform_driver sun8i_codec_driver = {
1707 .driver = {
1708 .name = "sun8i-codec",
1709 .of_match_table = sun8i_codec_of_match,
1710 .pm = pm_ptr(&sun8i_codec_pm_ops),
1711 },
1712 .probe = sun8i_codec_probe,
1713 .remove = sun8i_codec_remove,
1714};
1715module_platform_driver(sun8i_codec_driver);
1716
1717MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
1718MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
1719MODULE_LICENSE("GPL");
1720MODULE_ALIAS("platform:sun8i-codec");
1721

source code of linux/sound/soc/sunxi/sun8i-codec.c