1 // SPDX-License-Identifier: GPL-2.0
3 // Ingenic JZ4770 CODEC driver
9 #include <linux/delay.h>
10 #include <linux/iopoll.h>
11 #include <linux/module.h>
12 #include <linux/regmap.h>
13 #include <linux/time64.h>
15 #include <sound/pcm_params.h>
16 #include <sound/soc.h>
17 #include <sound/soc-dai.h>
18 #include <sound/soc-dapm.h>
19 #include <sound/tlv.h>
21 #define ICDC_RGADW_OFFSET 0x00
22 #define ICDC_RGDATA_OFFSET 0x04
24 /* ICDC internal register access control register(RGADW) */
25 #define ICDC_RGADW_RGWR BIT(16)
27 #define ICDC_RGADW_RGADDR_OFFSET 8
28 #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
30 #define ICDC_RGADW_RGDIN_OFFSET 0
31 #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
33 /* ICDC internal register data output register (RGDATA)*/
34 #define ICDC_RGDATA_IRQ BIT(8)
36 #define ICDC_RGDATA_RGDOUT_OFFSET 0
37 #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
39 /* Internal register space, accessed through regmap */
42 JZ4770_CODEC_REG_AICR_DAC,
43 JZ4770_CODEC_REG_AICR_ADC,
44 JZ4770_CODEC_REG_CR_LO,
45 JZ4770_CODEC_REG_CR_HP,
47 JZ4770_CODEC_REG_MISSING_REG1,
49 JZ4770_CODEC_REG_CR_DAC,
50 JZ4770_CODEC_REG_CR_MIC,
51 JZ4770_CODEC_REG_CR_LI,
52 JZ4770_CODEC_REG_CR_ADC,
53 JZ4770_CODEC_REG_CR_MIX,
54 JZ4770_CODEC_REG_CR_VIC,
56 JZ4770_CODEC_REG_FCR_DAC,
57 JZ4770_CODEC_REG_FCR_ADC,
61 JZ4770_CODEC_REG_GCR_HPL,
62 JZ4770_CODEC_REG_GCR_HPR,
63 JZ4770_CODEC_REG_GCR_LIBYL,
64 JZ4770_CODEC_REG_GCR_LIBYR,
65 JZ4770_CODEC_REG_GCR_DACL,
66 JZ4770_CODEC_REG_GCR_DACR,
67 JZ4770_CODEC_REG_GCR_MIC1,
68 JZ4770_CODEC_REG_GCR_MIC2,
69 JZ4770_CODEC_REG_GCR_ADCL,
70 JZ4770_CODEC_REG_GCR_ADCR,
72 JZ4770_CODEC_REG_MISSING_REG2,
74 JZ4770_CODEC_REG_GCR_MIXADC,
75 JZ4770_CODEC_REG_GCR_MIXDAC,
76 JZ4770_CODEC_REG_AGC1,
77 JZ4770_CODEC_REG_AGC2,
78 JZ4770_CODEC_REG_AGC3,
79 JZ4770_CODEC_REG_AGC4,
80 JZ4770_CODEC_REG_AGC5,
83 #define REG_AICR_DAC_ADWL_OFFSET 6
84 #define REG_AICR_DAC_ADWL_MASK (0x3 << REG_AICR_DAC_ADWL_OFFSET)
85 #define REG_AICR_DAC_SERIAL BIT(1)
86 #define REG_AICR_DAC_I2S BIT(0)
88 #define REG_AICR_ADC_ADWL_OFFSET 6
89 #define REG_AICR_ADC_ADWL_MASK (0x3 << REG_AICR_ADC_ADWL_OFFSET)
90 #define REG_AICR_ADC_SERIAL BIT(1)
91 #define REG_AICR_ADC_I2S BIT(0)
93 #define REG_CR_LO_MUTE_OFFSET 7
94 #define REG_CR_LO_SB_OFFSET 4
95 #define REG_CR_LO_SEL_OFFSET 0
96 #define REG_CR_LO_SEL_MASK (0x3 << REG_CR_LO_SEL_OFFSET)
98 #define REG_CR_HP_MUTE BIT(7)
99 #define REG_CR_HP_LOAD BIT(6)
100 #define REG_CR_HP_SB_OFFSET 4
101 #define REG_CR_HP_SB_HPCM BIT(3)
102 #define REG_CR_HP_SEL_OFFSET 0
103 #define REG_CR_HP_SEL_MASK (0x3 << REG_CR_HP_SEL_OFFSET)
105 #define REG_CR_DAC_MUTE BIT(7)
106 #define REG_CR_DAC_MONO BIT(6)
107 #define REG_CR_DAC_LEFT_ONLY BIT(5)
108 #define REG_CR_DAC_SB_OFFSET 4
109 #define REG_CR_DAC_LRSWAP BIT(3)
111 #define REG_CR_MIC_STEREO_OFFSET 7
112 #define REG_CR_MIC_IDIFF_OFFSET 6
113 #define REG_CR_MIC_SB_MIC2_OFFSET 5
114 #define REG_CR_MIC_SB_MIC1_OFFSET 4
115 #define REG_CR_MIC_BIAS_V0_OFFSET 1
116 #define REG_CR_MIC_BIAS_SB_OFFSET 0
118 #define REG_CR_LI_LIBY_OFFSET 4
119 #define REG_CR_LI_SB_OFFSET 0
121 #define REG_CR_ADC_DMIC_SEL BIT(7)
122 #define REG_CR_ADC_MONO BIT(6)
123 #define REG_CR_ADC_LEFT_ONLY BIT(5)
124 #define REG_CR_ADC_SB_OFFSET 4
125 #define REG_CR_ADC_LRSWAP BIT(3)
126 #define REG_CR_ADC_IN_SEL_OFFSET 0
127 #define REG_CR_ADC_IN_SEL_MASK (0x3 << REG_CR_ADC_IN_SEL_OFFSET)
129 #define REG_CR_VIC_SB_SLEEP BIT(1)
130 #define REG_CR_VIC_SB BIT(0)
132 #define REG_CCR_CRYSTAL_OFFSET 0
133 #define REG_CCR_CRYSTAL_MASK (0xf << REG_CCR_CRYSTAL_OFFSET)
135 #define REG_FCR_DAC_FREQ_OFFSET 0
136 #define REG_FCR_DAC_FREQ_MASK (0xf << REG_FCR_DAC_FREQ_OFFSET)
138 #define REG_FCR_ADC_FREQ_OFFSET 0
139 #define REG_FCR_ADC_FREQ_MASK (0xf << REG_FCR_ADC_FREQ_OFFSET)
141 #define REG_ICR_INT_FORM_OFFSET 6
142 #define REG_ICR_INT_FORM_MASK (0x3 << REG_ICR_INT_FORM_OFFSET)
144 #define REG_IMR_ALL_MASK (0x7f)
145 #define REG_IMR_SCLR_MASK BIT(6)
146 #define REG_IMR_JACK_MASK BIT(5)
147 #define REG_IMR_SCMC_MASK BIT(4)
148 #define REG_IMR_RUP_MASK BIT(3)
149 #define REG_IMR_RDO_MASK BIT(2)
150 #define REG_IMR_GUP_MASK BIT(1)
151 #define REG_IMR_GDO_MASK BIT(0)
153 #define REG_IFR_ALL_MASK (0x7f)
154 #define REG_IFR_SCLR BIT(6)
155 #define REG_IFR_JACK BIT(5)
156 #define REG_IFR_SCMC BIT(4)
157 #define REG_IFR_RUP BIT(3)
158 #define REG_IFR_RDO BIT(2)
159 #define REG_IFR_GUP BIT(1)
160 #define REG_IFR_GDO BIT(0)
162 #define REG_GCR_HPL_LRGO BIT(7)
164 #define REG_GCR_DACL_RLGOD BIT(7)
166 #define REG_GCR_GAIN_OFFSET 0
167 #define REG_GCR_GAIN_MAX 0x1f
169 #define REG_GCR_MIC_GAIN_OFFSET 0
170 #define REG_GCR_MIC_GAIN_MAX 5
172 #define REG_GCR_ADC_GAIN_OFFSET 0
173 #define REG_GCR_ADC_GAIN_MAX 23
175 #define REG_AGC1_EN BIT(7)
177 /* codec private data */
180 struct regmap *regmap;
185 static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
186 enum snd_soc_bias_level level)
188 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
189 struct regmap *regmap = jz_codec->regmap;
192 case SND_SOC_BIAS_PREPARE:
193 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
196 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
197 REG_CR_VIC_SB_SLEEP, 0);
200 case SND_SOC_BIAS_STANDBY:
201 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
202 REG_CR_VIC_SB_SLEEP, REG_CR_VIC_SB_SLEEP);
203 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
204 REG_CR_VIC_SB, REG_CR_VIC_SB);
213 static int jz4770_codec_startup(struct snd_pcm_substream *substream,
214 struct snd_soc_dai *dai)
216 struct snd_soc_component *codec = dai->component;
217 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
220 * SYSCLK output from the codec to the AIC is required to keep the
221 * DMA transfer going during playback when all audible outputs have
224 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
225 snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
230 static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
231 struct snd_soc_dai *dai)
233 struct snd_soc_component *codec = dai->component;
234 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
236 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
237 snd_soc_dapm_disable_pin(dapm, "SYSCLK");
241 static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
242 int cmd, struct snd_soc_dai *dai)
244 struct snd_soc_component *codec = dai->component;
248 case SNDRV_PCM_TRIGGER_START:
249 case SNDRV_PCM_TRIGGER_RESUME:
250 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
251 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
252 snd_soc_component_force_bias_level(codec,
255 case SNDRV_PCM_TRIGGER_STOP:
256 case SNDRV_PCM_TRIGGER_SUSPEND:
257 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
267 static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
269 struct snd_soc_component *codec = dai->component;
270 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
271 unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
275 change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
277 mute ? REG_CR_DAC_MUTE : 0);
279 regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
281 if (val & BIT(REG_CR_DAC_SB_OFFSET))
284 err = regmap_read_poll_timeout(jz_codec->regmap,
285 JZ4770_CODEC_REG_IFR,
287 1000, 100 * USEC_PER_MSEC);
289 dev_err(jz_codec->dev,
290 "Timeout while setting digital mute: %d", err);
294 /* clear GUP/GDO flag */
295 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
303 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
304 static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
305 static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
306 static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
308 /* Unconditional controls. */
309 static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
310 /* record gain control */
311 SOC_DOUBLE_R_TLV("PCM Capture Volume",
312 JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
313 REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
316 SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
317 JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
318 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
321 static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
325 .info = snd_soc_info_volsw,
326 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
327 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
329 .get = snd_soc_dapm_get_volsw,
330 .put = snd_soc_dapm_put_volsw,
332 * NOTE: DACR/DACL are inversed; the gain value written to DACR
333 * seems to affect the left channel, and the gain value written
334 * to DACL seems to affect the right channel.
336 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
337 JZ4770_CODEC_REG_GCR_DACL,
339 REG_GCR_GAIN_MAX, 1),
343 static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
345 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347 .info = snd_soc_info_volsw,
348 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
349 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
351 .get = snd_soc_dapm_get_volsw,
352 .put = snd_soc_dapm_put_volsw,
353 /* HPR/HPL inversed for the same reason as above */
354 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
355 JZ4770_CODEC_REG_GCR_HPL,
357 REG_GCR_GAIN_MAX, 1),
361 static int hpout_event(struct snd_soc_dapm_widget *w,
362 struct snd_kcontrol *kcontrol, int event)
364 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
365 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
370 case SND_SOC_DAPM_PRE_PMU:
371 /* set cap-less, unmute HP */
372 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
373 REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE, 0);
376 case SND_SOC_DAPM_POST_PMU:
377 /* wait for ramp-up complete (RUP) */
378 err = regmap_read_poll_timeout(jz_codec->regmap,
379 JZ4770_CODEC_REG_IFR,
380 val, val & REG_IFR_RUP,
381 1000, 100 * USEC_PER_MSEC);
383 dev_err(jz_codec->dev, "RUP timeout: %d", err);
388 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
389 REG_IFR_RUP, REG_IFR_RUP);
393 case SND_SOC_DAPM_POST_PMD:
394 /* set cap-couple, mute HP */
395 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
396 REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE,
397 REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE);
399 err = regmap_read_poll_timeout(jz_codec->regmap,
400 JZ4770_CODEC_REG_IFR,
401 val, val & REG_IFR_RDO,
402 1000, 100 * USEC_PER_MSEC);
404 dev_err(jz_codec->dev, "RDO timeout: %d", err);
409 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
410 REG_IFR_RDO, REG_IFR_RDO);
418 static int adc_poweron_event(struct snd_soc_dapm_widget *w,
419 struct snd_kcontrol *kcontrol, int event)
421 if (event == SND_SOC_DAPM_POST_PMU)
427 static const char * const jz4770_codec_hp_texts[] = {
428 "PCM", "Line In", "Mic 1", "Mic 2"
430 static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
431 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
432 JZ4770_CODEC_REG_CR_HP,
433 REG_CR_HP_SEL_OFFSET,
435 jz4770_codec_hp_texts,
436 jz4770_codec_hp_values);
437 static const struct snd_kcontrol_new jz4770_codec_hp_source =
438 SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
440 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
441 JZ4770_CODEC_REG_CR_LO,
442 REG_CR_LO_SEL_OFFSET,
444 jz4770_codec_hp_texts,
445 jz4770_codec_hp_values);
446 static const struct snd_kcontrol_new jz4770_codec_lo_source =
447 SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
449 static const char * const jz4770_codec_cap_texts[] = {
450 "Line In", "Mic 1", "Mic 2"
452 static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
453 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
454 JZ4770_CODEC_REG_CR_ADC,
455 REG_CR_ADC_IN_SEL_OFFSET,
456 REG_CR_ADC_IN_SEL_MASK,
457 jz4770_codec_cap_texts,
458 jz4770_codec_cap_values);
459 static const struct snd_kcontrol_new jz4770_codec_cap_source =
460 SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
462 static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
463 SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
464 REG_CR_MIC_STEREO_OFFSET, 1, 0),
467 static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
468 SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
469 REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
470 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
471 SND_SOC_DAPM_POST_PMD),
473 SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
474 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
476 SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
477 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
479 SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
480 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
482 SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
483 &jz4770_codec_hp_source),
484 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
485 &jz4770_codec_cap_source),
486 SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
487 &jz4770_codec_lo_source),
489 SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
490 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
491 SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
492 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
494 SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
495 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
497 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
498 jz4770_codec_mic_controls,
499 ARRAY_SIZE(jz4770_codec_mic_controls)),
501 SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
502 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
504 SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
505 REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
506 SND_SOC_DAPM_POST_PMU),
507 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
508 REG_CR_DAC_SB_OFFSET, 1),
510 SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
511 jz4770_codec_pcm_playback_controls,
512 ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
513 SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
514 jz4770_codec_hp_playback_controls,
515 ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
517 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
518 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
520 SND_SOC_DAPM_INPUT("MIC1P"),
521 SND_SOC_DAPM_INPUT("MIC1N"),
522 SND_SOC_DAPM_INPUT("MIC2P"),
523 SND_SOC_DAPM_INPUT("MIC2N"),
525 SND_SOC_DAPM_OUTPUT("LOUT"),
526 SND_SOC_DAPM_OUTPUT("ROUT"),
528 SND_SOC_DAPM_OUTPUT("LHPOUT"),
529 SND_SOC_DAPM_OUTPUT("RHPOUT"),
531 SND_SOC_DAPM_INPUT("LLINEIN"),
532 SND_SOC_DAPM_INPUT("RLINEIN"),
534 SND_SOC_DAPM_OUTPUT("SYSCLK"),
537 /* Unconditional routes. */
538 static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
539 { "Mic 1", NULL, "MIC1P" },
540 { "Mic Diff", NULL, "MIC1N" },
541 { "Mic 1", NULL, "Mic Diff" },
542 { "Mic 2", NULL, "MIC2P" },
543 { "Mic Diff", NULL, "MIC2N" },
544 { "Mic 2", NULL, "Mic Diff" },
546 { "Line In", NULL, "LLINEIN" },
547 { "Line In", NULL, "RLINEIN" },
549 { "Mic", "Stereo Capture Switch", "Mic 1" },
550 { "Mic", "Stereo Capture Switch", "Mic 2" },
551 { "Headphones Source", "Mic 1", "Mic" },
552 { "Headphones Source", "Mic 2", "Mic" },
553 { "Capture Source", "Mic 1", "Mic" },
554 { "Capture Source", "Mic 2", "Mic" },
556 { "Headphones Source", "Mic 1", "Mic 1" },
557 { "Headphones Source", "Mic 2", "Mic 2" },
558 { "Headphones Source", "Line In", "Line In Bypass" },
559 { "Headphones Source", "PCM", "Headphones Playback" },
560 { "HP Out", NULL, "Headphones Source" },
562 { "Capture Source", "Line In", "Line In" },
563 { "Capture Source", "Mic 1", "Mic 1" },
564 { "Capture Source", "Mic 2", "Mic 2" },
565 { "ADC", NULL, "Capture Source" },
567 { "Line In Bypass", NULL, "Line In" },
568 { "Line Out Source", "Line In", "Line In Bypass" },
569 { "Line Out Source", "PCM", "PCM Playback" },
571 { "LHPOUT", NULL, "HP Out"},
572 { "RHPOUT", NULL, "HP Out"},
574 { "Line Out", NULL, "Line Out Source" },
575 { "Line Out Switch 2", NULL, "Line Out" },
577 { "LOUT", NULL, "Line Out Switch 2"},
578 { "ROUT", NULL, "Line Out Switch 2"},
580 { "PCM Playback", "Volume", "DAC" },
581 { "Headphones Playback", "Volume", "PCM Playback" },
583 { "SYSCLK", NULL, "DAC" },
586 static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
588 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
589 struct regmap *regmap = jz_codec->regmap;
591 /* Collect updates for later sending. */
592 regcache_cache_only(regmap, true);
594 /* default HP output to PCM */
595 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
596 REG_CR_HP_SEL_MASK, REG_CR_HP_SEL_MASK);
598 /* default line output to PCM */
599 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_LO,
600 REG_CR_LO_SEL_MASK, REG_CR_LO_SEL_MASK);
602 /* Disable stereo mic */
603 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
604 BIT(REG_CR_MIC_STEREO_OFFSET), 0);
606 /* Set mic 1 as default source for ADC */
607 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
608 REG_CR_ADC_IN_SEL_MASK, 0);
610 /* ADC/DAC: serial + i2s */
611 regmap_update_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
612 REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S,
613 REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
614 regmap_update_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
615 REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S,
616 REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
618 /* The generated IRQ is a high level */
619 regmap_update_bits(regmap, JZ4770_CODEC_REG_ICR,
620 REG_ICR_INT_FORM_MASK, 0);
621 regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
622 REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
623 REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
627 regmap_update_bits(regmap, JZ4770_CODEC_REG_CCR,
628 REG_CCR_CRYSTAL_MASK, 0);
630 /* 0: 16ohm/220uF, 1: 10kohm/1uF */
631 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
634 /* disable automatic gain */
635 regmap_update_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN, 0);
637 /* Disable DAC lrswap */
638 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_DAC,
639 REG_CR_DAC_LRSWAP, REG_CR_DAC_LRSWAP);
641 /* Independent L/R DAC gain control */
642 regmap_update_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
643 REG_GCR_DACL_RLGOD, 0);
645 /* Disable ADC lrswap */
646 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
647 REG_CR_ADC_LRSWAP, REG_CR_ADC_LRSWAP);
649 /* default to cap-less mode(0) */
650 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
651 REG_CR_HP_SB_HPCM, 0);
653 /* Send collected updates. */
654 regcache_cache_only(regmap, false);
655 regcache_sync(regmap);
657 /* Reset all interrupt flags. */
658 regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
661 static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
663 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
665 clk_prepare_enable(jz_codec->clk);
667 jz4770_codec_codec_init_regs(codec);
672 static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
674 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
676 clk_disable_unprepare(jz_codec->clk);
679 static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
680 .probe = jz4770_codec_codec_probe,
681 .remove = jz4770_codec_codec_remove,
682 .set_bias_level = jz4770_codec_set_bias_level,
683 .controls = jz4770_codec_snd_controls,
684 .num_controls = ARRAY_SIZE(jz4770_codec_snd_controls),
685 .dapm_widgets = jz4770_codec_dapm_widgets,
686 .num_dapm_widgets = ARRAY_SIZE(jz4770_codec_dapm_widgets),
687 .dapm_routes = jz4770_codec_dapm_routes,
688 .num_dapm_routes = ARRAY_SIZE(jz4770_codec_dapm_routes),
689 .suspend_bias_off = 1,
690 .use_pmdown_time = 1,
693 static const unsigned int jz4770_codec_sample_rates[] = {
694 96000, 48000, 44100, 32000,
695 24000, 22050, 16000, 12000,
699 static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
700 struct snd_pcm_hw_params *params,
701 struct snd_soc_dai *dai)
703 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
704 unsigned int rate, bit_width;
706 switch (params_format(params)) {
707 case SNDRV_PCM_FORMAT_S16_LE:
710 case SNDRV_PCM_FORMAT_S18_3LE:
713 case SNDRV_PCM_FORMAT_S20_3LE:
716 case SNDRV_PCM_FORMAT_S24_3LE:
723 for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
724 if (jz4770_codec_sample_rates[rate] == params_rate(params))
728 if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
731 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
732 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
733 REG_AICR_DAC_ADWL_MASK,
734 bit_width << REG_AICR_DAC_ADWL_OFFSET);
735 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
736 REG_FCR_DAC_FREQ_MASK,
737 rate << REG_FCR_DAC_FREQ_OFFSET);
739 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
740 REG_AICR_ADC_ADWL_MASK,
741 bit_width << REG_AICR_ADC_ADWL_OFFSET);
742 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
743 REG_FCR_ADC_FREQ_MASK,
744 rate << REG_FCR_ADC_FREQ_OFFSET);
750 static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
751 .startup = jz4770_codec_startup,
752 .shutdown = jz4770_codec_shutdown,
753 .hw_params = jz4770_codec_hw_params,
754 .trigger = jz4770_codec_pcm_trigger,
755 .mute_stream = jz4770_codec_mute_stream,
756 .no_capture_mute = 1,
759 #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
760 SNDRV_PCM_FMTBIT_S18_3LE | \
761 SNDRV_PCM_FMTBIT_S20_3LE | \
762 SNDRV_PCM_FMTBIT_S24_3LE)
764 static struct snd_soc_dai_driver jz4770_codec_dai = {
765 .name = "jz4770-hifi",
767 .stream_name = "Playback",
770 .rates = SNDRV_PCM_RATE_8000_96000,
771 .formats = JZ_CODEC_FORMATS,
774 .stream_name = "Capture",
777 .rates = SNDRV_PCM_RATE_8000_96000,
778 .formats = JZ_CODEC_FORMATS,
780 .ops = &jz4770_codec_dai_ops,
783 static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
785 return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
788 static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
791 case JZ4770_CODEC_REG_MISSING_REG1:
792 case JZ4770_CODEC_REG_MISSING_REG2:
799 static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
802 case JZ4770_CODEC_REG_SR:
803 case JZ4770_CODEC_REG_MISSING_REG1:
804 case JZ4770_CODEC_REG_MISSING_REG2:
811 static int jz4770_codec_io_wait(struct jz_codec *codec)
815 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
816 !(reg & ICDC_RGADW_RGWR),
817 1000, 10 * USEC_PER_MSEC);
820 static int jz4770_codec_reg_read(void *context, unsigned int reg,
823 struct jz_codec *codec = context;
828 ret = jz4770_codec_io_wait(codec);
832 tmp = readl(codec->base + ICDC_RGADW_OFFSET);
833 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
834 | (reg << ICDC_RGADW_RGADDR_OFFSET);
835 writel(tmp, codec->base + ICDC_RGADW_OFFSET);
838 for (i = 0; i < 6; i++)
839 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
840 ICDC_RGDATA_RGDOUT_MASK;
845 static int jz4770_codec_reg_write(void *context, unsigned int reg,
848 struct jz_codec *codec = context;
851 ret = jz4770_codec_io_wait(codec);
855 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
856 codec->base + ICDC_RGADW_OFFSET);
858 ret = jz4770_codec_io_wait(codec);
865 static const u8 jz4770_codec_reg_defaults[] = {
866 0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
867 0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
868 0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
869 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
870 0x07, 0x44, 0x1F, 0x00
873 static struct regmap_config jz4770_codec_regmap_config = {
877 .max_register = JZ4770_CODEC_REG_AGC5,
878 .volatile_reg = jz4770_codec_volatile,
879 .readable_reg = jz4770_codec_readable,
880 .writeable_reg = jz4770_codec_writeable,
882 .reg_read = jz4770_codec_reg_read,
883 .reg_write = jz4770_codec_reg_write,
885 .reg_defaults_raw = jz4770_codec_reg_defaults,
886 .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
887 .cache_type = REGCACHE_FLAT,
890 static int jz4770_codec_probe(struct platform_device *pdev)
892 struct device *dev = &pdev->dev;
893 struct jz_codec *codec;
896 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
902 codec->base = devm_platform_ioremap_resource(pdev, 0);
903 if (IS_ERR(codec->base)) {
904 ret = PTR_ERR(codec->base);
905 dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
909 codec->regmap = devm_regmap_init(dev, NULL, codec,
910 &jz4770_codec_regmap_config);
911 if (IS_ERR(codec->regmap))
912 return PTR_ERR(codec->regmap);
914 codec->clk = devm_clk_get(dev, "aic");
915 if (IS_ERR(codec->clk))
916 return PTR_ERR(codec->clk);
918 platform_set_drvdata(pdev, codec);
920 ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
921 &jz4770_codec_dai, 1);
923 dev_err(dev, "Failed to register codec: %d\n", ret);
930 static const struct of_device_id jz4770_codec_of_matches[] = {
931 { .compatible = "ingenic,jz4770-codec", },
934 MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
936 static struct platform_driver jz4770_codec_driver = {
937 .probe = jz4770_codec_probe,
939 .name = "jz4770-codec",
940 .of_match_table = jz4770_codec_of_matches,
943 module_platform_driver(jz4770_codec_driver);
945 MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
948 MODULE_LICENSE("GPL v2");