ARM: dts: omap5: Add bus_dma_limit for L3 bus
[linux/fpc-iii.git] / sound / soc / codecs / jz4725b.c
blob2567a5d15b554a1774789749e8c8b5681be19041
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // JZ4725B CODEC driver
4 //
5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
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>
16 #include <linux/delay.h>
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>
25 #define ICDC_RGADW_OFFSET 0x00
26 #define ICDC_RGDATA_OFFSET 0x04
28 /* ICDC internal register access control register(RGADW) */
29 #define ICDC_RGADW_RGWR BIT(16)
31 #define ICDC_RGADW_RGADDR_OFFSET 8
32 #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
34 #define ICDC_RGADW_RGDIN_OFFSET 0
35 #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
37 /* ICDC internal register data output register (RGDATA)*/
38 #define ICDC_RGDATA_IRQ BIT(8)
40 #define ICDC_RGDATA_RGDOUT_OFFSET 0
41 #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
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,
75 #define REG_AICR_CONFIG1_OFFSET 0
76 #define REG_AICR_CONFIG1_MASK (0xf << REG_AICR_CONFIG1_OFFSET)
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
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
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)
101 #define REG_CCR1_CONFIG4_OFFSET 0
102 #define REG_CCR1_CONFIG4_MASK (0xf << REG_CCR1_CONFIG4_OFFSET)
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)
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
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
125 #define REG_IFR_RAMP_UP_DONE_OFFSET 3
126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET 2
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)
133 #define REG_CGR2_GO1R_OFFSET 0
134 #define REG_CGR2_GO1R_MASK (0x1f << REG_CGR2_GO1R_OFFSET)
136 #define REG_CGR3_GO1L_OFFSET 0
137 #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET)
139 struct jz_icdc {
140 struct regmap *regmap;
141 void __iomem *base;
142 struct clk *clk;
145 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0);
146 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600);
148 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
149 SOC_DOUBLE_TLV("Master Playback Volume",
150 JZ4725B_CODEC_REG_CGR1,
151 REG_CGR1_GODL_OFFSET,
152 REG_CGR1_GODR_OFFSET,
153 0xf, 1, jz4725b_dac_tlv),
154 SOC_DOUBLE_R_TLV("Master Capture Volume",
155 JZ4725B_CODEC_REG_CGR3,
156 JZ4725B_CODEC_REG_CGR2,
157 REG_CGR2_GO1R_OFFSET,
158 0x1f, 1, jz4725b_line_tlv),
160 SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
161 REG_CR1_DAC_MUTE_OFFSET, 1, 1),
163 SOC_SINGLE("Deemphasize Filter Playback Switch",
164 JZ4725B_CODEC_REG_CR2,
165 REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
167 SOC_SINGLE("High-Pass Filter Capture Switch",
168 JZ4725B_CODEC_REG_CR2,
169 REG_CR2_ADC_HPF_OFFSET, 1, 0),
172 static const char * const jz4725b_codec_adc_src_texts[] = {
173 "Mic 1", "Mic 2", "Line In", "Mixer",
175 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
176 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
177 JZ4725B_CODEC_REG_CR3,
178 REG_CR3_INSEL_OFFSET,
179 REG_CR3_INSEL_MASK,
180 jz4725b_codec_adc_src_texts,
181 jz4725b_codec_adc_src_values);
182 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
183 SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum);
185 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
186 SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
187 REG_CR1_BYPASS_OFFSET, 1, 0),
190 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
191 struct snd_kcontrol *kcontrol,
192 int event)
194 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
195 struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
196 struct regmap *map = icdc->regmap;
197 unsigned int val;
199 switch (event) {
200 case SND_SOC_DAPM_PRE_PMU:
201 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
202 BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 0);
203 case SND_SOC_DAPM_POST_PMU:
204 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
205 val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
206 100000, 500000);
207 case SND_SOC_DAPM_PRE_PMD:
208 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
209 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 0);
210 case SND_SOC_DAPM_POST_PMD:
211 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
212 val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
213 100000, 500000);
214 default:
215 return -EINVAL;
219 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
220 /* DAC */
221 SND_SOC_DAPM_DAC("DAC", "Playback",
222 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
224 /* ADC */
225 SND_SOC_DAPM_ADC("ADC", "Capture",
226 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
228 SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0,
229 &jz4725b_codec_adc_src_ctrl),
231 /* Mixer */
232 SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
233 REG_PMR1_SB_MIX_OFFSET, 1,
234 jz4725b_codec_mixer_controls,
235 ARRAY_SIZE(jz4725b_codec_mixer_controls)),
236 SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
237 REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
239 SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0),
240 SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
241 REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
243 SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
244 REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
245 SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
246 REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
248 SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
249 REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
250 jz4725b_out_stage_enable,
251 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
252 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
253 SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
254 REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
256 SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
257 REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
259 /* Pins */
260 SND_SOC_DAPM_INPUT("MIC1P"),
261 SND_SOC_DAPM_INPUT("MIC1N"),
262 SND_SOC_DAPM_INPUT("MIC2P"),
263 SND_SOC_DAPM_INPUT("MIC2N"),
265 SND_SOC_DAPM_INPUT("LLINEIN"),
266 SND_SOC_DAPM_INPUT("RLINEIN"),
268 SND_SOC_DAPM_OUTPUT("LHPOUT"),
269 SND_SOC_DAPM_OUTPUT("RHPOUT"),
272 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
273 {"Mic 1", NULL, "MIC1P"},
274 {"Mic 1", NULL, "MIC1N"},
275 {"Mic 2", NULL, "MIC2P"},
276 {"Mic 2", NULL, "MIC2N"},
278 {"Line In", NULL, "LLINEIN"},
279 {"Line In", NULL, "RLINEIN"},
281 {"Mixer", "Line In Bypass", "Line In"},
282 {"DAC to Mixer", NULL, "DAC"},
283 {"Mixer", NULL, "DAC to Mixer"},
285 {"Mixer to ADC", NULL, "Mixer"},
286 {"ADC Source", "Mixer", "Mixer to ADC"},
287 {"ADC Source", "Line In", "Line In"},
288 {"ADC Source", "Mic 1", "Mic 1"},
289 {"ADC Source", "Mic 2", "Mic 2"},
290 {"ADC", NULL, "ADC Source"},
292 {"Out Stage", NULL, "Mixer"},
293 {"HP Out", NULL, "Out Stage"},
294 {"LHPOUT", NULL, "HP Out"},
295 {"RHPOUT", NULL, "HP Out"},
298 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
299 enum snd_soc_bias_level level)
301 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
302 struct regmap *map = icdc->regmap;
304 switch (level) {
305 case SND_SOC_BIAS_ON:
306 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
307 BIT(REG_PMR2_SB_SLEEP_OFFSET), 0);
308 break;
309 case SND_SOC_BIAS_PREPARE:
310 /* Enable sound hardware */
311 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
312 BIT(REG_PMR2_SB_OFFSET), 0);
313 msleep(224);
314 break;
315 case SND_SOC_BIAS_STANDBY:
316 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
317 BIT(REG_PMR2_SB_SLEEP_OFFSET),
318 BIT(REG_PMR2_SB_SLEEP_OFFSET));
319 break;
320 case SND_SOC_BIAS_OFF:
321 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
322 BIT(REG_PMR2_SB_OFFSET),
323 BIT(REG_PMR2_SB_OFFSET));
324 break;
327 return 0;
330 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
332 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
333 struct regmap *map = icdc->regmap;
335 clk_prepare_enable(icdc->clk);
337 /* Write CONFIGn (n=1 to 8) bits.
338 * The value 0x0f is specified in the datasheet as a requirement.
340 regmap_write(map, JZ4725B_CODEC_REG_AICR,
341 0xf << REG_AICR_CONFIG1_OFFSET);
342 regmap_write(map, JZ4725B_CODEC_REG_CCR1,
343 0x0 << REG_CCR1_CONFIG4_OFFSET);
345 return 0;
348 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
350 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
352 clk_disable_unprepare(icdc->clk);
355 static const struct snd_soc_component_driver jz4725b_codec = {
356 .probe = jz4725b_codec_dev_probe,
357 .remove = jz4725b_codec_dev_remove,
358 .set_bias_level = jz4725b_codec_set_bias_level,
359 .controls = jz4725b_codec_controls,
360 .num_controls = ARRAY_SIZE(jz4725b_codec_controls),
361 .dapm_widgets = jz4725b_codec_dapm_widgets,
362 .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
363 .dapm_routes = jz4725b_codec_dapm_routes,
364 .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
365 .suspend_bias_off = 1,
366 .use_pmdown_time = 1,
369 static const unsigned int jz4725b_codec_sample_rates[] = {
370 96000, 48000, 44100, 32000,
371 24000, 22050, 16000, 12000,
372 11025, 9600, 8000,
375 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
376 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
378 struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
379 unsigned int rate, bit_width;
381 switch (params_format(params)) {
382 case SNDRV_PCM_FORMAT_S16_LE:
383 bit_width = 0;
384 break;
385 case SNDRV_PCM_FORMAT_S18_3LE:
386 bit_width = 1;
387 break;
388 case SNDRV_PCM_FORMAT_S20_3LE:
389 bit_width = 2;
390 break;
391 case SNDRV_PCM_FORMAT_S24_3LE:
392 bit_width = 3;
393 break;
394 default:
395 return -EINVAL;
398 for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
399 if (jz4725b_codec_sample_rates[rate] == params_rate(params))
400 break;
403 if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
404 return -EINVAL;
406 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
407 regmap_update_bits(icdc->regmap,
408 JZ4725B_CODEC_REG_CR2,
409 REG_CR2_DAC_ADWL_MASK,
410 bit_width << REG_CR2_DAC_ADWL_OFFSET);
412 regmap_update_bits(icdc->regmap,
413 JZ4725B_CODEC_REG_CCR2,
414 REG_CCR2_DFREQ_MASK,
415 rate << REG_CCR2_DFREQ_OFFSET);
416 } else {
417 regmap_update_bits(icdc->regmap,
418 JZ4725B_CODEC_REG_CR2,
419 REG_CR2_ADC_ADWL_MASK,
420 bit_width << REG_CR2_ADC_ADWL_OFFSET);
422 regmap_update_bits(icdc->regmap,
423 JZ4725B_CODEC_REG_CCR2,
424 REG_CCR2_AFREQ_MASK,
425 rate << REG_CCR2_AFREQ_OFFSET);
428 return 0;
431 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
432 .hw_params = jz4725b_codec_hw_params,
435 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
436 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
438 static struct snd_soc_dai_driver jz4725b_codec_dai = {
439 .name = "jz4725b-hifi",
440 .playback = {
441 .stream_name = "Playback",
442 .channels_min = 2,
443 .channels_max = 2,
444 .rates = SNDRV_PCM_RATE_8000_96000,
445 .formats = JZ_ICDC_FORMATS,
447 .capture = {
448 .stream_name = "Capture",
449 .channels_min = 2,
450 .channels_max = 2,
451 .rates = SNDRV_PCM_RATE_8000_96000,
452 .formats = JZ_ICDC_FORMATS,
454 .ops = &jz4725b_codec_dai_ops,
457 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
459 return reg == JZ4725B_CODEC_REG_IFR;
462 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
464 return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
467 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
469 u32 reg;
471 return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
472 !(reg & ICDC_RGADW_RGWR), 1000, 10000);
475 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
476 unsigned int *val)
478 struct jz_icdc *icdc = context;
479 unsigned int i;
480 u32 tmp;
481 int ret;
483 ret = jz4725b_codec_io_wait(icdc);
484 if (ret)
485 return ret;
487 tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
488 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
489 | (reg << ICDC_RGADW_RGADDR_OFFSET);
490 writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
492 /* wait 6+ cycles */
493 for (i = 0; i < 6; i++)
494 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
495 ICDC_RGDATA_RGDOUT_MASK;
497 return 0;
500 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
501 unsigned int val)
503 struct jz_icdc *icdc = context;
504 int ret;
506 ret = jz4725b_codec_io_wait(icdc);
507 if (ret)
508 return ret;
510 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
511 icdc->base + ICDC_RGADW_OFFSET);
513 ret = jz4725b_codec_io_wait(icdc);
514 if (ret)
515 return ret;
517 return 0;
520 static const u8 jz4725b_codec_reg_defaults[] = {
521 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
522 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
523 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
524 0x07, 0x44, 0x1f, 0x00,
527 static const struct regmap_config jz4725b_codec_regmap_config = {
528 .reg_bits = 7,
529 .val_bits = 8,
531 .max_register = JZ4725B_CODEC_REG_AGC5,
532 .volatile_reg = jz4725b_codec_volatile,
533 .readable_reg = jz4725b_codec_can_access_reg,
534 .writeable_reg = jz4725b_codec_can_access_reg,
536 .reg_read = jz4725b_codec_reg_read,
537 .reg_write = jz4725b_codec_reg_write,
539 .reg_defaults_raw = jz4725b_codec_reg_defaults,
540 .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
541 .cache_type = REGCACHE_FLAT,
544 static int jz4725b_codec_probe(struct platform_device *pdev)
546 struct device *dev = &pdev->dev;
547 struct jz_icdc *icdc;
548 int ret;
550 icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
551 if (!icdc)
552 return -ENOMEM;
554 icdc->base = devm_platform_ioremap_resource(pdev, 0);
555 if (IS_ERR(icdc->base))
556 return PTR_ERR(icdc->base);
558 icdc->regmap = devm_regmap_init(dev, NULL, icdc,
559 &jz4725b_codec_regmap_config);
560 if (IS_ERR(icdc->regmap))
561 return PTR_ERR(icdc->regmap);
563 icdc->clk = devm_clk_get(&pdev->dev, "aic");
564 if (IS_ERR(icdc->clk))
565 return PTR_ERR(icdc->clk);
567 platform_set_drvdata(pdev, icdc);
569 ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
570 &jz4725b_codec_dai, 1);
571 if (ret)
572 dev_err(dev, "Failed to register codec\n");
574 return ret;
577 #ifdef CONFIG_OF
578 static const struct of_device_id jz4725b_codec_of_matches[] = {
579 { .compatible = "ingenic,jz4725b-codec", },
582 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
583 #endif
585 static struct platform_driver jz4725b_codec_driver = {
586 .probe = jz4725b_codec_probe,
587 .driver = {
588 .name = "jz4725b-codec",
589 .of_match_table = of_match_ptr(jz4725b_codec_of_matches),
592 module_platform_driver(jz4725b_codec_driver);
594 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
595 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
596 MODULE_LICENSE("GPL v2");