1 // SPDX-License-Identifier: GPL-2.0
3 // rk3328 ALSA SoC Audio driver
5 // Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/regmap.h>
15 #include <linux/mfd/syscon.h>
16 #include <sound/dmaengine_pcm.h>
17 #include <sound/pcm_params.h>
18 #include "rk3328_codec.h"
27 #define OUT_VOLUME (0x18)
28 #define RK3328_GRF_SOC_CON2 (0x0408)
29 #define RK3328_GRF_SOC_CON10 (0x0428)
30 #define INITIAL_FREQ (11289600)
32 struct rk3328_codec_priv
{
33 struct regmap
*regmap
;
38 int spk_depop_time
; /* msec */
41 static const struct reg_default rk3328_codec_reg_defaults
[] = {
42 { CODEC_RESET
, 0x03 },
43 { DAC_INIT_CTRL1
, 0x00 },
44 { DAC_INIT_CTRL2
, 0x50 },
45 { DAC_INIT_CTRL3
, 0x0e },
46 { DAC_PRECHARGE_CTRL
, 0x01 },
47 { DAC_PWR_CTRL
, 0x00 },
48 { DAC_CLK_CTRL
, 0x00 },
51 { HPOUTL_GAIN_CTRL
, 0x00 },
52 { HPOUTR_GAIN_CTRL
, 0x00 },
53 { HPOUT_POP_CTRL
, 0x11 },
56 static int rk3328_codec_reset(struct rk3328_codec_priv
*rk3328
)
58 regmap_write(rk3328
->regmap
, CODEC_RESET
, 0x00);
60 regmap_write(rk3328
->regmap
, CODEC_RESET
, 0x03);
65 static int rk3328_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
67 struct rk3328_codec_priv
*rk3328
=
68 snd_soc_component_get_drvdata(dai
->component
);
71 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
72 case SND_SOC_DAIFMT_CBS_CFS
:
73 val
= PIN_DIRECTION_IN
| DAC_I2S_MODE_SLAVE
;
75 case SND_SOC_DAIFMT_CBM_CFM
:
76 val
= PIN_DIRECTION_OUT
| DAC_I2S_MODE_MASTER
;
82 regmap_update_bits(rk3328
->regmap
, DAC_INIT_CTRL1
,
83 PIN_DIRECTION_MASK
| DAC_I2S_MODE_MASK
, val
);
85 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
86 case SND_SOC_DAIFMT_DSP_A
:
87 case SND_SOC_DAIFMT_DSP_B
:
90 case SND_SOC_DAIFMT_I2S
:
93 case SND_SOC_DAIFMT_RIGHT_J
:
96 case SND_SOC_DAIFMT_LEFT_J
:
103 regmap_update_bits(rk3328
->regmap
, DAC_INIT_CTRL2
,
109 static void rk3328_analog_output(struct rk3328_codec_priv
*rk3328
, int mute
)
111 unsigned int val
= BIT(17);
116 regmap_write(rk3328
->grf
, RK3328_GRF_SOC_CON10
, val
);
119 static int rk3328_digital_mute(struct snd_soc_dai
*dai
, int mute
)
121 struct rk3328_codec_priv
*rk3328
=
122 snd_soc_component_get_drvdata(dai
->component
);
126 val
= HPOUTL_MUTE
| HPOUTR_MUTE
;
128 val
= HPOUTL_UNMUTE
| HPOUTR_UNMUTE
;
130 regmap_update_bits(rk3328
->regmap
, HPOUT_CTRL
,
131 HPOUTL_MUTE_MASK
| HPOUTR_MUTE_MASK
, val
);
136 static int rk3328_codec_power_on(struct rk3328_codec_priv
*rk3328
, int wait_ms
)
138 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
139 DAC_CHARGE_XCHARGE_MASK
, DAC_CHARGE_PRECHARGE
);
141 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
142 DAC_CHARGE_CURRENT_ALL_MASK
,
143 DAC_CHARGE_CURRENT_ALL_ON
);
149 static int rk3328_codec_power_off(struct rk3328_codec_priv
*rk3328
, int wait_ms
)
151 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
152 DAC_CHARGE_XCHARGE_MASK
, DAC_CHARGE_DISCHARGE
);
154 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
155 DAC_CHARGE_CURRENT_ALL_MASK
,
156 DAC_CHARGE_CURRENT_ALL_ON
);
162 static const struct rk3328_reg_msk_val playback_open_list
[] = {
163 { DAC_PWR_CTRL
, DAC_PWR_MASK
, DAC_PWR_ON
},
164 { DAC_PWR_CTRL
, DACL_PATH_REFV_MASK
| DACR_PATH_REFV_MASK
,
165 DACL_PATH_REFV_ON
| DACR_PATH_REFV_ON
},
166 { DAC_PWR_CTRL
, HPOUTL_ZERO_CROSSING_MASK
| HPOUTR_ZERO_CROSSING_MASK
,
167 HPOUTL_ZERO_CROSSING_ON
| HPOUTR_ZERO_CROSSING_ON
},
168 { HPOUT_POP_CTRL
, HPOUTR_POP_MASK
| HPOUTL_POP_MASK
,
169 HPOUTR_POP_WORK
| HPOUTL_POP_WORK
},
170 { HPMIX_CTRL
, HPMIXL_MASK
| HPMIXR_MASK
, HPMIXL_EN
| HPMIXR_EN
},
171 { HPMIX_CTRL
, HPMIXL_INIT_MASK
| HPMIXR_INIT_MASK
,
172 HPMIXL_INIT_EN
| HPMIXR_INIT_EN
},
173 { HPOUT_CTRL
, HPOUTL_MASK
| HPOUTR_MASK
, HPOUTL_EN
| HPOUTR_EN
},
174 { HPOUT_CTRL
, HPOUTL_INIT_MASK
| HPOUTR_INIT_MASK
,
175 HPOUTL_INIT_EN
| HPOUTR_INIT_EN
},
176 { DAC_CLK_CTRL
, DACL_REFV_MASK
| DACR_REFV_MASK
,
177 DACL_REFV_ON
| DACR_REFV_ON
},
178 { DAC_CLK_CTRL
, DACL_CLK_MASK
| DACR_CLK_MASK
,
179 DACL_CLK_ON
| DACR_CLK_ON
},
180 { DAC_CLK_CTRL
, DACL_MASK
| DACR_MASK
, DACL_ON
| DACR_ON
},
181 { DAC_CLK_CTRL
, DACL_INIT_MASK
| DACR_INIT_MASK
,
182 DACL_INIT_ON
| DACR_INIT_ON
},
183 { DAC_SELECT
, DACL_SELECT_MASK
| DACR_SELECT_MASK
,
184 DACL_SELECT
| DACR_SELECT
},
185 { HPMIX_CTRL
, HPMIXL_INIT2_MASK
| HPMIXR_INIT2_MASK
,
186 HPMIXL_INIT2_EN
| HPMIXR_INIT2_EN
},
187 { HPOUT_CTRL
, HPOUTL_MUTE_MASK
| HPOUTR_MUTE_MASK
,
188 HPOUTL_UNMUTE
| HPOUTR_UNMUTE
},
191 static int rk3328_codec_open_playback(struct rk3328_codec_priv
*rk3328
)
195 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
196 DAC_CHARGE_CURRENT_ALL_MASK
,
197 DAC_CHARGE_CURRENT_I
);
199 for (i
= 0; i
< ARRAY_SIZE(playback_open_list
); i
++) {
200 regmap_update_bits(rk3328
->regmap
,
201 playback_open_list
[i
].reg
,
202 playback_open_list
[i
].msk
,
203 playback_open_list
[i
].val
);
207 msleep(rk3328
->spk_depop_time
);
208 rk3328_analog_output(rk3328
, 1);
210 regmap_update_bits(rk3328
->regmap
, HPOUTL_GAIN_CTRL
,
211 HPOUTL_GAIN_MASK
, OUT_VOLUME
);
212 regmap_update_bits(rk3328
->regmap
, HPOUTR_GAIN_CTRL
,
213 HPOUTR_GAIN_MASK
, OUT_VOLUME
);
218 static const struct rk3328_reg_msk_val playback_close_list
[] = {
219 { HPMIX_CTRL
, HPMIXL_INIT2_MASK
| HPMIXR_INIT2_MASK
,
220 HPMIXL_INIT2_DIS
| HPMIXR_INIT2_DIS
},
221 { DAC_SELECT
, DACL_SELECT_MASK
| DACR_SELECT_MASK
,
222 DACL_UNSELECT
| DACR_UNSELECT
},
223 { HPOUT_CTRL
, HPOUTL_MUTE_MASK
| HPOUTR_MUTE_MASK
,
224 HPOUTL_MUTE
| HPOUTR_MUTE
},
225 { HPOUT_CTRL
, HPOUTL_INIT_MASK
| HPOUTR_INIT_MASK
,
226 HPOUTL_INIT_DIS
| HPOUTR_INIT_DIS
},
227 { HPOUT_CTRL
, HPOUTL_MASK
| HPOUTR_MASK
, HPOUTL_DIS
| HPOUTR_DIS
},
228 { HPMIX_CTRL
, HPMIXL_MASK
| HPMIXR_MASK
, HPMIXL_DIS
| HPMIXR_DIS
},
229 { DAC_CLK_CTRL
, DACL_MASK
| DACR_MASK
, DACL_OFF
| DACR_OFF
},
230 { DAC_CLK_CTRL
, DACL_CLK_MASK
| DACR_CLK_MASK
,
231 DACL_CLK_OFF
| DACR_CLK_OFF
},
232 { DAC_CLK_CTRL
, DACL_REFV_MASK
| DACR_REFV_MASK
,
233 DACL_REFV_OFF
| DACR_REFV_OFF
},
234 { HPOUT_POP_CTRL
, HPOUTR_POP_MASK
| HPOUTL_POP_MASK
,
235 HPOUTR_POP_XCHARGE
| HPOUTL_POP_XCHARGE
},
236 { DAC_PWR_CTRL
, DACL_PATH_REFV_MASK
| DACR_PATH_REFV_MASK
,
237 DACL_PATH_REFV_OFF
| DACR_PATH_REFV_OFF
},
238 { DAC_PWR_CTRL
, DAC_PWR_MASK
, DAC_PWR_OFF
},
239 { HPMIX_CTRL
, HPMIXL_INIT_MASK
| HPMIXR_INIT_MASK
,
240 HPMIXL_INIT_DIS
| HPMIXR_INIT_DIS
},
241 { DAC_CLK_CTRL
, DACL_INIT_MASK
| DACR_INIT_MASK
,
242 DACL_INIT_OFF
| DACR_INIT_OFF
},
245 static int rk3328_codec_close_playback(struct rk3328_codec_priv
*rk3328
)
249 rk3328_analog_output(rk3328
, 0);
251 regmap_update_bits(rk3328
->regmap
, HPOUTL_GAIN_CTRL
,
252 HPOUTL_GAIN_MASK
, 0);
253 regmap_update_bits(rk3328
->regmap
, HPOUTR_GAIN_CTRL
,
254 HPOUTR_GAIN_MASK
, 0);
256 for (i
= 0; i
< ARRAY_SIZE(playback_close_list
); i
++) {
257 regmap_update_bits(rk3328
->regmap
,
258 playback_close_list
[i
].reg
,
259 playback_close_list
[i
].msk
,
260 playback_close_list
[i
].val
);
264 /* Workaround for silence when changed Fs 48 -> 44.1kHz */
265 rk3328_codec_reset(rk3328
);
267 regmap_update_bits(rk3328
->regmap
, DAC_PRECHARGE_CTRL
,
268 DAC_CHARGE_CURRENT_ALL_MASK
,
269 DAC_CHARGE_CURRENT_ALL_ON
);
274 static int rk3328_hw_params(struct snd_pcm_substream
*substream
,
275 struct snd_pcm_hw_params
*params
,
276 struct snd_soc_dai
*dai
)
278 struct rk3328_codec_priv
*rk3328
=
279 snd_soc_component_get_drvdata(dai
->component
);
280 unsigned int val
= 0;
282 switch (params_format(params
)) {
283 case SNDRV_PCM_FORMAT_S16_LE
:
284 val
= DAC_VDL_16BITS
;
286 case SNDRV_PCM_FORMAT_S20_3LE
:
287 val
= DAC_VDL_20BITS
;
289 case SNDRV_PCM_FORMAT_S24_LE
:
290 val
= DAC_VDL_24BITS
;
292 case SNDRV_PCM_FORMAT_S32_LE
:
293 val
= DAC_VDL_32BITS
;
298 regmap_update_bits(rk3328
->regmap
, DAC_INIT_CTRL2
, DAC_VDL_MASK
, val
);
300 val
= DAC_WL_32BITS
| DAC_RST_DIS
;
301 regmap_update_bits(rk3328
->regmap
, DAC_INIT_CTRL3
,
302 DAC_WL_MASK
| DAC_RST_MASK
, val
);
307 static int rk3328_pcm_startup(struct snd_pcm_substream
*substream
,
308 struct snd_soc_dai
*dai
)
310 struct rk3328_codec_priv
*rk3328
=
311 snd_soc_component_get_drvdata(dai
->component
);
313 return rk3328_codec_open_playback(rk3328
);
316 static void rk3328_pcm_shutdown(struct snd_pcm_substream
*substream
,
317 struct snd_soc_dai
*dai
)
319 struct rk3328_codec_priv
*rk3328
=
320 snd_soc_component_get_drvdata(dai
->component
);
322 rk3328_codec_close_playback(rk3328
);
325 static const struct snd_soc_dai_ops rk3328_dai_ops
= {
326 .hw_params
= rk3328_hw_params
,
327 .set_fmt
= rk3328_set_dai_fmt
,
328 .digital_mute
= rk3328_digital_mute
,
329 .startup
= rk3328_pcm_startup
,
330 .shutdown
= rk3328_pcm_shutdown
,
333 static struct snd_soc_dai_driver rk3328_dai
[] = {
335 .name
= "rk3328-hifi",
338 .stream_name
= "HIFI Playback",
341 .rates
= SNDRV_PCM_RATE_8000_96000
,
342 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
|
343 SNDRV_PCM_FMTBIT_S20_3LE
|
344 SNDRV_PCM_FMTBIT_S24_LE
|
345 SNDRV_PCM_FMTBIT_S32_LE
),
348 .stream_name
= "HIFI Capture",
351 .rates
= SNDRV_PCM_RATE_8000_96000
,
352 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
|
353 SNDRV_PCM_FMTBIT_S20_3LE
|
354 SNDRV_PCM_FMTBIT_S24_LE
|
355 SNDRV_PCM_FMTBIT_S32_LE
),
357 .ops
= &rk3328_dai_ops
,
361 static int rk3328_codec_probe(struct snd_soc_component
*component
)
363 struct rk3328_codec_priv
*rk3328
=
364 snd_soc_component_get_drvdata(component
);
366 rk3328_codec_reset(rk3328
);
367 rk3328_codec_power_on(rk3328
, 0);
372 static void rk3328_codec_remove(struct snd_soc_component
*component
)
374 struct rk3328_codec_priv
*rk3328
=
375 snd_soc_component_get_drvdata(component
);
377 rk3328_codec_close_playback(rk3328
);
378 rk3328_codec_power_off(rk3328
, 0);
381 static const struct snd_soc_component_driver soc_codec_rk3328
= {
382 .probe
= rk3328_codec_probe
,
383 .remove
= rk3328_codec_remove
,
386 static bool rk3328_codec_write_read_reg(struct device
*dev
, unsigned int reg
)
393 case DAC_PRECHARGE_CTRL
:
399 case HPOUTL_GAIN_CTRL
:
400 case HPOUTR_GAIN_CTRL
:
408 static bool rk3328_codec_volatile_reg(struct device
*dev
, unsigned int reg
)
418 static const struct regmap_config rk3328_codec_regmap_config
= {
422 .max_register
= HPOUT_POP_CTRL
,
423 .writeable_reg
= rk3328_codec_write_read_reg
,
424 .readable_reg
= rk3328_codec_write_read_reg
,
425 .volatile_reg
= rk3328_codec_volatile_reg
,
426 .reg_defaults
= rk3328_codec_reg_defaults
,
427 .num_reg_defaults
= ARRAY_SIZE(rk3328_codec_reg_defaults
),
428 .cache_type
= REGCACHE_FLAT
,
431 static int rk3328_platform_probe(struct platform_device
*pdev
)
433 struct device_node
*rk3328_np
= pdev
->dev
.of_node
;
434 struct rk3328_codec_priv
*rk3328
;
439 rk3328
= devm_kzalloc(&pdev
->dev
, sizeof(*rk3328
), GFP_KERNEL
);
443 grf
= syscon_regmap_lookup_by_phandle(rk3328_np
,
446 dev_err(&pdev
->dev
, "missing 'rockchip,grf'\n");
450 /* enable i2s_acodec_en */
451 regmap_write(grf
, RK3328_GRF_SOC_CON2
,
452 (BIT(14) << 16 | BIT(14)));
454 ret
= of_property_read_u32(rk3328_np
, "spk-depop-time-ms",
455 &rk3328
->spk_depop_time
);
457 dev_info(&pdev
->dev
, "spk_depop_time use default value.\n");
458 rk3328
->spk_depop_time
= 200;
461 rk3328_analog_output(rk3328
, 0);
463 rk3328
->mclk
= devm_clk_get(&pdev
->dev
, "mclk");
464 if (IS_ERR(rk3328
->mclk
))
465 return PTR_ERR(rk3328
->mclk
);
467 ret
= clk_prepare_enable(rk3328
->mclk
);
470 clk_set_rate(rk3328
->mclk
, INITIAL_FREQ
);
472 rk3328
->pclk
= devm_clk_get(&pdev
->dev
, "pclk");
473 if (IS_ERR(rk3328
->pclk
)) {
474 dev_err(&pdev
->dev
, "can't get acodec pclk\n");
475 return PTR_ERR(rk3328
->pclk
);
478 ret
= clk_prepare_enable(rk3328
->pclk
);
480 dev_err(&pdev
->dev
, "failed to enable acodec pclk\n");
484 base
= devm_platform_ioremap_resource(pdev
, 0);
486 return PTR_ERR(base
);
488 rk3328
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, base
,
489 &rk3328_codec_regmap_config
);
490 if (IS_ERR(rk3328
->regmap
))
491 return PTR_ERR(rk3328
->regmap
);
493 platform_set_drvdata(pdev
, rk3328
);
495 return devm_snd_soc_register_component(&pdev
->dev
, &soc_codec_rk3328
,
497 ARRAY_SIZE(rk3328_dai
));
500 static const struct of_device_id rk3328_codec_of_match
[] = {
501 { .compatible
= "rockchip,rk3328-codec", },
504 MODULE_DEVICE_TABLE(of
, rk3328_codec_of_match
);
506 static struct platform_driver rk3328_codec_driver
= {
508 .name
= "rk3328-codec",
509 .of_match_table
= of_match_ptr(rk3328_codec_of_match
),
511 .probe
= rk3328_platform_probe
,
513 module_platform_driver(rk3328_codec_driver
);
515 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
516 MODULE_DESCRIPTION("ASoC rk3328 codec driver");
517 MODULE_LICENSE("GPL v2");