1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This driver supports the digital controls for the internal codec
4 * found in Allwinner's A33 SoCs.
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>
12 #include <linux/module.h>
13 #include <linux/delay.h>
14 #include <linux/clk.h>
15 #include <linux/input.h>
17 #include <linux/irq.h>
18 #include <linux/mutex.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/log2.h>
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>
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
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)
174 #define SUN8I_CODEC_BUTTONS (SND_JACK_BTN_0|\
179 #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
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)
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 |\
202 struct sun8i_codec_aif
{
203 unsigned int lrck_div_order
;
204 unsigned int sample_rate
;
206 unsigned int slot_width
;
207 unsigned int active_streams
: 2;
208 unsigned int open_streams
: 2;
211 struct sun8i_codec_quirks
{
213 bool jack_detection
: 1;
214 bool legacy_widgets
: 1;
215 bool lrck_inversion
: 1;
219 SUN8I_JACK_STATUS_DISCONNECTED
,
220 SUN8I_JACK_STATUS_WAITING_HBIAS
,
221 SUN8I_JACK_STATUS_CONNECTED
,
225 struct snd_soc_component
*component
;
226 struct regmap
*regmap
;
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
;
236 int jack_last_sample
;
237 ktime_t jack_hbias_ready
;
238 struct mutex jack_mutex
;
240 unsigned int sysclk_rate
;
244 static struct snd_soc_dai_driver sun8i_codec_dais
[];
246 static int sun8i_codec_runtime_resume(struct device
*dev
)
248 struct sun8i_codec
*scodec
= dev_get_drvdata(dev
);
251 if (scodec
->clk_bus
) {
252 ret
= clk_prepare_enable(scodec
->clk_bus
);
254 dev_err(dev
, "Failed to enable the bus clock\n");
259 regcache_cache_only(scodec
->regmap
, false);
261 ret
= regcache_sync(scodec
->regmap
);
263 dev_err(dev
, "Failed to sync regmap cache\n");
270 static int sun8i_codec_runtime_suspend(struct device
*dev
)
272 struct sun8i_codec
*scodec
= dev_get_drvdata(dev
);
274 regcache_cache_only(scodec
->regmap
, true);
275 regcache_mark_dirty(scodec
->regmap
);
278 clk_disable_unprepare(scodec
->clk_bus
);
283 static int sun8i_codec_get_hw_rate(unsigned int sample_rate
)
285 switch (sample_rate
) {
318 static int sun8i_codec_update_sample_rate(struct sun8i_codec
*scodec
)
320 unsigned int max_rate
= 0;
323 for (i
= SUN8I_CODEC_AIF1
; i
< SUN8I_CODEC_NAIFS
; ++i
) {
324 struct sun8i_codec_aif
*aif
= &scodec
->aifs
[i
];
326 if (aif
->active_streams
)
327 max_rate
= max(max_rate
, aif
->sample_rate
);
330 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */
332 max_rate
= SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE
;
334 hw_rate
= sun8i_codec_get_hw_rate(max_rate
);
338 regmap_update_bits(scodec
->regmap
, SUN8I_SYS_SR_CTRL
,
339 SUN8I_SYS_SR_CTRL_AIF1_FS_MASK
,
340 hw_rate
<< SUN8I_SYS_SR_CTRL_AIF1_FS
);
345 static int sun8i_codec_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
347 struct sun8i_codec
*scodec
= snd_soc_dai_get_drvdata(dai
);
348 u32 dsp_format
, format
, invert
, value
;
351 switch (fmt
& SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK
) {
352 case SND_SOC_DAIFMT_CBC_CFC
: /* Codec slave, DAI master */
355 case SND_SOC_DAIFMT_CBP_CFP
: /* Codec Master, DAI slave */
362 if (dai
->id
== SUN8I_CODEC_AIF3
) {
363 /* AIF3 only supports master mode. */
367 /* Use the AIF2 BCLK and LRCK for AIF3. */
368 regmap_update_bits(scodec
->regmap
, SUN8I_AIF_CLK_CTRL(dai
->id
),
369 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK
,
370 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2
);
372 regmap_update_bits(scodec
->regmap
, SUN8I_AIF_CLK_CTRL(dai
->id
),
373 BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD
),
374 value
<< SUN8I_AIF_CLK_CTRL_MSTR_MOD
);
378 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
379 case SND_SOC_DAIFMT_I2S
:
382 case SND_SOC_DAIFMT_LEFT_J
:
385 case SND_SOC_DAIFMT_RIGHT_J
:
388 case SND_SOC_DAIFMT_DSP_A
:
390 dsp_format
= 0x0; /* Set LRCK_INV to 0 */
392 case SND_SOC_DAIFMT_DSP_B
:
394 dsp_format
= 0x1; /* Set LRCK_INV to 1 */
400 if (dai
->id
== SUN8I_CODEC_AIF3
) {
401 /* AIF3 only supports DSP mode. */
405 regmap_update_bits(scodec
->regmap
, SUN8I_AIF_CLK_CTRL(dai
->id
),
406 SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK
,
407 format
<< SUN8I_AIF_CLK_CTRL_DATA_FMT
);
410 /* clock inversion */
411 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
412 case SND_SOC_DAIFMT_NB_NF
: /* Normal */
415 case SND_SOC_DAIFMT_NB_IF
: /* Inverted LRCK */
418 case SND_SOC_DAIFMT_IB_NF
: /* Inverted BCLK */
421 case SND_SOC_DAIFMT_IB_IF
: /* Both inverted */
429 /* Inverted LRCK is not available in DSP mode. */
433 /* Instead, the bit selects between DSP A/B formats. */
434 invert
|= dsp_format
;
437 * It appears that the DAI and the codec in the A33 SoC don't
438 * share the same polarity for the LRCK signal when they mean
439 * 'normal' and 'inverted' in the datasheet.
441 * Since the DAI here is our regular i2s driver that have been
442 * tested with way more codecs than just this one, it means
443 * that the codec probably gets it backward, and we have to
444 * invert the value here.
446 invert
^= scodec
->quirks
->lrck_inversion
;
449 regmap_update_bits(scodec
->regmap
, SUN8I_AIF_CLK_CTRL(dai
->id
),
450 SUN8I_AIF_CLK_CTRL_CLK_INV_MASK
,
451 invert
<< SUN8I_AIF_CLK_CTRL_CLK_INV
);
456 static int sun8i_codec_set_tdm_slot(struct snd_soc_dai
*dai
,
457 unsigned int tx_mask
, unsigned int rx_mask
,
458 int slots
, int slot_width
)
460 struct sun8i_codec
*scodec
= snd_soc_dai_get_drvdata(dai
);
461 struct sun8i_codec_aif
*aif
= &scodec
->aifs
[dai
->id
];
463 if (slot_width
&& !is_power_of_2(slot_width
))
467 aif
->slot_width
= slot_width
;
472 static const unsigned int sun8i_codec_rates
[] = {
473 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000,
474 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000,
477 static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates
= {
478 .list
= sun8i_codec_rates
,
479 .count
= ARRAY_SIZE(sun8i_codec_rates
),
482 static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates
= {
483 .list
= sun8i_codec_rates
,
484 .count
= ARRAY_SIZE(sun8i_codec_rates
),
488 static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates
= {
489 .list
= sun8i_codec_rates
,
490 .count
= ARRAY_SIZE(sun8i_codec_rates
),
494 static int sun8i_codec_startup(struct snd_pcm_substream
*substream
,
495 struct snd_soc_dai
*dai
)
497 struct sun8i_codec
*scodec
= snd_soc_dai_get_drvdata(dai
);
498 const struct snd_pcm_hw_constraint_list
*list
;
500 /* hw_constraints is not relevant for codec2codec DAIs. */
501 if (dai
->id
!= SUN8I_CODEC_AIF1
)
504 if (!scodec
->sysclk_refcnt
)
505 list
= &sun8i_codec_all_rates
;
506 else if (scodec
->sysclk_rate
== 22579200)
507 list
= &sun8i_codec_22M_rates
;
508 else if (scodec
->sysclk_rate
== 24576000)
509 list
= &sun8i_codec_24M_rates
;
513 return snd_pcm_hw_constraint_list(substream
->runtime
, 0,
514 SNDRV_PCM_HW_PARAM_RATE
, list
);
517 struct sun8i_codec_clk_div
{
522 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div
[] = {
523 { .div
= 1, .val
= 0 },
524 { .div
= 2, .val
= 1 },
525 { .div
= 4, .val
= 2 },
526 { .div
= 6, .val
= 3 },
527 { .div
= 8, .val
= 4 },
528 { .div
= 12, .val
= 5 },
529 { .div
= 16, .val
= 6 },
530 { .div
= 24, .val
= 7 },
531 { .div
= 32, .val
= 8 },
532 { .div
= 48, .val
= 9 },
533 { .div
= 64, .val
= 10 },
534 { .div
= 96, .val
= 11 },
535 { .div
= 128, .val
= 12 },
536 { .div
= 192, .val
= 13 },
539 static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate
,
540 unsigned int lrck_div_order
,
541 unsigned int sample_rate
)
543 unsigned int div
= sysclk_rate
/ sample_rate
>> lrck_div_order
;
546 for (i
= 0; i
< ARRAY_SIZE(sun8i_codec_bclk_div
); i
++) {
547 const struct sun8i_codec_clk_div
*bdiv
= &sun8i_codec_bclk_div
[i
];
549 if (bdiv
->div
== div
)
556 static int sun8i_codec_get_lrck_div_order(unsigned int slots
,
557 unsigned int slot_width
)
559 unsigned int div
= slots
* slot_width
;
561 if (div
< 16 || div
> 256)
564 return order_base_2(div
);
567 static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate
)
569 return (sample_rate
% 4000) ? 22579200 : 24576000;
572 static int sun8i_codec_hw_params(struct snd_pcm_substream
*substream
,
573 struct snd_pcm_hw_params
*params
,
574 struct snd_soc_dai
*dai
)
576 struct sun8i_codec
*scodec
= snd_soc_dai_get_drvdata(dai
);
577 struct sun8i_codec_aif
*aif
= &scodec
->aifs
[dai
->id
];
578 unsigned int sample_rate
= params_rate(params
);
579 unsigned int slots
= aif
->slots
?: params_channels(params
);
580 unsigned int slot_width
= aif
->slot_width
?: params_width(params
);
581 unsigned int sysclk_rate
= sun8i_codec_get_sysclk_rate(sample_rate
);
582 int bclk_div
, lrck_div_order
, ret
, word_size
;
586 switch (params_width(params
)) {
603 regmap_update_bits(scodec
->regmap
, SUN8I_AIF_CLK_CTRL(dai
->id
),
604 SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK
,
605 word_size
<< SUN8I_AIF_CLK_CTRL_WORD_SIZ
);
607 /* LRCK divider (BCLK/LRCK ratio) */
608 lrck_div_order
= sun8i_codec_get_lrck_div_order(slots
, slot_width
);
609 if (lrck_div_order
< 0)
610 return lrck_div_order
;
612 if (dai
->id
== SUN8I_CODEC_AIF2
|| dai
->id
== SUN8I_CODEC_AIF3
) {
613 /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */
614 int partner
= (SUN8I_CODEC_AIF2
+ SUN8I_CODEC_AIF3
) - dai
->id
;
615 const struct sun8i_codec_aif
*partner_aif
= &scodec
->aifs
[partner
];
616 const char *partner_name
= sun8i_codec_dais
[partner
].name
;
618 if (partner_aif
->open_streams
&&
619 (lrck_div_order
!= partner_aif
->lrck_div_order
||
620 sample_rate
!= partner_aif
->sample_rate
)) {
622 "%s sample and bit rates must match %s when both are used\n",
623 dai
->name
, partner_name
);
627 clk_reg
= SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2
);
629 clk_reg
= SUN8I_AIF_CLK_CTRL(dai
->id
);
632 regmap_update_bits(scodec
->regmap
, clk_reg
,
633 SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK
,
634 (lrck_div_order
- 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV
);
636 /* BCLK divider (SYSCLK/BCLK ratio) */
637 bclk_div
= sun8i_codec_get_bclk_div(sysclk_rate
, lrck_div_order
, sample_rate
);
641 regmap_update_bits(scodec
->regmap
, clk_reg
,
642 SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK
,
643 bclk_div
<< SUN8I_AIF_CLK_CTRL_BCLK_DIV
);
648 * Clock rate protection is reference counted; but hw_params may be
649 * called many times per substream, without matching calls to hw_free.
650 * Protect the clock rate once per AIF, on the first hw_params call
651 * for the first substream. clk_set_rate() will allow clock rate
652 * changes on subsequent calls if only one AIF has open streams.
654 ret
= (aif
->open_streams
? clk_set_rate
: clk_set_rate_exclusive
)(scodec
->clk_module
,
658 "%s sample rate (%u Hz) conflicts with other audio streams\n",
659 dai
->name
, sample_rate
);
663 if (!aif
->open_streams
)
664 scodec
->sysclk_refcnt
++;
665 scodec
->sysclk_rate
= sysclk_rate
;
667 aif
->lrck_div_order
= lrck_div_order
;
668 aif
->sample_rate
= sample_rate
;
669 aif
->open_streams
|= BIT(substream
->stream
);
671 return sun8i_codec_update_sample_rate(scodec
);
674 static int sun8i_codec_hw_free(struct snd_pcm_substream
*substream
,
675 struct snd_soc_dai
*dai
)
677 struct sun8i_codec
*scodec
= snd_soc_dai_get_drvdata(dai
);
678 struct sun8i_codec_aif
*aif
= &scodec
->aifs
[dai
->id
];
680 /* Drop references when the last substream for the AIF is freed. */
681 if (aif
->open_streams
!= BIT(substream
->stream
))
684 clk_rate_exclusive_put(scodec
->clk_module
);
685 scodec
->sysclk_refcnt
--;
686 aif
->lrck_div_order
= 0;
687 aif
->sample_rate
= 0;
690 aif
->open_streams
&= ~BIT(substream
->stream
);
694 static const struct snd_soc_dai_ops sun8i_codec_dai_ops
= {
695 .set_fmt
= sun8i_codec_set_fmt
,
696 .set_tdm_slot
= sun8i_codec_set_tdm_slot
,
697 .startup
= sun8i_codec_startup
,
698 .hw_params
= sun8i_codec_hw_params
,
699 .hw_free
= sun8i_codec_hw_free
,
702 static struct snd_soc_dai_driver sun8i_codec_dais
[] = {
704 .name
= "sun8i-codec-aif1",
705 .id
= SUN8I_CODEC_AIF1
,
706 .ops
= &sun8i_codec_dai_ops
,
707 /* capture capabilities */
709 .stream_name
= "AIF1 Capture",
712 .rates
= SUN8I_CODEC_PCM_RATES
,
713 .formats
= SUN8I_CODEC_PCM_FORMATS
,
716 /* playback capabilities */
718 .stream_name
= "AIF1 Playback",
721 .rates
= SUN8I_CODEC_PCM_RATES
,
722 .formats
= SUN8I_CODEC_PCM_FORMATS
,
724 .symmetric_rate
= true,
725 .symmetric_channels
= true,
726 .symmetric_sample_bits
= true,
729 .name
= "sun8i-codec-aif2",
730 .id
= SUN8I_CODEC_AIF2
,
731 .ops
= &sun8i_codec_dai_ops
,
732 /* capture capabilities */
734 .stream_name
= "AIF2 Capture",
737 .rates
= SUN8I_CODEC_PCM_RATES
,
738 .formats
= SUN8I_CODEC_PCM_FORMATS
,
741 /* playback capabilities */
743 .stream_name
= "AIF2 Playback",
746 .rates
= SUN8I_CODEC_PCM_RATES
,
747 .formats
= SUN8I_CODEC_PCM_FORMATS
,
749 .symmetric_rate
= true,
750 .symmetric_channels
= true,
751 .symmetric_sample_bits
= true,
754 .name
= "sun8i-codec-aif3",
755 .id
= SUN8I_CODEC_AIF3
,
756 .ops
= &sun8i_codec_dai_ops
,
757 /* capture capabilities */
759 .stream_name
= "AIF3 Capture",
762 .rates
= SUN8I_CODEC_PCM_RATES
,
763 .formats
= SUN8I_CODEC_PCM_FORMATS
,
766 /* playback capabilities */
768 .stream_name
= "AIF3 Playback",
771 .rates
= SUN8I_CODEC_PCM_RATES
,
772 .formats
= SUN8I_CODEC_PCM_FORMATS
,
774 .symmetric_rate
= true,
775 .symmetric_channels
= true,
776 .symmetric_sample_bits
= true,
780 static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale
, -12000, 75, 1);
782 static const struct snd_kcontrol_new sun8i_codec_controls
[] = {
783 SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume",
784 SUN8I_AIF1_VOL_CTRL1
,
785 SUN8I_AIF1_VOL_CTRL1_AD0L_VOL
,
786 SUN8I_AIF1_VOL_CTRL1_AD0R_VOL
,
787 0xc0, 0, sun8i_codec_vol_scale
),
788 SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume",
789 SUN8I_AIF1_VOL_CTRL3
,
790 SUN8I_AIF1_VOL_CTRL3_DA0L_VOL
,
791 SUN8I_AIF1_VOL_CTRL3_DA0R_VOL
,
792 0xc0, 0, sun8i_codec_vol_scale
),
793 SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",
794 SUN8I_AIF2_VOL_CTRL1
,
795 SUN8I_AIF2_VOL_CTRL1_ADCL_VOL
,
796 SUN8I_AIF2_VOL_CTRL1_ADCR_VOL
,
797 0xc0, 0, sun8i_codec_vol_scale
),
798 SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",
799 SUN8I_AIF2_VOL_CTRL2
,
800 SUN8I_AIF2_VOL_CTRL2_DACL_VOL
,
801 SUN8I_AIF2_VOL_CTRL2_DACR_VOL
,
802 0xc0, 0, sun8i_codec_vol_scale
),
803 SOC_DOUBLE_TLV("ADC Capture Volume",
805 SUN8I_ADC_VOL_CTRL_ADCL_VOL
,
806 SUN8I_ADC_VOL_CTRL_ADCR_VOL
,
807 0xc0, 0, sun8i_codec_vol_scale
),
808 SOC_DOUBLE_TLV("DAC Playback Volume",
810 SUN8I_DAC_VOL_CTRL_DACL_VOL
,
811 SUN8I_DAC_VOL_CTRL_DACR_VOL
,
812 0xc0, 0, sun8i_codec_vol_scale
),
815 static int sun8i_codec_aif_event(struct snd_soc_dapm_widget
*w
,
816 struct snd_kcontrol
*kcontrol
, int event
)
818 struct snd_soc_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
819 struct sun8i_codec
*scodec
= snd_soc_component_get_drvdata(component
);
820 struct sun8i_codec_aif
*aif
= &scodec
->aifs
[w
->sname
[3] - '1'];
821 int stream
= w
->id
== snd_soc_dapm_aif_out
;
823 if (SND_SOC_DAPM_EVENT_ON(event
))
824 aif
->active_streams
|= BIT(stream
);
826 aif
->active_streams
&= ~BIT(stream
);
828 return sun8i_codec_update_sample_rate(scodec
);
831 static const char *const sun8i_aif_stereo_mux_enum_values
[] = {
832 "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
835 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum
,
836 SUN8I_AIF1_ADCDAT_CTRL
,
837 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC
,
838 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC
,
839 sun8i_aif_stereo_mux_enum_values
);
841 static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control
=
842 SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",
843 sun8i_aif1_ad0_stereo_mux_enum
);
845 static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum
,
846 SUN8I_AIF2_ADCDAT_CTRL
,
847 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC
,
848 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC
,
849 sun8i_aif_stereo_mux_enum_values
);
851 static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control
=
852 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
853 sun8i_aif2_adc_stereo_mux_enum
);
855 static const char *const sun8i_aif3_adc_mux_enum_values
[] = {
856 "None", "AIF2 ADCL", "AIF2 ADCR"
859 static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum
,
860 SUN8I_AIF3_PATH_CTRL
,
861 SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC
,
862 sun8i_aif3_adc_mux_enum_values
);
864 static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control
=
865 SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",
866 sun8i_aif3_adc_mux_enum
);
868 static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls
[] = {
869 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
871 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L
,
872 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R
, 1, 0),
873 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
875 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL
,
876 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR
, 1, 0),
877 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
879 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL
,
880 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR
, 1, 0),
881 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
883 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR
,
884 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL
, 1, 0),
887 static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls
[] = {
888 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
890 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L
,
891 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R
, 1, 0),
892 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
894 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L
,
895 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R
, 1, 0),
896 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
898 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR
,
899 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL
, 1, 0),
900 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
902 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL
,
903 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR
, 1, 0),
906 static const char *const sun8i_aif2_dac_mux_enum_values
[] = {
907 "AIF2", "AIF3+2", "AIF2+3"
910 static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum
,
911 SUN8I_AIF3_PATH_CTRL
,
912 SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC
,
913 sun8i_aif2_dac_mux_enum_values
);
915 static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control
=
916 SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",
917 sun8i_aif2_dac_mux_enum
);
919 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum
,
920 SUN8I_AIF1_DACDAT_CTRL
,
921 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC
,
922 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC
,
923 sun8i_aif_stereo_mux_enum_values
);
925 static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control
=
926 SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",
927 sun8i_aif1_da0_stereo_mux_enum
);
929 static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum
,
930 SUN8I_AIF2_DACDAT_CTRL
,
931 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC
,
932 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC
,
933 sun8i_aif_stereo_mux_enum_values
);
935 static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control
=
936 SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",
937 sun8i_aif2_dac_stereo_mux_enum
);
939 static const struct snd_kcontrol_new sun8i_dac_mixer_controls
[] = {
940 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
942 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L
,
943 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R
, 1, 0),
944 SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
946 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L
,
947 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R
, 1, 0),
948 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC
,
949 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL
,
950 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR
, 1, 0),
951 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC
,
952 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL
,
953 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR
, 1, 0),
956 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets
[] = {
958 SND_SOC_DAPM_CLOCK_SUPPLY("mod"),
960 SND_SOC_DAPM_SUPPLY("AIF1CLK",
962 SUN8I_SYSCLK_CTL_AIF1CLK_ENA
, 0, NULL
, 0),
963 SND_SOC_DAPM_SUPPLY("AIF2CLK",
965 SUN8I_SYSCLK_CTL_AIF2CLK_ENA
, 0, NULL
, 0),
966 SND_SOC_DAPM_SUPPLY("SYSCLK",
968 SUN8I_SYSCLK_CTL_SYSCLK_ENA
, 0, NULL
, 0),
971 SND_SOC_DAPM_SUPPLY("CLK AIF1",
973 SUN8I_MOD_CLK_ENA_AIF1
, 0, NULL
, 0),
974 SND_SOC_DAPM_SUPPLY("CLK AIF2",
976 SUN8I_MOD_CLK_ENA_AIF2
, 0, NULL
, 0),
977 SND_SOC_DAPM_SUPPLY("CLK AIF3",
979 SUN8I_MOD_CLK_ENA_AIF3
, 0, NULL
, 0),
980 SND_SOC_DAPM_SUPPLY("CLK ADC",
982 SUN8I_MOD_CLK_ENA_ADC
, 0, NULL
, 0),
983 SND_SOC_DAPM_SUPPLY("CLK DAC",
985 SUN8I_MOD_CLK_ENA_DAC
, 0, NULL
, 0),
988 SND_SOC_DAPM_SUPPLY("RST AIF1",
990 SUN8I_MOD_RST_CTL_AIF1
, 0, NULL
, 0),
991 SND_SOC_DAPM_SUPPLY("RST AIF2",
993 SUN8I_MOD_RST_CTL_AIF2
, 0, NULL
, 0),
994 SND_SOC_DAPM_SUPPLY("RST AIF3",
996 SUN8I_MOD_RST_CTL_AIF3
, 0, NULL
, 0),
997 SND_SOC_DAPM_SUPPLY("RST ADC",
999 SUN8I_MOD_RST_CTL_ADC
, 0, NULL
, 0),
1000 SND_SOC_DAPM_SUPPLY("RST DAC",
1002 SUN8I_MOD_RST_CTL_DAC
, 0, NULL
, 0),
1004 /* Module Supplies */
1005 SND_SOC_DAPM_SUPPLY("ADC",
1007 SUN8I_ADC_DIG_CTRL_ENAD
, 0, NULL
, 0),
1008 SND_SOC_DAPM_SUPPLY("DAC",
1010 SUN8I_DAC_DIG_CTRL_ENDA
, 0, NULL
, 0),
1012 /* AIF "ADC" Outputs */
1013 SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0,
1014 SUN8I_AIF1_ADCDAT_CTRL
,
1015 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA
, 0,
1016 sun8i_codec_aif_event
,
1017 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1018 SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
1019 SUN8I_AIF1_ADCDAT_CTRL
,
1020 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA
, 0),
1022 SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,
1023 SUN8I_AIF2_ADCDAT_CTRL
,
1024 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA
, 0,
1025 sun8i_codec_aif_event
,
1026 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1027 SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,
1028 SUN8I_AIF2_ADCDAT_CTRL
,
1029 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA
, 0),
1031 SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,
1033 sun8i_codec_aif_event
,
1034 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1036 /* AIF "ADC" Mono/Stereo Muxes */
1037 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM
, 0, 0,
1038 &sun8i_aif1_ad0_stereo_mux_control
),
1039 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM
, 0, 0,
1040 &sun8i_aif1_ad0_stereo_mux_control
),
1042 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM
, 0, 0,
1043 &sun8i_aif2_adc_stereo_mux_control
),
1044 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM
, 0, 0,
1045 &sun8i_aif2_adc_stereo_mux_control
),
1047 /* AIF "ADC" Output Muxes */
1048 SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM
, 0, 0,
1049 &sun8i_aif3_adc_mux_control
),
1051 /* AIF "ADC" Mixers */
1052 SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM
, 0, 0,
1053 sun8i_aif1_ad0_mixer_controls
),
1054 SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM
, 0, 0,
1055 sun8i_aif1_ad0_mixer_controls
),
1057 SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM
, 0, 0,
1058 sun8i_aif2_adc_mixer_controls
),
1059 SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM
, 0, 0,
1060 sun8i_aif2_adc_mixer_controls
),
1062 /* AIF "DAC" Input Muxes */
1063 SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM
, 0, 0,
1064 &sun8i_aif2_dac_mux_control
),
1065 SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM
, 0, 0,
1066 &sun8i_aif2_dac_mux_control
),
1068 /* AIF "DAC" Mono/Stereo Muxes */
1069 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM
, 0, 0,
1070 &sun8i_aif1_da0_stereo_mux_control
),
1071 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM
, 0, 0,
1072 &sun8i_aif1_da0_stereo_mux_control
),
1074 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM
, 0, 0,
1075 &sun8i_aif2_dac_stereo_mux_control
),
1076 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM
, 0, 0,
1077 &sun8i_aif2_dac_stereo_mux_control
),
1079 /* AIF "DAC" Inputs */
1080 SND_SOC_DAPM_AIF_IN_E("AIF1 DA0L", "AIF1 Playback", 0,
1081 SUN8I_AIF1_DACDAT_CTRL
,
1082 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA
, 0,
1083 sun8i_codec_aif_event
,
1084 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1085 SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1,
1086 SUN8I_AIF1_DACDAT_CTRL
,
1087 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA
, 0),
1089 SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0,
1090 SUN8I_AIF2_DACDAT_CTRL
,
1091 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA
, 0,
1092 sun8i_codec_aif_event
,
1093 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1094 SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1,
1095 SUN8I_AIF2_DACDAT_CTRL
,
1096 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA
, 0),
1098 SND_SOC_DAPM_AIF_IN_E("AIF3 DAC", "AIF3 Playback", 0,
1100 sun8i_codec_aif_event
,
1101 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
1103 /* ADC Inputs (connected to analog codec DAPM context) */
1104 SND_SOC_DAPM_ADC("ADCL", NULL
, SND_SOC_NOPM
, 0, 0),
1105 SND_SOC_DAPM_ADC("ADCR", NULL
, SND_SOC_NOPM
, 0, 0),
1107 /* DAC Outputs (connected to analog codec DAPM context) */
1108 SND_SOC_DAPM_DAC("DACL", NULL
, SND_SOC_NOPM
, 0, 0),
1109 SND_SOC_DAPM_DAC("DACR", NULL
, SND_SOC_NOPM
, 0, 0),
1112 SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM
, 0, 0,
1113 sun8i_dac_mixer_controls
),
1114 SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM
, 0, 0,
1115 sun8i_dac_mixer_controls
),
1118 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes
[] = {
1120 { "AIF1CLK", NULL
, "mod" },
1122 { "SYSCLK", NULL
, "AIF1CLK" },
1124 { "CLK AIF1", NULL
, "AIF1CLK" },
1125 { "CLK AIF1", NULL
, "SYSCLK" },
1126 { "RST AIF1", NULL
, "CLK AIF1" },
1127 { "AIF1 AD0L", NULL
, "RST AIF1" },
1128 { "AIF1 AD0R", NULL
, "RST AIF1" },
1129 { "AIF1 DA0L", NULL
, "RST AIF1" },
1130 { "AIF1 DA0R", NULL
, "RST AIF1" },
1132 { "CLK AIF2", NULL
, "AIF2CLK" },
1133 { "CLK AIF2", NULL
, "SYSCLK" },
1134 { "RST AIF2", NULL
, "CLK AIF2" },
1135 { "AIF2 ADCL", NULL
, "RST AIF2" },
1136 { "AIF2 ADCR", NULL
, "RST AIF2" },
1137 { "AIF2 DACL", NULL
, "RST AIF2" },
1138 { "AIF2 DACR", NULL
, "RST AIF2" },
1140 { "CLK AIF3", NULL
, "AIF1CLK" },
1141 { "CLK AIF3", NULL
, "SYSCLK" },
1142 { "RST AIF3", NULL
, "CLK AIF3" },
1143 { "AIF3 ADC", NULL
, "RST AIF3" },
1144 { "AIF3 DAC", NULL
, "RST AIF3" },
1146 { "CLK ADC", NULL
, "SYSCLK" },
1147 { "RST ADC", NULL
, "CLK ADC" },
1148 { "ADC", NULL
, "RST ADC" },
1149 { "ADCL", NULL
, "ADC" },
1150 { "ADCR", NULL
, "ADC" },
1152 { "CLK DAC", NULL
, "SYSCLK" },
1153 { "RST DAC", NULL
, "CLK DAC" },
1154 { "DAC", NULL
, "RST DAC" },
1155 { "DACL", NULL
, "DAC" },
1156 { "DACR", NULL
, "DAC" },
1158 /* AIF "ADC" Output Routes */
1159 { "AIF1 AD0L", NULL
, "AIF1 AD0L Stereo Mux" },
1160 { "AIF1 AD0R", NULL
, "AIF1 AD0R Stereo Mux" },
1162 { "AIF2 ADCL", NULL
, "AIF2 ADCL Stereo Mux" },
1163 { "AIF2 ADCR", NULL
, "AIF2 ADCR Stereo Mux" },
1165 { "AIF3 ADC", NULL
, "AIF3 ADC Source Capture Route" },
1167 /* AIF "ADC" Mono/Stereo Mux Routes */
1168 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" },
1169 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" },
1170 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1171 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1172 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1173 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1175 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" },
1176 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" },
1177 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1178 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1179 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1180 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1182 { "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" },
1183 { "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" },
1184 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1185 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1186 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1187 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1189 { "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" },
1190 { "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" },
1191 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1192 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1193 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1194 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1196 /* AIF "ADC" Output Mux Routes */
1197 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },
1198 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },
1200 /* AIF "ADC" Mixer Routes */
1201 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" },
1202 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },
1203 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },
1204 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },
1206 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" },
1207 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },
1208 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },
1209 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },
1211 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" },
1212 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" },
1213 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" },
1215 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" },
1216 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" },
1217 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" },
1219 /* AIF "DAC" Input Mux Routes */
1220 { "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" },
1221 { "AIF2 DACL Source", "AIF3+2", "AIF3 DAC" },
1222 { "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" },
1224 { "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" },
1225 { "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" },
1226 { "AIF2 DACR Source", "AIF2+3", "AIF3 DAC" },
1228 /* AIF "DAC" Mono/Stereo Mux Routes */
1229 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" },
1230 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" },
1231 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1232 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1233 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1234 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1236 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" },
1237 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" },
1238 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1239 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1240 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1241 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1243 { "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" },
1244 { "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" },
1245 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" },
1246 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" },
1247 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" },
1248 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" },
1250 { "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" },
1251 { "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" },
1252 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" },
1253 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" },
1254 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" },
1255 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" },
1257 /* DAC Output Routes */
1258 { "DACL", NULL
, "DACL Mixer" },
1259 { "DACR", NULL
, "DACR Mixer" },
1261 /* DAC Mixer Routes */
1262 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" },
1263 { "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" },
1264 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
1266 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" },
1267 { "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" },
1268 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" },
1271 static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets
[] = {
1272 /* Legacy ADC Inputs (connected to analog codec DAPM context) */
1273 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL
, SND_SOC_NOPM
, 0, 0),
1274 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL
, SND_SOC_NOPM
, 0, 0),
1276 /* Legacy DAC Outputs (connected to analog codec DAPM context) */
1277 SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL
, SND_SOC_NOPM
, 0, 0),
1278 SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL
, SND_SOC_NOPM
, 0, 0),
1281 static const struct snd_soc_dapm_route sun8i_codec_legacy_routes
[] = {
1282 /* Legacy ADC Routes */
1283 { "ADCL", NULL
, "AIF1 Slot 0 Left ADC" },
1284 { "ADCR", NULL
, "AIF1 Slot 0 Right ADC" },
1286 /* Legacy DAC Routes */
1287 { "AIF1 Slot 0 Left", NULL
, "DACL" },
1288 { "AIF1 Slot 0 Right", NULL
, "DACR" },
1291 static int sun8i_codec_component_probe(struct snd_soc_component
*component
)
1293 struct snd_soc_dapm_context
*dapm
= snd_soc_component_get_dapm(component
);
1294 struct sun8i_codec
*scodec
= snd_soc_component_get_drvdata(component
);
1297 scodec
->component
= component
;
1299 /* Add widgets for backward compatibility with old device trees. */
1300 if (scodec
->quirks
->legacy_widgets
) {
1301 ret
= snd_soc_dapm_new_controls(dapm
, sun8i_codec_legacy_widgets
,
1302 ARRAY_SIZE(sun8i_codec_legacy_widgets
));
1306 ret
= snd_soc_dapm_add_routes(dapm
, sun8i_codec_legacy_routes
,
1307 ARRAY_SIZE(sun8i_codec_legacy_routes
));
1313 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod")
1314 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also
1315 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO
1316 * directly to simplify the clock tree.
1318 regmap_update_bits(scodec
->regmap
, SUN8I_SYSCLK_CTL
,
1319 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK
|
1320 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK
,
1321 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL
|
1322 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL
);
1324 /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */
1325 regmap_update_bits(scodec
->regmap
, SUN8I_SYSCLK_CTL
,
1326 BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC
),
1327 SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK
);
1329 /* Program the default sample rate. */
1330 sun8i_codec_update_sample_rate(scodec
);
1335 static void sun8i_codec_set_hmic_bias(struct sun8i_codec
*scodec
, bool enable
)
1337 struct snd_soc_dapm_context
*dapm
= &scodec
->component
->card
->dapm
;
1338 int irq_mask
= BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN
);
1341 snd_soc_dapm_force_enable_pin(dapm
, "HBIAS");
1343 snd_soc_dapm_disable_pin(dapm
, "HBIAS");
1345 snd_soc_dapm_sync(dapm
);
1347 regmap_update_bits(scodec
->regmap
, SUN8I_HMIC_CTRL1
,
1348 irq_mask
, enable
? irq_mask
: 0);
1351 static void sun8i_codec_jack_work(struct work_struct
*work
)
1353 struct sun8i_codec
*scodec
= container_of(work
, struct sun8i_codec
,
1358 guard(mutex
)(&scodec
->jack_mutex
);
1360 if (scodec
->jack_status
== SUN8I_JACK_STATUS_DISCONNECTED
) {
1361 if (scodec
->last_hmic_irq
!= SUN8I_HMIC_STS_JACK_IN_IRQ_ST
)
1364 scodec
->jack_last_sample
= -1;
1366 if (scodec
->jack_type
& SND_JACK_MICROPHONE
) {
1368 * If we were in disconnected state, we enable HBIAS and
1369 * wait 600ms before reading initial HDATA value.
1371 scodec
->jack_hbias_ready
= ktime_add_ms(ktime_get(), 600);
1372 sun8i_codec_set_hmic_bias(scodec
, true);
1373 queue_delayed_work(system_power_efficient_wq
,
1375 msecs_to_jiffies(610));
1376 scodec
->jack_status
= SUN8I_JACK_STATUS_WAITING_HBIAS
;
1378 snd_soc_jack_report(scodec
->jack
, SND_JACK_HEADPHONE
,
1380 scodec
->jack_status
= SUN8I_JACK_STATUS_CONNECTED
;
1382 } else if (scodec
->jack_status
== SUN8I_JACK_STATUS_WAITING_HBIAS
) {
1384 * If we're waiting for HBIAS to stabilize, and we get plug-out
1385 * interrupt and nothing more for > 100ms, just cancel the
1388 if (scodec
->last_hmic_irq
== SUN8I_HMIC_STS_JACK_OUT_IRQ_ST
) {
1389 scodec
->jack_status
= SUN8I_JACK_STATUS_DISCONNECTED
;
1390 sun8i_codec_set_hmic_bias(scodec
, false);
1395 * If we're not done waiting for HBIAS to stabilize, wait more.
1397 if (!ktime_after(ktime_get(), scodec
->jack_hbias_ready
)) {
1398 s64 msecs
= ktime_ms_delta(scodec
->jack_hbias_ready
,
1401 queue_delayed_work(system_power_efficient_wq
,
1403 msecs_to_jiffies(msecs
+ 10));
1408 * Everything is stabilized, determine jack type and report it.
1410 regmap_read(scodec
->regmap
, SUN8I_HMIC_STS
, &mdata
);
1411 mdata
&= SUN8I_HMIC_STS_HMIC_DATA_MASK
;
1412 mdata
>>= SUN8I_HMIC_STS_HMIC_DATA
;
1414 regmap_write(scodec
->regmap
, SUN8I_HMIC_STS
, 0);
1416 type
= mdata
< 16 ? SND_JACK_HEADPHONE
: SND_JACK_HEADSET
;
1417 if (type
== SND_JACK_HEADPHONE
)
1418 sun8i_codec_set_hmic_bias(scodec
, false);
1420 snd_soc_jack_report(scodec
->jack
, type
, scodec
->jack_type
);
1421 scodec
->jack_status
= SUN8I_JACK_STATUS_CONNECTED
;
1422 } else if (scodec
->jack_status
== SUN8I_JACK_STATUS_CONNECTED
) {
1423 if (scodec
->last_hmic_irq
!= SUN8I_HMIC_STS_JACK_OUT_IRQ_ST
)
1426 scodec
->jack_status
= SUN8I_JACK_STATUS_DISCONNECTED
;
1427 if (scodec
->jack_type
& SND_JACK_MICROPHONE
)
1428 sun8i_codec_set_hmic_bias(scodec
, false);
1430 snd_soc_jack_report(scodec
->jack
, 0, scodec
->jack_type
);
1434 static irqreturn_t
sun8i_codec_jack_irq(int irq
, void *dev_id
)
1436 struct sun8i_codec
*scodec
= dev_id
;
1437 int type
= SND_JACK_HEADSET
;
1438 unsigned int status
, value
;
1440 guard(mutex
)(&scodec
->jack_mutex
);
1442 regmap_read(scodec
->regmap
, SUN8I_HMIC_STS
, &status
);
1443 regmap_write(scodec
->regmap
, SUN8I_HMIC_STS
, status
);
1446 * De-bounce in/out interrupts via a delayed work re-scheduling to
1447 * 100ms after each interrupt..
1449 if (status
& BIT(SUN8I_HMIC_STS_JACK_OUT_IRQ_ST
)) {
1451 * Out interrupt has priority over in interrupt so that if
1452 * we get both, we assume the disconnected state, which is
1455 scodec
->last_hmic_irq
= SUN8I_HMIC_STS_JACK_OUT_IRQ_ST
;
1456 mod_delayed_work(system_power_efficient_wq
, &scodec
->jack_work
,
1457 msecs_to_jiffies(100));
1458 } else if (status
& BIT(SUN8I_HMIC_STS_JACK_IN_IRQ_ST
)) {
1459 scodec
->last_hmic_irq
= SUN8I_HMIC_STS_JACK_IN_IRQ_ST
;
1460 mod_delayed_work(system_power_efficient_wq
, &scodec
->jack_work
,
1461 msecs_to_jiffies(100));
1462 } else if (status
& BIT(SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST
)) {
1464 * Ignore data interrupts until jack status turns to connected
1465 * state, which is after HMIC enable stabilization is completed.
1466 * Until then tha data are bogus.
1468 if (scodec
->jack_status
!= SUN8I_JACK_STATUS_CONNECTED
)
1471 value
= (status
& SUN8I_HMIC_STS_HMIC_DATA_MASK
) >>
1472 SUN8I_HMIC_STS_HMIC_DATA
;
1475 * Assumes 60 mV per ADC LSB increment, 2V bias voltage, 2.2kOhm
1479 type
|= SND_JACK_BTN_0
;
1480 else if (value
== 1)
1481 type
|= SND_JACK_BTN_3
;
1482 else if (value
<= 3)
1483 type
|= SND_JACK_BTN_1
;
1484 else if (value
<= 8)
1485 type
|= SND_JACK_BTN_2
;
1488 * De-bounce. Only report button after two consecutive A/D
1489 * samples are identical.
1491 if (scodec
->jack_last_sample
>= 0 &&
1492 scodec
->jack_last_sample
== value
)
1493 snd_soc_jack_report(scodec
->jack
, type
,
1496 scodec
->jack_last_sample
= value
;
1502 static int sun8i_codec_enable_jack_detect(struct snd_soc_component
*component
,
1503 struct snd_soc_jack
*jack
, void *data
)
1505 struct sun8i_codec
*scodec
= snd_soc_component_get_drvdata(component
);
1506 struct platform_device
*pdev
= to_platform_device(component
->dev
);
1509 if (!scodec
->quirks
->jack_detection
)
1512 scodec
->jack
= jack
;
1514 scodec
->jack_irq
= platform_get_irq(pdev
, 0);
1515 if (scodec
->jack_irq
< 0)
1516 return scodec
->jack_irq
;
1518 /* Reserved value required for jack IRQs to trigger. */
1519 regmap_write(scodec
->regmap
, SUN8I_HMIC_CTRL1
,
1520 0xf << SUN8I_HMIC_CTRL1_HMIC_N
|
1521 0x0 << SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB
|
1522 0x4 << SUN8I_HMIC_CTRL1_HMIC_M
);
1524 /* Sample the ADC at 128 Hz; bypass smooth filter. */
1525 regmap_write(scodec
->regmap
, SUN8I_HMIC_CTRL2
,
1526 0x0 << SUN8I_HMIC_CTRL2_HMIC_SAMPLE
|
1527 0x17 << SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD
|
1528 0x0 << SUN8I_HMIC_CTRL2_HMIC_SF
);
1530 /* Do not discard any MDATA, enable user written MDATA threshold. */
1531 regmap_write(scodec
->regmap
, SUN8I_HMIC_STS
, 0);
1533 regmap_set_bits(scodec
->regmap
, SUN8I_HMIC_CTRL1
,
1534 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN
) |
1535 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN
));
1537 ret
= devm_request_threaded_irq(&pdev
->dev
, scodec
->jack_irq
,
1538 NULL
, sun8i_codec_jack_irq
,
1540 dev_name(&pdev
->dev
), scodec
);
1547 static void sun8i_codec_disable_jack_detect(struct snd_soc_component
*component
)
1549 struct sun8i_codec
*scodec
= snd_soc_component_get_drvdata(component
);
1551 if (!scodec
->quirks
->jack_detection
)
1554 devm_free_irq(component
->dev
, scodec
->jack_irq
, scodec
);
1556 cancel_delayed_work_sync(&scodec
->jack_work
);
1558 regmap_clear_bits(scodec
->regmap
, SUN8I_HMIC_CTRL1
,
1559 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN
) |
1560 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN
) |
1561 BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN
));
1563 scodec
->jack
= NULL
;
1566 static int sun8i_codec_component_set_jack(struct snd_soc_component
*component
,
1567 struct snd_soc_jack
*jack
, void *data
)
1572 ret
= sun8i_codec_enable_jack_detect(component
, jack
, data
);
1574 sun8i_codec_disable_jack_detect(component
);
1579 static const struct snd_soc_component_driver sun8i_soc_component
= {
1580 .controls
= sun8i_codec_controls
,
1581 .num_controls
= ARRAY_SIZE(sun8i_codec_controls
),
1582 .dapm_widgets
= sun8i_codec_dapm_widgets
,
1583 .num_dapm_widgets
= ARRAY_SIZE(sun8i_codec_dapm_widgets
),
1584 .dapm_routes
= sun8i_codec_dapm_routes
,
1585 .num_dapm_routes
= ARRAY_SIZE(sun8i_codec_dapm_routes
),
1586 .set_jack
= sun8i_codec_component_set_jack
,
1587 .probe
= sun8i_codec_component_probe
,
1589 .suspend_bias_off
= 1,
1593 static bool sun8i_codec_volatile_reg(struct device
*dev
, unsigned int reg
)
1595 return reg
== SUN8I_HMIC_STS
;
1598 static const struct regmap_config sun8i_codec_regmap_config
= {
1602 .volatile_reg
= sun8i_codec_volatile_reg
,
1603 .max_register
= SUN8I_DAC_MXR_SRC
,
1605 .cache_type
= REGCACHE_FLAT
,
1608 static int sun8i_codec_probe(struct platform_device
*pdev
)
1610 struct sun8i_codec
*scodec
;
1614 scodec
= devm_kzalloc(&pdev
->dev
, sizeof(*scodec
), GFP_KERNEL
);
1618 scodec
->quirks
= of_device_get_match_data(&pdev
->dev
);
1619 INIT_DELAYED_WORK(&scodec
->jack_work
, sun8i_codec_jack_work
);
1620 mutex_init(&scodec
->jack_mutex
);
1622 platform_set_drvdata(pdev
, scodec
);
1624 if (scodec
->quirks
->bus_clock
) {
1625 scodec
->clk_bus
= devm_clk_get(&pdev
->dev
, "bus");
1626 if (IS_ERR(scodec
->clk_bus
)) {
1627 dev_err(&pdev
->dev
, "Failed to get the bus clock\n");
1628 return PTR_ERR(scodec
->clk_bus
);
1632 scodec
->clk_module
= devm_clk_get(&pdev
->dev
, "mod");
1633 if (IS_ERR(scodec
->clk_module
)) {
1634 dev_err(&pdev
->dev
, "Failed to get the module clock\n");
1635 return PTR_ERR(scodec
->clk_module
);
1638 base
= devm_platform_ioremap_resource(pdev
, 0);
1640 dev_err(&pdev
->dev
, "Failed to map the registers\n");
1641 return PTR_ERR(base
);
1644 scodec
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, base
,
1645 &sun8i_codec_regmap_config
);
1646 if (IS_ERR(scodec
->regmap
)) {
1647 dev_err(&pdev
->dev
, "Failed to create our regmap\n");
1648 return PTR_ERR(scodec
->regmap
);
1651 regcache_cache_only(scodec
->regmap
, true);
1652 pm_runtime_enable(&pdev
->dev
);
1653 if (!pm_runtime_enabled(&pdev
->dev
)) {
1654 ret
= sun8i_codec_runtime_resume(&pdev
->dev
);
1656 goto err_pm_disable
;
1659 ret
= devm_snd_soc_register_component(&pdev
->dev
, &sun8i_soc_component
,
1661 ARRAY_SIZE(sun8i_codec_dais
));
1663 dev_err(&pdev
->dev
, "Failed to register codec\n");
1670 if (!pm_runtime_status_suspended(&pdev
->dev
))
1671 sun8i_codec_runtime_suspend(&pdev
->dev
);
1674 pm_runtime_disable(&pdev
->dev
);
1679 static void sun8i_codec_remove(struct platform_device
*pdev
)
1681 pm_runtime_disable(&pdev
->dev
);
1682 if (!pm_runtime_status_suspended(&pdev
->dev
))
1683 sun8i_codec_runtime_suspend(&pdev
->dev
);
1686 static const struct sun8i_codec_quirks sun8i_a33_quirks
= {
1688 .legacy_widgets
= true,
1689 .lrck_inversion
= true,
1692 static const struct sun8i_codec_quirks sun50i_a64_quirks
= {
1694 .jack_detection
= true,
1697 static const struct of_device_id sun8i_codec_of_match
[] = {
1698 { .compatible
= "allwinner,sun8i-a33-codec", .data
= &sun8i_a33_quirks
},
1699 { .compatible
= "allwinner,sun50i-a64-codec", .data
= &sun50i_a64_quirks
},
1702 MODULE_DEVICE_TABLE(of
, sun8i_codec_of_match
);
1704 static const struct dev_pm_ops sun8i_codec_pm_ops
= {
1705 SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend
,
1706 sun8i_codec_runtime_resume
, NULL
)
1709 static struct platform_driver sun8i_codec_driver
= {
1711 .name
= "sun8i-codec",
1712 .of_match_table
= sun8i_codec_of_match
,
1713 .pm
= &sun8i_codec_pm_ops
,
1715 .probe
= sun8i_codec_probe
,
1716 .remove
= sun8i_codec_remove
,
1718 module_platform_driver(sun8i_codec_driver
);
1720 MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
1721 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
1722 MODULE_LICENSE("GPL");
1723 MODULE_ALIAS("platform:sun8i-codec");