Loading...
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>
7
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>
14
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>
20
21#define ICDC_RGADW_OFFSET 0x00
22#define ICDC_RGDATA_OFFSET 0x04
23
24/* ICDC internal register access control register(RGADW) */
25#define ICDC_RGADW_RGWR BIT(16)
26
27#define ICDC_RGADW_RGADDR_OFFSET 8
28#define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
29
30#define ICDC_RGADW_RGDIN_OFFSET 0
31#define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
32
33/* ICDC internal register data output register (RGDATA)*/
34#define ICDC_RGDATA_IRQ BIT(8)
35
36#define ICDC_RGDATA_RGDOUT_OFFSET 0
37#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
38
39/* Internal register space, accessed through regmap */
40enum {
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,
46
47 JZ4770_CODEC_REG_MISSING_REG1,
48
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,
71
72 JZ4770_CODEC_REG_MISSING_REG2,
73
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,
81};
82
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)
87
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)
92
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)
97
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)
104
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)
110
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
117
118#define REG_CR_LI_LIBY_OFFSET 4
119#define REG_CR_LI_SB_OFFSET 0
120
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)
128
129#define REG_CR_VIC_SB_SLEEP BIT(1)
130#define REG_CR_VIC_SB BIT(0)
131
132#define REG_CCR_CRYSTAL_OFFSET 0
133#define REG_CCR_CRYSTAL_MASK (0xf << REG_CCR_CRYSTAL_OFFSET)
134
135#define REG_FCR_DAC_FREQ_OFFSET 0
136#define REG_FCR_DAC_FREQ_MASK (0xf << REG_FCR_DAC_FREQ_OFFSET)
137
138#define REG_FCR_ADC_FREQ_OFFSET 0
139#define REG_FCR_ADC_FREQ_MASK (0xf << REG_FCR_ADC_FREQ_OFFSET)
140
141#define REG_ICR_INT_FORM_OFFSET 6
142#define REG_ICR_INT_FORM_MASK (0x3 << REG_ICR_INT_FORM_OFFSET)
143
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)
152
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)
161
162#define REG_GCR_HPL_LRGO BIT(7)
163
164#define REG_GCR_DACL_RLGOD BIT(7)
165
166#define REG_GCR_GAIN_OFFSET 0
167#define REG_GCR_GAIN_MAX 0x1f
168
169#define REG_GCR_MIC_GAIN_OFFSET 0
170#define REG_GCR_MIC_GAIN_MAX 5
171
172#define REG_GCR_ADC_GAIN_OFFSET 0
173#define REG_GCR_ADC_GAIN_MAX 23
174
175#define REG_AGC1_EN BIT(7)
176
177/* codec private data */
178struct jz_codec {
179 struct device *dev;
180 struct regmap *regmap;
181 void __iomem *base;
182 struct clk *clk;
183};
184
185static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
186 enum snd_soc_bias_level level)
187{
188 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
189 struct regmap *regmap = jz_codec->regmap;
190
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);
195
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;
211 }
212
213 return 0;
214}
215
216static int jz4770_codec_startup(struct snd_pcm_substream *substream,
217 struct snd_soc_dai *dai)
218{
219 struct snd_soc_component *codec = dai->component;
220 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
221
222 /*
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.
226 */
227 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
228 snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
229
230 return 0;
231}
232
233static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
234 struct snd_soc_dai *dai)
235{
236 struct snd_soc_component *codec = dai->component;
237 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
238
239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
240 snd_soc_dapm_disable_pin(dapm, "SYSCLK");
241}
242
243
244static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
245 int cmd, struct snd_soc_dai *dai)
246{
247 struct snd_soc_component *codec = dai->component;
248 int ret = 0;
249
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;
265 }
266
267 return ret;
268}
269
270static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
271{
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;
277
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);
283
284 if (val & BIT(REG_CR_DAC_SB_OFFSET))
285 return 1;
286
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;
295 }
296
297 /* clear GUP/GDO flag */
298 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
299 gain_bit);
300 }
301
302 return 0;
303}
304
305/* unit: 0.01dB */
306static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
307static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
308static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
309static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
310static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
311
312/* Unconditional controls. */
313static 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),
319
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),
323
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),
327
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),
331};
332
333static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
334 {
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,
343 /*
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.
347 */
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),
352 },
353};
354
355static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
356 {
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),
370 },
371};
372
373static int hpout_event(struct snd_soc_dapm_widget *w,
374 struct snd_kcontrol *kcontrol, int event)
375{
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;
380
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;
387
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;
397 }
398
399 /* clear RUP flag */
400 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
401 REG_IFR_RUP);
402
403 break;
404
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);
409
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;
417 }
418
419 /* clear RDO flag */
420 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
421 REG_IFR_RDO);
422
423 break;
424 }
425
426 return 0;
427}
428
429static int adc_poweron_event(struct snd_soc_dapm_widget *w,
430 struct snd_kcontrol *kcontrol, int event)
431{
432 if (event == SND_SOC_DAPM_POST_PMU)
433 msleep(1000);
434
435 return 0;
436}
437
438static const char * const jz4770_codec_hp_texts[] = {
439 "PCM", "Line In", "Mic 1", "Mic 2"
440};
441static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
442static 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);
448static const struct snd_kcontrol_new jz4770_codec_hp_source =
449 SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
450
451static 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);
457static const struct snd_kcontrol_new jz4770_codec_lo_source =
458 SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
459
460static const char * const jz4770_codec_cap_texts[] = {
461 "Line In", "Mic 1", "Mic 2"
462};
463static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
464static 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);
470static const struct snd_kcontrol_new jz4770_codec_cap_source =
471 SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
472
473static 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),
476};
477
478static 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),
483
484 SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
485 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
486
487 SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
488 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
489
490 SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
491 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
492
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),
499
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),
504
505 SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
506 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
507
508 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
509 jz4770_codec_mic_controls,
510 ARRAY_SIZE(jz4770_codec_mic_controls)),
511
512 SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
513 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
514
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),
520
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)),
527
528 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
529 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
530
531 SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
532 REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
533
534 SND_SOC_DAPM_INPUT("MIC1P"),
535 SND_SOC_DAPM_INPUT("MIC1N"),
536 SND_SOC_DAPM_INPUT("MIC2P"),
537 SND_SOC_DAPM_INPUT("MIC2N"),
538
539 SND_SOC_DAPM_OUTPUT("LOUT"),
540 SND_SOC_DAPM_OUTPUT("ROUT"),
541
542 SND_SOC_DAPM_OUTPUT("LHPOUT"),
543 SND_SOC_DAPM_OUTPUT("RHPOUT"),
544
545 SND_SOC_DAPM_INPUT("LLINEIN"),
546 SND_SOC_DAPM_INPUT("RLINEIN"),
547
548 SND_SOC_DAPM_OUTPUT("SYSCLK"),
549};
550
551/* Unconditional routes. */
552static 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" },
559
560 { "Line In", NULL, "LLINEIN" },
561 { "Line In", NULL, "RLINEIN" },
562
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" },
569
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" },
575
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" },
580
581 { "Line In Bypass", NULL, "Line In" },
582 { "Line Out Source", "Line In", "Line In Bypass" },
583 { "Line Out Source", "PCM", "PCM Playback" },
584
585 { "LHPOUT", NULL, "HP Out"},
586 { "RHPOUT", NULL, "HP Out"},
587
588 { "Line Out", NULL, "Line Out Source" },
589 { "Line Out Switch 2", NULL, "Line Out" },
590
591 { "LOUT", NULL, "Line Out Switch 2"},
592 { "ROUT", NULL, "Line Out Switch 2"},
593
594 { "PCM Playback", "Volume", "DAC" },
595 { "Headphones Playback", "Volume", "PCM Playback" },
596
597 { "SYSCLK", NULL, "DAC" },
598};
599
600static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
601{
602 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
603 struct regmap *regmap = jz_codec->regmap;
604
605 /* Collect updates for later sending. */
606 regcache_cache_only(regmap, true);
607
608 /* default HP output to PCM */
609 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
610
611 /* default line output to PCM */
612 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
613
614 /* Disable stereo mic */
615 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
616 BIT(REG_CR_MIC_STEREO_OFFSET));
617
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);
621
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);
627
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);
634
635 /* 12M oscillator */
636 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
637
638 /* 0: 16ohm/220uF, 1: 10kohm/1uF */
639 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
640
641 /* disable automatic gain */
642 regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
643
644 /* Disable DAC lrswap */
645 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
646
647 /* Independent L/R DAC gain control */
648 regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
649 REG_GCR_DACL_RLGOD);
650
651 /* Disable ADC lrswap */
652 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
653
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));
657
658 /* Send collected updates. */
659 regcache_cache_only(regmap, false);
660 regcache_sync(regmap);
661}
662
663static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
664{
665 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
666
667 clk_prepare_enable(jz_codec->clk);
668
669 jz4770_codec_codec_init_regs(codec);
670
671 return 0;
672}
673
674static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
675{
676 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
677
678 clk_disable_unprepare(jz_codec->clk);
679}
680
681static 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,
693};
694
695static const unsigned int jz4770_codec_sample_rates[] = {
696 96000, 48000, 44100, 32000,
697 24000, 22050, 16000, 12000,
698 11025, 9600, 8000,
699};
700
701static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
702 struct snd_pcm_hw_params *params,
703 struct snd_soc_dai *dai)
704{
705 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
706 unsigned int rate, bit_width;
707
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;
723 }
724
725 for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
726 if (jz4770_codec_sample_rates[rate] == params_rate(params))
727 break;
728 }
729
730 if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
731 return -EINVAL;
732
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);
747 }
748
749 return 0;
750}
751
752static 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,
759};
760
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)
765
766static 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,
774 },
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,
781 },
782 .ops = &jz4770_codec_dai_ops,
783};
784
785static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
786{
787 return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
788}
789
790static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
791{
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;
798 }
799}
800
801static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
802{
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;
810 }
811}
812
813static int jz4770_codec_io_wait(struct jz_codec *codec)
814{
815 u32 reg;
816
817 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
818 !(reg & ICDC_RGADW_RGWR),
819 1000, 1 * USEC_PER_SEC);
820}
821
822static int jz4770_codec_reg_read(void *context, unsigned int reg,
823 unsigned int *val)
824{
825 struct jz_codec *codec = context;
826 unsigned int i;
827 u32 tmp;
828 int ret;
829
830 ret = jz4770_codec_io_wait(codec);
831 if (ret)
832 return ret;
833
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);
838
839 /* wait 6+ cycles */
840 for (i = 0; i < 6; i++)
841 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
842 ICDC_RGDATA_RGDOUT_MASK;
843
844 return 0;
845}
846
847static int jz4770_codec_reg_write(void *context, unsigned int reg,
848 unsigned int val)
849{
850 struct jz_codec *codec = context;
851 int ret;
852
853 ret = jz4770_codec_io_wait(codec);
854 if (ret)
855 return ret;
856
857 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
858 codec->base + ICDC_RGADW_OFFSET);
859
860 ret = jz4770_codec_io_wait(codec);
861 if (ret)
862 return ret;
863
864 return 0;
865}
866
867static 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
873};
874
875static const struct regmap_config jz4770_codec_regmap_config = {
876 .reg_bits = 7,
877 .val_bits = 8,
878
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,
883
884 .reg_read = jz4770_codec_reg_read,
885 .reg_write = jz4770_codec_reg_write,
886
887 .reg_defaults_raw = jz4770_codec_reg_defaults,
888 .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
889 .cache_type = REGCACHE_FLAT,
890};
891
892static int jz4770_codec_probe(struct platform_device *pdev)
893{
894 struct device *dev = &pdev->dev;
895 struct jz_codec *codec;
896 int ret;
897
898 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
899 if (!codec)
900 return -ENOMEM;
901
902 codec->dev = dev;
903
904 codec->base = devm_platform_ioremap_resource(pdev, 0);
905 if (IS_ERR(codec->base))
906 return PTR_ERR(codec->base);
907
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);
912
913 codec->clk = devm_clk_get(dev, "aic");
914 if (IS_ERR(codec->clk))
915 return PTR_ERR(codec->clk);
916
917 platform_set_drvdata(pdev, codec);
918
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;
924 }
925
926 return 0;
927}
928
929static const struct of_device_id jz4770_codec_of_matches[] = {
930 { .compatible = "ingenic,jz4770-codec", },
931 { /* sentinel */ }
932};
933MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
934
935static 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,
940 },
941};
942module_platform_driver(jz4770_codec_driver);
943
944MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
945MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
946MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
947MODULE_LICENSE("GPL v2");
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>
7
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>
14
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>
20
21#define ICDC_RGADW_OFFSET 0x00
22#define ICDC_RGDATA_OFFSET 0x04
23
24/* ICDC internal register access control register(RGADW) */
25#define ICDC_RGADW_RGWR BIT(16)
26
27#define ICDC_RGADW_RGADDR_OFFSET 8
28#define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
29
30#define ICDC_RGADW_RGDIN_OFFSET 0
31#define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
32
33/* ICDC internal register data output register (RGDATA)*/
34#define ICDC_RGDATA_IRQ BIT(8)
35
36#define ICDC_RGDATA_RGDOUT_OFFSET 0
37#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
38
39/* Internal register space, accessed through regmap */
40enum {
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,
46
47 JZ4770_CODEC_REG_MISSING_REG1,
48
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,
71
72 JZ4770_CODEC_REG_MISSING_REG2,
73
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,
81};
82
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)
87
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)
92
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)
97
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)
104
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)
110
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
117
118#define REG_CR_LI_LIBY_OFFSET 4
119#define REG_CR_LI_SB_OFFSET 0
120
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)
128
129#define REG_CR_VIC_SB_SLEEP BIT(1)
130#define REG_CR_VIC_SB BIT(0)
131
132#define REG_CCR_CRYSTAL_OFFSET 0
133#define REG_CCR_CRYSTAL_MASK (0xf << REG_CCR_CRYSTAL_OFFSET)
134
135#define REG_FCR_DAC_FREQ_OFFSET 0
136#define REG_FCR_DAC_FREQ_MASK (0xf << REG_FCR_DAC_FREQ_OFFSET)
137
138#define REG_FCR_ADC_FREQ_OFFSET 0
139#define REG_FCR_ADC_FREQ_MASK (0xf << REG_FCR_ADC_FREQ_OFFSET)
140
141#define REG_ICR_INT_FORM_OFFSET 6
142#define REG_ICR_INT_FORM_MASK (0x3 << REG_ICR_INT_FORM_OFFSET)
143
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)
152
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)
161
162#define REG_GCR_HPL_LRGO BIT(7)
163
164#define REG_GCR_DACL_RLGOD BIT(7)
165
166#define REG_GCR_GAIN_OFFSET 0
167#define REG_GCR_GAIN_MAX 0x1f
168
169#define REG_GCR_MIC_GAIN_OFFSET 0
170#define REG_GCR_MIC_GAIN_MAX 5
171
172#define REG_GCR_ADC_GAIN_OFFSET 0
173#define REG_GCR_ADC_GAIN_MAX 23
174
175#define REG_AGC1_EN BIT(7)
176
177/* codec private data */
178struct jz_codec {
179 struct device *dev;
180 struct regmap *regmap;
181 void __iomem *base;
182 struct clk *clk;
183};
184
185static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
186 enum snd_soc_bias_level level)
187{
188 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
189 struct regmap *regmap = jz_codec->regmap;
190
191 switch (level) {
192 case SND_SOC_BIAS_PREPARE:
193 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
194 REG_CR_VIC_SB, 0);
195 msleep(250);
196 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
197 REG_CR_VIC_SB_SLEEP, 0);
198 msleep(400);
199 break;
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);
205 fallthrough;
206 default:
207 break;
208 }
209
210 return 0;
211}
212
213static int jz4770_codec_startup(struct snd_pcm_substream *substream,
214 struct snd_soc_dai *dai)
215{
216 struct snd_soc_component *codec = dai->component;
217 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
218
219 /*
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
222 * been disabled.
223 */
224 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
225 snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
226
227 return 0;
228}
229
230static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
231 struct snd_soc_dai *dai)
232{
233 struct snd_soc_component *codec = dai->component;
234 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
235
236 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
237 snd_soc_dapm_disable_pin(dapm, "SYSCLK");
238}
239
240
241static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
242 int cmd, struct snd_soc_dai *dai)
243{
244 struct snd_soc_component *codec = dai->component;
245 int ret = 0;
246
247 switch (cmd) {
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,
253 SND_SOC_BIAS_ON);
254 break;
255 case SNDRV_PCM_TRIGGER_STOP:
256 case SNDRV_PCM_TRIGGER_SUSPEND:
257 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
258 /* do nothing */
259 break;
260 default:
261 ret = -EINVAL;
262 }
263
264 return ret;
265}
266
267static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
268{
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;
272 unsigned int val;
273 int change, err;
274
275 change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
276 REG_CR_DAC_MUTE,
277 mute ? REG_CR_DAC_MUTE : 0);
278 if (change == 1) {
279 regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
280
281 if (val & BIT(REG_CR_DAC_SB_OFFSET))
282 return 1;
283
284 err = regmap_read_poll_timeout(jz_codec->regmap,
285 JZ4770_CODEC_REG_IFR,
286 val, val & gain_bit,
287 1000, 100 * USEC_PER_MSEC);
288 if (err) {
289 dev_err(jz_codec->dev,
290 "Timeout while setting digital mute: %d", err);
291 return err;
292 }
293
294 /* clear GUP/GDO flag */
295 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
296 gain_bit, gain_bit);
297 }
298
299 return 0;
300}
301
302/* unit: 0.01dB */
303static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
304static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
305static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
306static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
307
308/* Unconditional controls. */
309static 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,
314 0, adc_tlv),
315
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),
319};
320
321static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
322 {
323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
324 .name = "Volume",
325 .info = snd_soc_info_volsw,
326 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
327 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
328 .tlv.p = dac_tlv,
329 .get = snd_soc_dapm_get_volsw,
330 .put = snd_soc_dapm_put_volsw,
331 /*
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.
335 */
336 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
337 JZ4770_CODEC_REG_GCR_DACL,
338 REG_GCR_GAIN_OFFSET,
339 REG_GCR_GAIN_MAX, 1),
340 },
341};
342
343static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
344 {
345 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
346 .name = "Volume",
347 .info = snd_soc_info_volsw,
348 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
349 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
350 .tlv.p = out_tlv,
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,
356 REG_GCR_GAIN_OFFSET,
357 REG_GCR_GAIN_MAX, 1),
358 },
359};
360
361static int hpout_event(struct snd_soc_dapm_widget *w,
362 struct snd_kcontrol *kcontrol, int event)
363{
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);
366 unsigned int val;
367 int err;
368
369 switch (event) {
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);
374 break;
375
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);
382 if (err) {
383 dev_err(jz_codec->dev, "RUP timeout: %d", err);
384 return err;
385 }
386
387 /* clear RUP flag */
388 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
389 REG_IFR_RUP, REG_IFR_RUP);
390
391 break;
392
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);
398
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);
403 if (err) {
404 dev_err(jz_codec->dev, "RDO timeout: %d", err);
405 return err;
406 }
407
408 /* clear RDO flag */
409 regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
410 REG_IFR_RDO, REG_IFR_RDO);
411
412 break;
413 }
414
415 return 0;
416}
417
418static int adc_poweron_event(struct snd_soc_dapm_widget *w,
419 struct snd_kcontrol *kcontrol, int event)
420{
421 if (event == SND_SOC_DAPM_POST_PMU)
422 msleep(1000);
423
424 return 0;
425}
426
427static const char * const jz4770_codec_hp_texts[] = {
428 "PCM", "Line In", "Mic 1", "Mic 2"
429};
430static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
431static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
432 JZ4770_CODEC_REG_CR_HP,
433 REG_CR_HP_SEL_OFFSET,
434 REG_CR_HP_SEL_MASK,
435 jz4770_codec_hp_texts,
436 jz4770_codec_hp_values);
437static const struct snd_kcontrol_new jz4770_codec_hp_source =
438 SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
439
440static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
441 JZ4770_CODEC_REG_CR_LO,
442 REG_CR_LO_SEL_OFFSET,
443 REG_CR_LO_SEL_MASK,
444 jz4770_codec_hp_texts,
445 jz4770_codec_hp_values);
446static const struct snd_kcontrol_new jz4770_codec_lo_source =
447 SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
448
449static const char * const jz4770_codec_cap_texts[] = {
450 "Line In", "Mic 1", "Mic 2"
451};
452static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
453static 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);
459static const struct snd_kcontrol_new jz4770_codec_cap_source =
460 SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
461
462static 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),
465};
466
467static 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),
472
473 SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
474 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
475
476 SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
477 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
478
479 SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
480 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
481
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),
488
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),
493
494 SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
495 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
496
497 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
498 jz4770_codec_mic_controls,
499 ARRAY_SIZE(jz4770_codec_mic_controls)),
500
501 SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
502 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
503
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),
509
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)),
516
517 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
518 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
519
520 SND_SOC_DAPM_INPUT("MIC1P"),
521 SND_SOC_DAPM_INPUT("MIC1N"),
522 SND_SOC_DAPM_INPUT("MIC2P"),
523 SND_SOC_DAPM_INPUT("MIC2N"),
524
525 SND_SOC_DAPM_OUTPUT("LOUT"),
526 SND_SOC_DAPM_OUTPUT("ROUT"),
527
528 SND_SOC_DAPM_OUTPUT("LHPOUT"),
529 SND_SOC_DAPM_OUTPUT("RHPOUT"),
530
531 SND_SOC_DAPM_INPUT("LLINEIN"),
532 SND_SOC_DAPM_INPUT("RLINEIN"),
533
534 SND_SOC_DAPM_OUTPUT("SYSCLK"),
535};
536
537/* Unconditional routes. */
538static 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" },
545
546 { "Line In", NULL, "LLINEIN" },
547 { "Line In", NULL, "RLINEIN" },
548
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" },
555
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" },
561
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" },
566
567 { "Line In Bypass", NULL, "Line In" },
568 { "Line Out Source", "Line In", "Line In Bypass" },
569 { "Line Out Source", "PCM", "PCM Playback" },
570
571 { "LHPOUT", NULL, "HP Out"},
572 { "RHPOUT", NULL, "HP Out"},
573
574 { "Line Out", NULL, "Line Out Source" },
575 { "Line Out Switch 2", NULL, "Line Out" },
576
577 { "LOUT", NULL, "Line Out Switch 2"},
578 { "ROUT", NULL, "Line Out Switch 2"},
579
580 { "PCM Playback", "Volume", "DAC" },
581 { "Headphones Playback", "Volume", "PCM Playback" },
582
583 { "SYSCLK", NULL, "DAC" },
584};
585
586static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
587{
588 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
589 struct regmap *regmap = jz_codec->regmap;
590
591 /* Collect updates for later sending. */
592 regcache_cache_only(regmap, true);
593
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);
597
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);
601
602 /* Disable stereo mic */
603 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
604 BIT(REG_CR_MIC_STEREO_OFFSET), 0);
605
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);
609
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);
617
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 |
624 REG_IMR_GDO_MASK);
625
626 /* 12M oscillator */
627 regmap_update_bits(regmap, JZ4770_CODEC_REG_CCR,
628 REG_CCR_CRYSTAL_MASK, 0);
629
630 /* 0: 16ohm/220uF, 1: 10kohm/1uF */
631 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
632 REG_CR_HP_LOAD, 0);
633
634 /* disable automatic gain */
635 regmap_update_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN, 0);
636
637 /* Disable DAC lrswap */
638 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_DAC,
639 REG_CR_DAC_LRSWAP, REG_CR_DAC_LRSWAP);
640
641 /* Independent L/R DAC gain control */
642 regmap_update_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
643 REG_GCR_DACL_RLGOD, 0);
644
645 /* Disable ADC lrswap */
646 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
647 REG_CR_ADC_LRSWAP, REG_CR_ADC_LRSWAP);
648
649 /* default to cap-less mode(0) */
650 regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
651 REG_CR_HP_SB_HPCM, 0);
652
653 /* Send collected updates. */
654 regcache_cache_only(regmap, false);
655 regcache_sync(regmap);
656
657 /* Reset all interrupt flags. */
658 regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
659}
660
661static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
662{
663 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
664
665 clk_prepare_enable(jz_codec->clk);
666
667 jz4770_codec_codec_init_regs(codec);
668
669 return 0;
670}
671
672static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
673{
674 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
675
676 clk_disable_unprepare(jz_codec->clk);
677}
678
679static 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,
691};
692
693static const unsigned int jz4770_codec_sample_rates[] = {
694 96000, 48000, 44100, 32000,
695 24000, 22050, 16000, 12000,
696 11025, 9600, 8000,
697};
698
699static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
700 struct snd_pcm_hw_params *params,
701 struct snd_soc_dai *dai)
702{
703 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
704 unsigned int rate, bit_width;
705
706 switch (params_format(params)) {
707 case SNDRV_PCM_FORMAT_S16_LE:
708 bit_width = 0;
709 break;
710 case SNDRV_PCM_FORMAT_S18_3LE:
711 bit_width = 1;
712 break;
713 case SNDRV_PCM_FORMAT_S20_3LE:
714 bit_width = 2;
715 break;
716 case SNDRV_PCM_FORMAT_S24_3LE:
717 bit_width = 3;
718 break;
719 default:
720 return -EINVAL;
721 }
722
723 for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
724 if (jz4770_codec_sample_rates[rate] == params_rate(params))
725 break;
726 }
727
728 if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
729 return -EINVAL;
730
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);
738 } else {
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);
745 }
746
747 return 0;
748}
749
750static 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,
757};
758
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)
763
764static struct snd_soc_dai_driver jz4770_codec_dai = {
765 .name = "jz4770-hifi",
766 .playback = {
767 .stream_name = "Playback",
768 .channels_min = 2,
769 .channels_max = 2,
770 .rates = SNDRV_PCM_RATE_8000_96000,
771 .formats = JZ_CODEC_FORMATS,
772 },
773 .capture = {
774 .stream_name = "Capture",
775 .channels_min = 2,
776 .channels_max = 2,
777 .rates = SNDRV_PCM_RATE_8000_96000,
778 .formats = JZ_CODEC_FORMATS,
779 },
780 .ops = &jz4770_codec_dai_ops,
781};
782
783static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
784{
785 return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
786}
787
788static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
789{
790 switch (reg) {
791 case JZ4770_CODEC_REG_MISSING_REG1:
792 case JZ4770_CODEC_REG_MISSING_REG2:
793 return false;
794 default:
795 return true;
796 }
797}
798
799static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
800{
801 switch (reg) {
802 case JZ4770_CODEC_REG_SR:
803 case JZ4770_CODEC_REG_MISSING_REG1:
804 case JZ4770_CODEC_REG_MISSING_REG2:
805 return false;
806 default:
807 return true;
808 }
809}
810
811static int jz4770_codec_io_wait(struct jz_codec *codec)
812{
813 u32 reg;
814
815 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
816 !(reg & ICDC_RGADW_RGWR),
817 1000, 10 * USEC_PER_MSEC);
818}
819
820static int jz4770_codec_reg_read(void *context, unsigned int reg,
821 unsigned int *val)
822{
823 struct jz_codec *codec = context;
824 unsigned int i;
825 u32 tmp;
826 int ret;
827
828 ret = jz4770_codec_io_wait(codec);
829 if (ret)
830 return ret;
831
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);
836
837 /* wait 6+ cycles */
838 for (i = 0; i < 6; i++)
839 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
840 ICDC_RGDATA_RGDOUT_MASK;
841
842 return 0;
843}
844
845static int jz4770_codec_reg_write(void *context, unsigned int reg,
846 unsigned int val)
847{
848 struct jz_codec *codec = context;
849 int ret;
850
851 ret = jz4770_codec_io_wait(codec);
852 if (ret)
853 return ret;
854
855 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
856 codec->base + ICDC_RGADW_OFFSET);
857
858 ret = jz4770_codec_io_wait(codec);
859 if (ret)
860 return ret;
861
862 return 0;
863}
864
865static 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
871};
872
873static struct regmap_config jz4770_codec_regmap_config = {
874 .reg_bits = 7,
875 .val_bits = 8,
876
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,
881
882 .reg_read = jz4770_codec_reg_read,
883 .reg_write = jz4770_codec_reg_write,
884
885 .reg_defaults_raw = jz4770_codec_reg_defaults,
886 .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
887 .cache_type = REGCACHE_FLAT,
888};
889
890static int jz4770_codec_probe(struct platform_device *pdev)
891{
892 struct device *dev = &pdev->dev;
893 struct jz_codec *codec;
894 int ret;
895
896 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
897 if (!codec)
898 return -ENOMEM;
899
900 codec->dev = dev;
901
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);
906 return ret;
907 }
908
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);
913
914 codec->clk = devm_clk_get(dev, "aic");
915 if (IS_ERR(codec->clk))
916 return PTR_ERR(codec->clk);
917
918 platform_set_drvdata(pdev, codec);
919
920 ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
921 &jz4770_codec_dai, 1);
922 if (ret) {
923 dev_err(dev, "Failed to register codec: %d\n", ret);
924 return ret;
925 }
926
927 return 0;
928}
929
930static const struct of_device_id jz4770_codec_of_matches[] = {
931 { .compatible = "ingenic,jz4770-codec", },
932 { /* sentinel */ }
933};
934MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
935
936static struct platform_driver jz4770_codec_driver = {
937 .probe = jz4770_codec_probe,
938 .driver = {
939 .name = "jz4770-codec",
940 .of_match_table = jz4770_codec_of_matches,
941 },
942};
943module_platform_driver(jz4770_codec_driver);
944
945MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
946MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
947MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
948MODULE_LICENSE("GPL v2");