printf: Remove unused 'bprintf'
[drm/drm-misc.git] / sound / soc / codecs / jz4770.c
blobacb9eaa7ea1c50e2178d402deed9862a9527d6b1
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Ingenic JZ4770 CODEC driver
4 //
5 // Copyright (C) 2012, Maarten ter Huurne <maarten@treewalker.org>
6 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
8 #include <linux/clk.h>
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 */
40 enum {
41 JZ4770_CODEC_REG_SR,
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,
55 JZ4770_CODEC_REG_CCR,
56 JZ4770_CODEC_REG_FCR_DAC,
57 JZ4770_CODEC_REG_FCR_ADC,
58 JZ4770_CODEC_REG_ICR,
59 JZ4770_CODEC_REG_IMR,
60 JZ4770_CODEC_REG_IFR,
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_OFFSET 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 */
178 struct jz_codec {
179 struct device *dev;
180 struct regmap *regmap;
181 void __iomem *base;
182 struct clk *clk;
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;
191 switch (level) {
192 case SND_SOC_BIAS_PREPARE:
193 /* Reset all interrupt flags. */
194 regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
196 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
197 REG_CR_VIC_SB);
198 msleep(250);
199 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
200 REG_CR_VIC_SB_SLEEP);
201 msleep(400);
202 break;
203 case SND_SOC_BIAS_STANDBY:
204 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
205 REG_CR_VIC_SB_SLEEP);
206 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
207 REG_CR_VIC_SB);
208 fallthrough;
209 default:
210 break;
213 return 0;
216 static int jz4770_codec_startup(struct snd_pcm_substream *substream,
217 struct snd_soc_dai *dai)
219 struct snd_soc_component *codec = dai->component;
220 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
223 * SYSCLK output from the codec to the AIC is required to keep the
224 * DMA transfer going during playback when all audible outputs have
225 * been disabled.
227 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
228 snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
230 return 0;
233 static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
234 struct snd_soc_dai *dai)
236 struct snd_soc_component *codec = dai->component;
237 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
240 snd_soc_dapm_disable_pin(dapm, "SYSCLK");
244 static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
245 int cmd, struct snd_soc_dai *dai)
247 struct snd_soc_component *codec = dai->component;
248 int ret = 0;
250 switch (cmd) {
251 case SNDRV_PCM_TRIGGER_START:
252 case SNDRV_PCM_TRIGGER_RESUME:
253 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
254 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
255 snd_soc_component_force_bias_level(codec,
256 SND_SOC_BIAS_ON);
257 break;
258 case SNDRV_PCM_TRIGGER_STOP:
259 case SNDRV_PCM_TRIGGER_SUSPEND:
260 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
261 /* do nothing */
262 break;
263 default:
264 ret = -EINVAL;
267 return ret;
270 static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
272 struct snd_soc_component *codec = dai->component;
273 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
274 unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
275 unsigned int val;
276 int change, err;
278 change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
279 REG_CR_DAC_MUTE,
280 mute ? REG_CR_DAC_MUTE : 0);
281 if (change == 1) {
282 regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
284 if (val & BIT(REG_CR_DAC_SB_OFFSET))
285 return 1;
287 err = regmap_read_poll_timeout(jz_codec->regmap,
288 JZ4770_CODEC_REG_IFR,
289 val, val & gain_bit,
290 1000, 1 * USEC_PER_SEC);
291 if (err) {
292 dev_err(jz_codec->dev,
293 "Timeout while setting digital mute: %d", err);
294 return err;
297 /* clear GUP/GDO flag */
298 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
299 gain_bit);
302 return 0;
305 /* unit: 0.01dB */
306 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
307 static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
308 static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
309 static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
310 static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
312 /* Unconditional controls. */
313 static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
314 /* record gain control */
315 SOC_DOUBLE_R_TLV("PCM Capture Volume",
316 JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
317 REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
318 0, adc_tlv),
320 SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
321 JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
322 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
324 SOC_SINGLE_TLV("Mixer Capture Volume",
325 JZ4770_CODEC_REG_GCR_MIXADC,
326 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
328 SOC_SINGLE_TLV("Mixer Playback Volume",
329 JZ4770_CODEC_REG_GCR_MIXDAC,
330 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
333 static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
335 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
336 .name = "Volume",
337 .info = snd_soc_info_volsw,
338 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
339 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
340 .tlv.p = dac_tlv,
341 .get = snd_soc_dapm_get_volsw,
342 .put = snd_soc_dapm_put_volsw,
344 * NOTE: DACR/DACL are inversed; the gain value written to DACR
345 * seems to affect the left channel, and the gain value written
346 * to DACL seems to affect the right channel.
348 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
349 JZ4770_CODEC_REG_GCR_DACL,
350 REG_GCR_GAIN_OFFSET,
351 REG_GCR_GAIN_MAX, 1),
355 static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
358 .name = "Volume",
359 .info = snd_soc_info_volsw,
360 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
361 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
362 .tlv.p = out_tlv,
363 .get = snd_soc_dapm_get_volsw,
364 .put = snd_soc_dapm_put_volsw,
365 /* HPR/HPL inversed for the same reason as above */
366 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
367 JZ4770_CODEC_REG_GCR_HPL,
368 REG_GCR_GAIN_OFFSET,
369 REG_GCR_GAIN_MAX, 1),
373 static int hpout_event(struct snd_soc_dapm_widget *w,
374 struct snd_kcontrol *kcontrol, int event)
376 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
377 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
378 unsigned int val;
379 int err;
381 switch (event) {
382 case SND_SOC_DAPM_PRE_PMU:
383 /* unmute HP */
384 regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
385 REG_CR_HP_MUTE);
386 break;
388 case SND_SOC_DAPM_POST_PMU:
389 /* wait for ramp-up complete (RUP) */
390 err = regmap_read_poll_timeout(jz_codec->regmap,
391 JZ4770_CODEC_REG_IFR,
392 val, val & REG_IFR_RUP,
393 1000, 1 * USEC_PER_SEC);
394 if (err) {
395 dev_err(jz_codec->dev, "RUP timeout: %d", err);
396 return err;
399 /* clear RUP flag */
400 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
401 REG_IFR_RUP);
403 break;
405 case SND_SOC_DAPM_POST_PMD:
406 /* mute HP */
407 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
408 REG_CR_HP_MUTE);
410 err = regmap_read_poll_timeout(jz_codec->regmap,
411 JZ4770_CODEC_REG_IFR,
412 val, val & REG_IFR_RDO,
413 1000, 1 * USEC_PER_SEC);
414 if (err) {
415 dev_err(jz_codec->dev, "RDO timeout: %d", err);
416 return err;
419 /* clear RDO flag */
420 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
421 REG_IFR_RDO);
423 break;
426 return 0;
429 static int adc_poweron_event(struct snd_soc_dapm_widget *w,
430 struct snd_kcontrol *kcontrol, int event)
432 if (event == SND_SOC_DAPM_POST_PMU)
433 msleep(1000);
435 return 0;
438 static const char * const jz4770_codec_hp_texts[] = {
439 "PCM", "Line In", "Mic 1", "Mic 2"
441 static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
442 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
443 JZ4770_CODEC_REG_CR_HP,
444 REG_CR_HP_SEL_OFFSET,
445 REG_CR_HP_SEL_MASK,
446 jz4770_codec_hp_texts,
447 jz4770_codec_hp_values);
448 static const struct snd_kcontrol_new jz4770_codec_hp_source =
449 SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
451 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
452 JZ4770_CODEC_REG_CR_LO,
453 REG_CR_LO_SEL_OFFSET,
454 REG_CR_LO_SEL_MASK,
455 jz4770_codec_hp_texts,
456 jz4770_codec_hp_values);
457 static const struct snd_kcontrol_new jz4770_codec_lo_source =
458 SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
460 static const char * const jz4770_codec_cap_texts[] = {
461 "Line In", "Mic 1", "Mic 2"
463 static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
464 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
465 JZ4770_CODEC_REG_CR_ADC,
466 REG_CR_ADC_IN_SEL_OFFSET,
467 REG_CR_ADC_IN_SEL_MASK,
468 jz4770_codec_cap_texts,
469 jz4770_codec_cap_values);
470 static const struct snd_kcontrol_new jz4770_codec_cap_source =
471 SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
473 static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
474 SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
475 REG_CR_MIC_STEREO_OFFSET, 1, 0),
478 static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
479 SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
480 REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
481 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
482 SND_SOC_DAPM_POST_PMD),
484 SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
485 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
487 SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
488 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
490 SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
491 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
493 SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
494 &jz4770_codec_hp_source),
495 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
496 &jz4770_codec_cap_source),
497 SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
498 &jz4770_codec_lo_source),
500 SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
501 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
502 SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
503 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
505 SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
506 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
508 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
509 jz4770_codec_mic_controls,
510 ARRAY_SIZE(jz4770_codec_mic_controls)),
512 SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
513 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
515 SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
516 REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
517 SND_SOC_DAPM_POST_PMU),
518 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
519 REG_CR_DAC_SB_OFFSET, 1),
521 SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
522 jz4770_codec_pcm_playback_controls,
523 ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
524 SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
525 jz4770_codec_hp_playback_controls,
526 ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
528 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
529 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
531 SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
532 REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
534 SND_SOC_DAPM_INPUT("MIC1P"),
535 SND_SOC_DAPM_INPUT("MIC1N"),
536 SND_SOC_DAPM_INPUT("MIC2P"),
537 SND_SOC_DAPM_INPUT("MIC2N"),
539 SND_SOC_DAPM_OUTPUT("LOUT"),
540 SND_SOC_DAPM_OUTPUT("ROUT"),
542 SND_SOC_DAPM_OUTPUT("LHPOUT"),
543 SND_SOC_DAPM_OUTPUT("RHPOUT"),
545 SND_SOC_DAPM_INPUT("LLINEIN"),
546 SND_SOC_DAPM_INPUT("RLINEIN"),
548 SND_SOC_DAPM_OUTPUT("SYSCLK"),
551 /* Unconditional routes. */
552 static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
553 { "Mic 1", NULL, "MIC1P" },
554 { "Mic Diff", NULL, "MIC1N" },
555 { "Mic 1", NULL, "Mic Diff" },
556 { "Mic 2", NULL, "MIC2P" },
557 { "Mic Diff", NULL, "MIC2N" },
558 { "Mic 2", NULL, "Mic Diff" },
560 { "Line In", NULL, "LLINEIN" },
561 { "Line In", NULL, "RLINEIN" },
563 { "Mic", "Stereo Capture Switch", "Mic 1" },
564 { "Mic", "Stereo Capture Switch", "Mic 2" },
565 { "Headphones Source", "Mic 1", "Mic" },
566 { "Headphones Source", "Mic 2", "Mic" },
567 { "Capture Source", "Mic 1", "Mic" },
568 { "Capture Source", "Mic 2", "Mic" },
570 { "Headphones Source", "Mic 1", "Mic 1" },
571 { "Headphones Source", "Mic 2", "Mic 2" },
572 { "Headphones Source", "Line In", "Line In Bypass" },
573 { "Headphones Source", "PCM", "Headphones Playback" },
574 { "HP Out", NULL, "Headphones Source" },
576 { "Capture Source", "Line In", "Line In" },
577 { "Capture Source", "Mic 1", "Mic 1" },
578 { "Capture Source", "Mic 2", "Mic 2" },
579 { "ADC", NULL, "Capture Source" },
581 { "Line In Bypass", NULL, "Line In" },
582 { "Line Out Source", "Line In", "Line In Bypass" },
583 { "Line Out Source", "PCM", "PCM Playback" },
585 { "LHPOUT", NULL, "HP Out"},
586 { "RHPOUT", NULL, "HP Out"},
588 { "Line Out", NULL, "Line Out Source" },
589 { "Line Out Switch 2", NULL, "Line Out" },
591 { "LOUT", NULL, "Line Out Switch 2"},
592 { "ROUT", NULL, "Line Out Switch 2"},
594 { "PCM Playback", "Volume", "DAC" },
595 { "Headphones Playback", "Volume", "PCM Playback" },
597 { "SYSCLK", NULL, "DAC" },
600 static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
602 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
603 struct regmap *regmap = jz_codec->regmap;
605 /* Collect updates for later sending. */
606 regcache_cache_only(regmap, true);
608 /* default HP output to PCM */
609 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
611 /* default line output to PCM */
612 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
614 /* Disable stereo mic */
615 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
616 BIT(REG_CR_MIC_STEREO_OFFSET));
618 /* Set mic 1 as default source for ADC */
619 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
620 REG_CR_ADC_IN_SEL_MASK);
622 /* ADC/DAC: serial + i2s */
623 regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
624 REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
625 regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
626 REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
628 /* The generated IRQ is a high level */
629 regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
630 regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
631 REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
632 REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
633 REG_IMR_GDO_MASK);
635 /* 12M oscillator */
636 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
638 /* 0: 16ohm/220uF, 1: 10kohm/1uF */
639 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
641 /* disable automatic gain */
642 regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
644 /* Disable DAC lrswap */
645 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
647 /* Independent L/R DAC gain control */
648 regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
649 REG_GCR_DACL_RLGOD);
651 /* Disable ADC lrswap */
652 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
654 /* default to cap-less mode(0) */
655 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
656 BIT(REG_CR_HP_SB_HPCM_OFFSET));
658 /* Send collected updates. */
659 regcache_cache_only(regmap, false);
660 regcache_sync(regmap);
663 static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
665 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
667 clk_prepare_enable(jz_codec->clk);
669 jz4770_codec_codec_init_regs(codec);
671 return 0;
674 static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
676 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
678 clk_disable_unprepare(jz_codec->clk);
681 static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
682 .probe = jz4770_codec_codec_probe,
683 .remove = jz4770_codec_codec_remove,
684 .set_bias_level = jz4770_codec_set_bias_level,
685 .controls = jz4770_codec_snd_controls,
686 .num_controls = ARRAY_SIZE(jz4770_codec_snd_controls),
687 .dapm_widgets = jz4770_codec_dapm_widgets,
688 .num_dapm_widgets = ARRAY_SIZE(jz4770_codec_dapm_widgets),
689 .dapm_routes = jz4770_codec_dapm_routes,
690 .num_dapm_routes = ARRAY_SIZE(jz4770_codec_dapm_routes),
691 .suspend_bias_off = 1,
692 .use_pmdown_time = 1,
695 static const unsigned int jz4770_codec_sample_rates[] = {
696 96000, 48000, 44100, 32000,
697 24000, 22050, 16000, 12000,
698 11025, 9600, 8000,
701 static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
702 struct snd_pcm_hw_params *params,
703 struct snd_soc_dai *dai)
705 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
706 unsigned int rate, bit_width;
708 switch (params_format(params)) {
709 case SNDRV_PCM_FORMAT_S16_LE:
710 bit_width = 0;
711 break;
712 case SNDRV_PCM_FORMAT_S18_3LE:
713 bit_width = 1;
714 break;
715 case SNDRV_PCM_FORMAT_S20_3LE:
716 bit_width = 2;
717 break;
718 case SNDRV_PCM_FORMAT_S24_3LE:
719 bit_width = 3;
720 break;
721 default:
722 return -EINVAL;
725 for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
726 if (jz4770_codec_sample_rates[rate] == params_rate(params))
727 break;
730 if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
731 return -EINVAL;
733 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
734 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
735 REG_AICR_DAC_ADWL_MASK,
736 bit_width << REG_AICR_DAC_ADWL_OFFSET);
737 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
738 REG_FCR_DAC_FREQ_MASK,
739 rate << REG_FCR_DAC_FREQ_OFFSET);
740 } else {
741 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
742 REG_AICR_ADC_ADWL_MASK,
743 bit_width << REG_AICR_ADC_ADWL_OFFSET);
744 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
745 REG_FCR_ADC_FREQ_MASK,
746 rate << REG_FCR_ADC_FREQ_OFFSET);
749 return 0;
752 static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
753 .startup = jz4770_codec_startup,
754 .shutdown = jz4770_codec_shutdown,
755 .hw_params = jz4770_codec_hw_params,
756 .trigger = jz4770_codec_pcm_trigger,
757 .mute_stream = jz4770_codec_mute_stream,
758 .no_capture_mute = 1,
761 #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
762 SNDRV_PCM_FMTBIT_S18_3LE | \
763 SNDRV_PCM_FMTBIT_S20_3LE | \
764 SNDRV_PCM_FMTBIT_S24_3LE)
766 static struct snd_soc_dai_driver jz4770_codec_dai = {
767 .name = "jz4770-hifi",
768 .playback = {
769 .stream_name = "Playback",
770 .channels_min = 2,
771 .channels_max = 2,
772 .rates = SNDRV_PCM_RATE_8000_96000,
773 .formats = JZ_CODEC_FORMATS,
775 .capture = {
776 .stream_name = "Capture",
777 .channels_min = 2,
778 .channels_max = 2,
779 .rates = SNDRV_PCM_RATE_8000_96000,
780 .formats = JZ_CODEC_FORMATS,
782 .ops = &jz4770_codec_dai_ops,
785 static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
787 return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
790 static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
792 switch (reg) {
793 case JZ4770_CODEC_REG_MISSING_REG1:
794 case JZ4770_CODEC_REG_MISSING_REG2:
795 return false;
796 default:
797 return true;
801 static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
803 switch (reg) {
804 case JZ4770_CODEC_REG_SR:
805 case JZ4770_CODEC_REG_MISSING_REG1:
806 case JZ4770_CODEC_REG_MISSING_REG2:
807 return false;
808 default:
809 return true;
813 static int jz4770_codec_io_wait(struct jz_codec *codec)
815 u32 reg;
817 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
818 !(reg & ICDC_RGADW_RGWR),
819 1000, 1 * USEC_PER_SEC);
822 static int jz4770_codec_reg_read(void *context, unsigned int reg,
823 unsigned int *val)
825 struct jz_codec *codec = context;
826 unsigned int i;
827 u32 tmp;
828 int ret;
830 ret = jz4770_codec_io_wait(codec);
831 if (ret)
832 return ret;
834 tmp = readl(codec->base + ICDC_RGADW_OFFSET);
835 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
836 | (reg << ICDC_RGADW_RGADDR_OFFSET);
837 writel(tmp, codec->base + ICDC_RGADW_OFFSET);
839 /* wait 6+ cycles */
840 for (i = 0; i < 6; i++)
841 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
842 ICDC_RGDATA_RGDOUT_MASK;
844 return 0;
847 static int jz4770_codec_reg_write(void *context, unsigned int reg,
848 unsigned int val)
850 struct jz_codec *codec = context;
851 int ret;
853 ret = jz4770_codec_io_wait(codec);
854 if (ret)
855 return ret;
857 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
858 codec->base + ICDC_RGADW_OFFSET);
860 ret = jz4770_codec_io_wait(codec);
861 if (ret)
862 return ret;
864 return 0;
867 static const u8 jz4770_codec_reg_defaults[] = {
868 0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
869 0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
870 0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
872 0x07, 0x44, 0x1F, 0x00
875 static const struct regmap_config jz4770_codec_regmap_config = {
876 .reg_bits = 7,
877 .val_bits = 8,
879 .max_register = JZ4770_CODEC_REG_AGC5,
880 .volatile_reg = jz4770_codec_volatile,
881 .readable_reg = jz4770_codec_readable,
882 .writeable_reg = jz4770_codec_writeable,
884 .reg_read = jz4770_codec_reg_read,
885 .reg_write = jz4770_codec_reg_write,
887 .reg_defaults_raw = jz4770_codec_reg_defaults,
888 .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
889 .cache_type = REGCACHE_FLAT,
892 static int jz4770_codec_probe(struct platform_device *pdev)
894 struct device *dev = &pdev->dev;
895 struct jz_codec *codec;
896 int ret;
898 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
899 if (!codec)
900 return -ENOMEM;
902 codec->dev = dev;
904 codec->base = devm_platform_ioremap_resource(pdev, 0);
905 if (IS_ERR(codec->base))
906 return PTR_ERR(codec->base);
908 codec->regmap = devm_regmap_init(dev, NULL, codec,
909 &jz4770_codec_regmap_config);
910 if (IS_ERR(codec->regmap))
911 return PTR_ERR(codec->regmap);
913 codec->clk = devm_clk_get(dev, "aic");
914 if (IS_ERR(codec->clk))
915 return PTR_ERR(codec->clk);
917 platform_set_drvdata(pdev, codec);
919 ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
920 &jz4770_codec_dai, 1);
921 if (ret) {
922 dev_err(dev, "Failed to register codec: %d\n", ret);
923 return ret;
926 return 0;
929 static const struct of_device_id jz4770_codec_of_matches[] = {
930 { .compatible = "ingenic,jz4770-codec", },
931 { /* sentinel */ }
933 MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
935 static struct platform_driver jz4770_codec_driver = {
936 .probe = jz4770_codec_probe,
937 .driver = {
938 .name = "jz4770-codec",
939 .of_match_table = jz4770_codec_of_matches,
942 module_platform_driver(jz4770_codec_driver);
944 MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
945 MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
946 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
947 MODULE_LICENSE("GPL v2");