xref: /linux/sound/soc/codecs/jz4725b.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // JZ4725B CODEC driver
4 //
5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
6 
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/slab.h>
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/regmap.h>
14 #include <linux/clk.h>
15 
16 #include <linux/delay.h>
17 
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/initval.h>
22 #include <sound/soc.h>
23 #include <sound/tlv.h>
24 
25 #define ICDC_RGADW_OFFSET		0x00
26 #define ICDC_RGDATA_OFFSET		0x04
27 
28 /* ICDC internal register access control register(RGADW) */
29 #define ICDC_RGADW_RGWR			BIT(16)
30 
31 #define ICDC_RGADW_RGADDR_OFFSET	8
32 #define	ICDC_RGADW_RGADDR_MASK		GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
33 
34 #define ICDC_RGADW_RGDIN_OFFSET		0
35 #define	ICDC_RGADW_RGDIN_MASK		GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
36 
37 /* ICDC internal register data output register (RGDATA)*/
38 #define ICDC_RGDATA_IRQ			BIT(8)
39 
40 #define ICDC_RGDATA_RGDOUT_OFFSET	0
41 #define ICDC_RGDATA_RGDOUT_MASK		GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
42 
43 /* JZ internal register space */
44 enum {
45 	JZ4725B_CODEC_REG_AICR,
46 	JZ4725B_CODEC_REG_CR1,
47 	JZ4725B_CODEC_REG_CR2,
48 	JZ4725B_CODEC_REG_CCR1,
49 	JZ4725B_CODEC_REG_CCR2,
50 	JZ4725B_CODEC_REG_PMR1,
51 	JZ4725B_CODEC_REG_PMR2,
52 	JZ4725B_CODEC_REG_CRR,
53 	JZ4725B_CODEC_REG_ICR,
54 	JZ4725B_CODEC_REG_IFR,
55 	JZ4725B_CODEC_REG_CGR1,
56 	JZ4725B_CODEC_REG_CGR2,
57 	JZ4725B_CODEC_REG_CGR3,
58 	JZ4725B_CODEC_REG_CGR4,
59 	JZ4725B_CODEC_REG_CGR5,
60 	JZ4725B_CODEC_REG_CGR6,
61 	JZ4725B_CODEC_REG_CGR7,
62 	JZ4725B_CODEC_REG_CGR8,
63 	JZ4725B_CODEC_REG_CGR9,
64 	JZ4725B_CODEC_REG_CGR10,
65 	JZ4725B_CODEC_REG_TR1,
66 	JZ4725B_CODEC_REG_TR2,
67 	JZ4725B_CODEC_REG_CR3,
68 	JZ4725B_CODEC_REG_AGC1,
69 	JZ4725B_CODEC_REG_AGC2,
70 	JZ4725B_CODEC_REG_AGC3,
71 	JZ4725B_CODEC_REG_AGC4,
72 	JZ4725B_CODEC_REG_AGC5,
73 };
74 
75 #define REG_AICR_CONFIG1_OFFSET		0
76 #define REG_AICR_CONFIG1_MASK		(0xf << REG_AICR_CONFIG1_OFFSET)
77 
78 #define REG_CR1_SB_MICBIAS_OFFSET	7
79 #define REG_CR1_MONO_OFFSET		6
80 #define REG_CR1_DAC_MUTE_OFFSET		5
81 #define REG_CR1_HP_DIS_OFFSET		4
82 #define REG_CR1_DACSEL_OFFSET		3
83 #define REG_CR1_BYPASS_OFFSET		2
84 
85 #define REG_CR2_DAC_DEEMP_OFFSET	7
86 #define REG_CR2_DAC_ADWL_OFFSET		5
87 #define REG_CR2_DAC_ADWL_MASK		(0x3 << REG_CR2_DAC_ADWL_OFFSET)
88 #define REG_CR2_ADC_ADWL_OFFSET		3
89 #define REG_CR2_ADC_ADWL_MASK		(0x3 << REG_CR2_ADC_ADWL_OFFSET)
90 #define REG_CR2_ADC_HPF_OFFSET		2
91 
92 #define REG_CR3_SB_MIC1_OFFSET		7
93 #define REG_CR3_SB_MIC2_OFFSET		6
94 #define REG_CR3_SIDETONE1_OFFSET	5
95 #define REG_CR3_SIDETONE2_OFFSET	4
96 #define REG_CR3_MICDIFF_OFFSET		3
97 #define REG_CR3_MICSTEREO_OFFSET	2
98 #define REG_CR3_INSEL_OFFSET		0
99 #define REG_CR3_INSEL_MASK		(0x3 << REG_CR3_INSEL_OFFSET)
100 
101 #define REG_CCR1_CONFIG4_OFFSET		0
102 #define REG_CCR1_CONFIG4_MASK		(0xf << REG_CCR1_CONFIG4_OFFSET)
103 
104 #define REG_CCR2_DFREQ_OFFSET		4
105 #define REG_CCR2_DFREQ_MASK		(0xf << REG_CCR2_DFREQ_OFFSET)
106 #define REG_CCR2_AFREQ_OFFSET		0
107 #define REG_CCR2_AFREQ_MASK		(0xf << REG_CCR2_AFREQ_OFFSET)
108 
109 #define REG_PMR1_SB_DAC_OFFSET		7
110 #define REG_PMR1_SB_OUT_OFFSET		6
111 #define REG_PMR1_SB_MIX_OFFSET		5
112 #define REG_PMR1_SB_ADC_OFFSET		4
113 #define REG_PMR1_SB_LIN_OFFSET		3
114 #define REG_PMR1_SB_IND_OFFSET		0
115 
116 #define REG_PMR2_LRGI_OFFSET		7
117 #define REG_PMR2_RLGI_OFFSET		6
118 #define REG_PMR2_LRGOD_OFFSET		5
119 #define REG_PMR2_RLGOD_OFFSET		4
120 #define REG_PMR2_GIM_OFFSET		3
121 #define REG_PMR2_SB_MC_OFFSET		2
122 #define REG_PMR2_SB_OFFSET		1
123 #define REG_PMR2_SB_SLEEP_OFFSET	0
124 
125 #define REG_IFR_RAMP_UP_DONE_OFFSET	3
126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET	2
127 
128 #define REG_CGR1_GODL_OFFSET		4
129 #define REG_CGR1_GODL_MASK		(0xf << REG_CGR1_GODL_OFFSET)
130 #define REG_CGR1_GODR_OFFSET		0
131 #define REG_CGR1_GODR_MASK		(0xf << REG_CGR1_GODR_OFFSET)
132 
133 #define REG_CGR2_GO1R_OFFSET		0
134 #define REG_CGR2_GO1R_MASK		(0x1f << REG_CGR2_GO1R_OFFSET)
135 
136 #define REG_CGR3_GO1L_OFFSET		0
137 #define REG_CGR3_GO1L_MASK		(0x1f << REG_CGR3_GO1L_OFFSET)
138 
139 #define REG_CGR4_GO2R_OFFSET		0
140 #define REG_CGR4_GO2R_MASK		(0x1f << REG_CGR4_GO2R_OFFSET)
141 
142 #define REG_CGR5_GO2L_OFFSET		0
143 #define REG_CGR5_GO2L_MASK		(0x1f << REG_CGR5_GO2L_OFFSET)
144 
145 #define REG_CGR6_GO3R_OFFSET		0
146 #define REG_CGR6_GO3R_MASK		(0x1f << REG_CGR6_GO3R_OFFSET)
147 
148 #define REG_CGR7_GO3L_OFFSET		0
149 #define REG_CGR7_GO3L_MASK		(0x1f << REG_CGR7_GO3L_OFFSET)
150 
151 #define REG_CGR8_GOR_OFFSET		0
152 #define REG_CGR8_GOR_MASK		(0x1f << REG_CGR8_GOR_OFFSET)
153 
154 #define REG_CGR9_GOL_OFFSET		0
155 #define REG_CGR9_GOL_MASK		(0x1f << REG_CGR9_GOL_OFFSET)
156 
157 #define REG_CGR10_GIL_OFFSET		0
158 #define REG_CGR10_GIR_OFFSET		4
159 
160 struct jz_icdc {
161 	struct regmap *regmap;
162 	void __iomem *base;
163 };
164 
165 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv,     0, 150, 0);
166 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0);
167 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_mix_tlv,
168 	 0, 11, TLV_DB_SCALE_ITEM(-2250,   0, 0),
169 	12, 31, TLV_DB_SCALE_ITEM(-2250, 150, 0),
170 );
171 
172 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_out_tlv,
173 	 0, 11, TLV_DB_SCALE_ITEM(-3350, 200, 0),
174 	12, 23, TLV_DB_SCALE_ITEM(-1050, 100, 0),
175 	24, 31, TLV_DB_SCALE_ITEM(  100,  50, 0),
176 );
177 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_mic_boost_tlv, 0, 2000, 0);
178 
179 static const char * const jz4725b_mic_mode_texts[] = {
180 	"Single Ended", "Differential",
181 };
182 
183 static const struct soc_enum jz4725b_mic_mode_enum =
184 	SOC_ENUM_SINGLE(JZ4725B_CODEC_REG_CR3, REG_CR3_MICDIFF_OFFSET,
185 			2, jz4725b_mic_mode_texts);
186 
187 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
188 	SOC_DOUBLE_TLV("DAC Playback Volume",
189 		       JZ4725B_CODEC_REG_CGR1,
190 		       REG_CGR1_GODL_OFFSET,
191 		       REG_CGR1_GODR_OFFSET,
192 		       0xf, 1, jz4725b_dac_tlv),
193 	SOC_DOUBLE_TLV("Master Capture Volume",
194 		       JZ4725B_CODEC_REG_CGR10,
195 		       REG_CGR10_GIL_OFFSET,
196 		       REG_CGR10_GIR_OFFSET,
197 		       0xf, 0, jz4725b_adc_tlv),
198 	SOC_DOUBLE_R_TLV("Mixer Line In Bypass Playback Volume",
199 			 JZ4725B_CODEC_REG_CGR3,
200 			 JZ4725B_CODEC_REG_CGR2,
201 			 REG_CGR2_GO1R_OFFSET,
202 			 0x1f, 1, jz4725b_mix_tlv),
203 	SOC_DOUBLE_R_TLV("Mixer Mic 1 Bypass Playback Volume",
204 			 JZ4725B_CODEC_REG_CGR5,
205 			 JZ4725B_CODEC_REG_CGR4,
206 			 REG_CGR4_GO2R_OFFSET,
207 			 0x1f, 1, jz4725b_mix_tlv),
208 	SOC_DOUBLE_R_TLV("Mixer Mic 2 Bypass Playback Volume",
209 			 JZ4725B_CODEC_REG_CGR7,
210 			 JZ4725B_CODEC_REG_CGR6,
211 			 REG_CGR6_GO3R_OFFSET,
212 			 0x1f, 1, jz4725b_mix_tlv),
213 
214 	SOC_DOUBLE_R_TLV("Master Playback Volume",
215 			 JZ4725B_CODEC_REG_CGR9,
216 			 JZ4725B_CODEC_REG_CGR8,
217 			 REG_CGR8_GOR_OFFSET,
218 			 0x1f, 1, jz4725b_out_tlv),
219 
220 	SOC_SINGLE("DAC Playback Switch", JZ4725B_CODEC_REG_CR1,
221 		   REG_CR1_DAC_MUTE_OFFSET, 1, 1),
222 
223 	SOC_SINGLE("Deemphasize Filter Playback Switch",
224 		   JZ4725B_CODEC_REG_CR2,
225 		   REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
226 
227 	SOC_SINGLE("High-Pass Filter Capture Switch",
228 		   JZ4725B_CODEC_REG_CR2,
229 		   REG_CR2_ADC_HPF_OFFSET, 1, 0),
230 
231 	SOC_ENUM("Mic Mode Capture Switch", jz4725b_mic_mode_enum),
232 
233 	SOC_SINGLE_TLV("Mic1 Boost Capture Volume",
234 		       JZ4725B_CODEC_REG_PMR2,
235 		       REG_PMR2_GIM_OFFSET,
236 		       1, 0, jz4725b_mic_boost_tlv),
237 };
238 
239 static const char * const jz4725b_codec_adc_src_texts[] = {
240 	"Mic 1", "Mic 2", "Line In", "Mixer",
241 };
242 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
243 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
244 				  JZ4725B_CODEC_REG_CR3,
245 				  REG_CR3_INSEL_OFFSET,
246 				  REG_CR3_INSEL_MASK,
247 				  jz4725b_codec_adc_src_texts,
248 				  jz4725b_codec_adc_src_values);
249 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
250 	SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum);
251 
252 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
253 	SOC_DAPM_SINGLE("Line In Bypass Playback Switch", JZ4725B_CODEC_REG_CR1,
254 			REG_CR1_BYPASS_OFFSET, 1, 0),
255 	SOC_DAPM_SINGLE("Mic 1 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3,
256 			REG_CR3_SIDETONE1_OFFSET, 1, 0),
257 	SOC_DAPM_SINGLE("Mic 2 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3,
258 			REG_CR3_SIDETONE2_OFFSET, 1, 0),
259 };
260 
261 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
262 				    struct snd_kcontrol *kcontrol,
263 				    int event)
264 {
265 	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
266 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
267 	struct regmap *map = icdc->regmap;
268 	unsigned int val;
269 
270 	switch (event) {
271 	case SND_SOC_DAPM_PRE_PMU:
272 		return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
273 					 BIT(REG_IFR_RAMP_UP_DONE_OFFSET));
274 	case SND_SOC_DAPM_POST_PMU:
275 		return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
276 			       val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
277 			       100000, 500000);
278 	case SND_SOC_DAPM_PRE_PMD:
279 		return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
280 				BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET));
281 	case SND_SOC_DAPM_POST_PMD:
282 		return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
283 			       val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
284 			       100000, 500000);
285 	default:
286 		return -EINVAL;
287 	}
288 }
289 
290 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
291 	/* DAC */
292 	SND_SOC_DAPM_DAC("DAC", "Playback",
293 			 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
294 
295 	/* ADC */
296 	SND_SOC_DAPM_ADC("ADC", "Capture",
297 			 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
298 
299 	SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
300 			 &jz4725b_codec_adc_src_ctrl),
301 
302 	/* Mixer */
303 	SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
304 			   REG_PMR1_SB_MIX_OFFSET, 1,
305 			   jz4725b_codec_mixer_controls,
306 			   ARRAY_SIZE(jz4725b_codec_mixer_controls)),
307 	SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
308 			   REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
309 
310 	SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1,
311 			   REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0),
312 	SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
313 			   REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
314 
315 	SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
316 			   REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
317 	SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
318 			   REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
319 
320 	SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
321 			     REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
322 			     jz4725b_out_stage_enable,
323 			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
324 			     SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
325 	SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
326 			   REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
327 
328 	SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
329 			    REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
330 
331 	/* Pins */
332 	SND_SOC_DAPM_INPUT("MIC1P"),
333 	SND_SOC_DAPM_INPUT("MIC1N"),
334 	SND_SOC_DAPM_INPUT("MIC2P"),
335 	SND_SOC_DAPM_INPUT("MIC2N"),
336 
337 	SND_SOC_DAPM_INPUT("LLINEIN"),
338 	SND_SOC_DAPM_INPUT("RLINEIN"),
339 
340 	SND_SOC_DAPM_OUTPUT("LHPOUT"),
341 	SND_SOC_DAPM_OUTPUT("RHPOUT"),
342 };
343 
344 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
345 	{"Mic 1", NULL, "MIC1P"},
346 	{"Mic 1", NULL, "MIC1N"},
347 	{"Mic 2", NULL, "MIC2P"},
348 	{"Mic 2", NULL, "MIC2N"},
349 
350 	{"Line In", NULL, "LLINEIN"},
351 	{"Line In", NULL, "RLINEIN"},
352 
353 	{"Mixer", "Mic 1 Bypass Playback Switch", "Mic 1"},
354 	{"Mixer", "Mic 2 Bypass Playback Switch", "Mic 2"},
355 	{"Mixer", "Line In Bypass Playback Switch", "Line In"},
356 	{"DAC to Mixer", NULL, "DAC"},
357 	{"Mixer", NULL, "DAC to Mixer"},
358 
359 	{"Mixer to ADC", NULL, "Mixer"},
360 	{"ADC Source Capture Route", "Mixer", "Mixer to ADC"},
361 	{"ADC Source Capture Route", "Line In", "Line In"},
362 	{"ADC Source Capture Route", "Mic 1", "Mic 1"},
363 	{"ADC Source Capture Route", "Mic 2", "Mic 2"},
364 	{"ADC", NULL, "ADC Source Capture Route"},
365 
366 	{"Out Stage", NULL, "Mixer"},
367 	{"HP Out", NULL, "Out Stage"},
368 	{"LHPOUT", NULL, "HP Out"},
369 	{"RHPOUT", NULL, "HP Out"},
370 };
371 
372 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
373 					enum snd_soc_bias_level level)
374 {
375 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
376 	struct regmap *map = icdc->regmap;
377 
378 	switch (level) {
379 	case SND_SOC_BIAS_ON:
380 		regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
381 				  BIT(REG_PMR2_SB_SLEEP_OFFSET));
382 		break;
383 	case SND_SOC_BIAS_PREPARE:
384 		/* Enable sound hardware */
385 		regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
386 				  BIT(REG_PMR2_SB_OFFSET));
387 		msleep(224);
388 		break;
389 	case SND_SOC_BIAS_STANDBY:
390 		regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
391 				BIT(REG_PMR2_SB_SLEEP_OFFSET));
392 		break;
393 	case SND_SOC_BIAS_OFF:
394 		regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
395 				BIT(REG_PMR2_SB_OFFSET));
396 		break;
397 	}
398 
399 	return 0;
400 }
401 
402 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
403 {
404 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
405 	struct regmap *map = icdc->regmap;
406 
407 	/* Write CONFIGn (n=1 to 8) bits.
408 	 * The value 0x0f is specified in the datasheet as a requirement.
409 	 */
410 	regmap_write(map, JZ4725B_CODEC_REG_AICR,
411 		     0xf << REG_AICR_CONFIG1_OFFSET);
412 	regmap_write(map, JZ4725B_CODEC_REG_CCR1,
413 		     0x0 << REG_CCR1_CONFIG4_OFFSET);
414 
415 	return 0;
416 }
417 
418 static const struct snd_soc_component_driver jz4725b_codec = {
419 	.probe			= jz4725b_codec_dev_probe,
420 	.set_bias_level		= jz4725b_codec_set_bias_level,
421 	.controls		= jz4725b_codec_controls,
422 	.num_controls		= ARRAY_SIZE(jz4725b_codec_controls),
423 	.dapm_widgets		= jz4725b_codec_dapm_widgets,
424 	.num_dapm_widgets	= ARRAY_SIZE(jz4725b_codec_dapm_widgets),
425 	.dapm_routes		= jz4725b_codec_dapm_routes,
426 	.num_dapm_routes	= ARRAY_SIZE(jz4725b_codec_dapm_routes),
427 	.suspend_bias_off	= 1,
428 	.use_pmdown_time	= 1,
429 };
430 
431 static const unsigned int jz4725b_codec_sample_rates[] = {
432 	96000, 48000, 44100, 32000,
433 	24000, 22050, 16000, 12000,
434 	11025, 9600, 8000,
435 };
436 
437 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
438 	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
439 {
440 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
441 	unsigned int rate, bit_width;
442 
443 	switch (params_format(params)) {
444 	case SNDRV_PCM_FORMAT_S16_LE:
445 		bit_width = 0;
446 		break;
447 	case SNDRV_PCM_FORMAT_S18_3LE:
448 		bit_width = 1;
449 		break;
450 	case SNDRV_PCM_FORMAT_S20_3LE:
451 		bit_width = 2;
452 		break;
453 	case SNDRV_PCM_FORMAT_S24_3LE:
454 		bit_width = 3;
455 		break;
456 	default:
457 		return -EINVAL;
458 	}
459 
460 	for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
461 		if (jz4725b_codec_sample_rates[rate] == params_rate(params))
462 			break;
463 	}
464 
465 	if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
466 		return -EINVAL;
467 
468 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
469 		regmap_update_bits(icdc->regmap,
470 				   JZ4725B_CODEC_REG_CR2,
471 				   REG_CR2_DAC_ADWL_MASK,
472 				   bit_width << REG_CR2_DAC_ADWL_OFFSET);
473 
474 		regmap_update_bits(icdc->regmap,
475 				   JZ4725B_CODEC_REG_CCR2,
476 				   REG_CCR2_DFREQ_MASK,
477 				   rate << REG_CCR2_DFREQ_OFFSET);
478 	} else {
479 		regmap_update_bits(icdc->regmap,
480 				   JZ4725B_CODEC_REG_CR2,
481 				   REG_CR2_ADC_ADWL_MASK,
482 				   bit_width << REG_CR2_ADC_ADWL_OFFSET);
483 
484 		regmap_update_bits(icdc->regmap,
485 				   JZ4725B_CODEC_REG_CCR2,
486 				   REG_CCR2_AFREQ_MASK,
487 				   rate << REG_CCR2_AFREQ_OFFSET);
488 	}
489 
490 	return 0;
491 }
492 
493 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
494 	.hw_params = jz4725b_codec_hw_params,
495 };
496 
497 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S18_3LE | \
498 			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
499 
500 static struct snd_soc_dai_driver jz4725b_codec_dai = {
501 	.name = "jz4725b-hifi",
502 	.playback = {
503 		.stream_name = "Playback",
504 		.channels_min = 2,
505 		.channels_max = 2,
506 		.rates = SNDRV_PCM_RATE_8000_96000,
507 		.formats = JZ_ICDC_FORMATS,
508 	},
509 	.capture = {
510 		.stream_name = "Capture",
511 		.channels_min = 2,
512 		.channels_max = 2,
513 		.rates = SNDRV_PCM_RATE_8000_96000,
514 		.formats = JZ_ICDC_FORMATS,
515 	},
516 	.ops = &jz4725b_codec_dai_ops,
517 };
518 
519 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
520 {
521 	return reg == JZ4725B_CODEC_REG_IFR;
522 }
523 
524 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
525 {
526 	return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
527 }
528 
529 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
530 {
531 	u32 reg;
532 
533 	return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
534 				  !(reg & ICDC_RGADW_RGWR), 1000, 10000);
535 }
536 
537 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
538 				  unsigned int *val)
539 {
540 	struct jz_icdc *icdc = context;
541 	unsigned int i;
542 	u32 tmp;
543 	int ret;
544 
545 	ret = jz4725b_codec_io_wait(icdc);
546 	if (ret)
547 		return ret;
548 
549 	tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
550 	tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
551 	    | (reg << ICDC_RGADW_RGADDR_OFFSET);
552 	writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
553 
554 	/* wait 6+ cycles */
555 	for (i = 0; i < 6; i++)
556 		*val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
557 			ICDC_RGDATA_RGDOUT_MASK;
558 
559 	return 0;
560 }
561 
562 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
563 				   unsigned int val)
564 {
565 	struct jz_icdc *icdc = context;
566 	int ret;
567 
568 	ret = jz4725b_codec_io_wait(icdc);
569 	if (ret)
570 		return ret;
571 
572 	writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
573 			icdc->base + ICDC_RGADW_OFFSET);
574 
575 	ret = jz4725b_codec_io_wait(icdc);
576 	if (ret)
577 		return ret;
578 
579 	return 0;
580 }
581 
582 static const u8 jz4725b_codec_reg_defaults[] = {
583 	0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
584 	0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
585 	0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
586 	0x07, 0x44, 0x1f, 0x00,
587 };
588 
589 static const struct regmap_config jz4725b_codec_regmap_config = {
590 	.reg_bits = 7,
591 	.val_bits = 8,
592 
593 	.max_register = JZ4725B_CODEC_REG_AGC5,
594 	.volatile_reg = jz4725b_codec_volatile,
595 	.readable_reg = jz4725b_codec_can_access_reg,
596 	.writeable_reg = jz4725b_codec_can_access_reg,
597 
598 	.reg_read = jz4725b_codec_reg_read,
599 	.reg_write = jz4725b_codec_reg_write,
600 
601 	.reg_defaults_raw = jz4725b_codec_reg_defaults,
602 	.num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
603 	.cache_type = REGCACHE_FLAT,
604 };
605 
606 static int jz4725b_codec_probe(struct platform_device *pdev)
607 {
608 	struct device *dev = &pdev->dev;
609 	struct jz_icdc *icdc;
610 	struct clk *clk;
611 	int ret;
612 
613 	icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
614 	if (!icdc)
615 		return -ENOMEM;
616 
617 	icdc->base = devm_platform_ioremap_resource(pdev, 0);
618 	if (IS_ERR(icdc->base))
619 		return PTR_ERR(icdc->base);
620 
621 	icdc->regmap = devm_regmap_init(dev, NULL, icdc,
622 					&jz4725b_codec_regmap_config);
623 	if (IS_ERR(icdc->regmap))
624 		return PTR_ERR(icdc->regmap);
625 
626 	clk = devm_clk_get_enabled(dev, "aic");
627 	if (IS_ERR(clk))
628 		return PTR_ERR(clk);
629 
630 	platform_set_drvdata(pdev, icdc);
631 
632 	ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
633 					      &jz4725b_codec_dai, 1);
634 	if (ret)
635 		dev_err(dev, "Failed to register codec\n");
636 
637 	return ret;
638 }
639 
640 static const struct of_device_id jz4725b_codec_of_matches[] = {
641 	{ .compatible = "ingenic,jz4725b-codec", },
642 	{ }
643 };
644 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
645 
646 static struct platform_driver jz4725b_codec_driver = {
647 	.probe = jz4725b_codec_probe,
648 	.driver = {
649 		.name = "jz4725b-codec",
650 		.of_match_table = jz4725b_codec_of_matches,
651 	},
652 };
653 module_platform_driver(jz4725b_codec_driver);
654 
655 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
656 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
657 MODULE_LICENSE("GPL v2");
658