2 * rk3328_codec.c -- rk3328 ALSA Soc Audio driver
4 * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/module.h>
21 #include <linux/device.h>
22 #include <linux/delay.h>
24 #include <linux/clk.h>
25 #include <linux/mfd/syscon.h>
26 #include <linux/platform_device.h>
27 #include <linux/pm_runtime.h>
28 #include <linux/regmap.h>
29 #include <sound/pcm_params.h>
30 #include <sound/dmaengine_pcm.h>
31 #include "rk3328_codec.h"
40 #define OUT_VOLUME (0x18)
41 #define RK3328_GRF_SOC_CON2 (0x0408)
42 #define RK3328_GRF_SOC_CON10 (0x0428)
44 struct rk3328_codec_priv {
45 struct regmap *regmap;
49 int spk_depop_time; /* msec */
52 static const struct reg_default rk3328_codec_reg_defaults[] = {
53 { CODEC_RESET, 0x03 },
54 { DAC_INIT_CTRL1, 0x00 },
55 { DAC_INIT_CTRL2, 0x50 },
56 { DAC_INIT_CTRL3, 0x0e },
57 { DAC_PRECHARGE_CTRL, 0x01 },
58 { DAC_PWR_CTRL, 0x00 },
59 { DAC_CLK_CTRL, 0x00 },
62 { HPOUTL_GAIN_CTRL, 0x00 },
63 { HPOUTR_GAIN_CTRL, 0x00 },
64 { HPOUT_POP_CTRL, 0x11 },
67 static int rk3328_codec_reset(struct snd_soc_codec *codec)
69 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
71 regmap_write(rk3328->regmap, CODEC_RESET, 0);
73 regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
78 static int rk3328_set_dai_fmt(struct snd_soc_dai *codec_dai,
81 struct snd_soc_codec *codec = codec_dai->codec;
82 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
85 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
86 case SND_SOC_DAIFMT_CBS_CFS:
87 val |= PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
89 case SND_SOC_DAIFMT_CBM_CFM:
90 val |= PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
96 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
97 PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
100 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
101 case SND_SOC_DAIFMT_DSP_A:
102 case SND_SOC_DAIFMT_DSP_B:
105 case SND_SOC_DAIFMT_I2S:
108 case SND_SOC_DAIFMT_RIGHT_J:
111 case SND_SOC_DAIFMT_LEFT_J:
118 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
123 static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
125 regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10,
126 (BIT(1) << 16) | (mute << 1));
129 static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
131 struct snd_soc_codec *codec = dai->codec;
132 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
133 unsigned int val = 0;
136 val = HPOUTL_MUTE | HPOUTR_MUTE;
138 val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
140 regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
141 HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
145 static int rk3328_codec_power_on(struct snd_soc_codec *codec, int wait_ms)
147 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
149 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
150 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
152 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
153 DAC_CHARGE_CURRENT_ALL_MASK,
154 DAC_CHARGE_CURRENT_ALL_ON);
161 static int rk3328_codec_power_off(struct snd_soc_codec *codec, int wait_ms)
163 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
165 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
166 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
168 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
169 DAC_CHARGE_CURRENT_ALL_MASK,
170 DAC_CHARGE_CURRENT_ALL_ON);
177 static struct rk3328_reg_msk_val playback_open_list[] = {
178 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
179 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
180 DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
181 { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON,
182 HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
183 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
184 HPOUTR_POP_WORK | HPOUTL_POP_WORK },
185 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
186 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
187 HPMIXL_INIT_EN | HPMIXR_INIT_EN },
188 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
189 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
190 HPOUTL_INIT_EN | HPOUTR_INIT_EN },
191 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
192 DACL_REFV_ON | DACR_REFV_ON },
193 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
194 DACL_CLK_ON | DACR_CLK_ON },
195 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
196 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
197 DACL_INIT_ON | DACR_INIT_ON },
198 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
199 DACL_SELECT | DACR_SELECT },
200 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
201 HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
202 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
203 HPOUTL_UNMUTE | HPOUTR_UNMUTE },
206 #define PLAYBACK_OPEN_LIST_LEN ARRAY_SIZE(playback_open_list)
208 static int rk3328_codec_open_playback(struct snd_soc_codec *codec)
210 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
213 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
214 DAC_CHARGE_CURRENT_ALL_MASK,
215 DAC_CHARGE_CURRENT_I);
217 for (i = 0; i < PLAYBACK_OPEN_LIST_LEN; i++) {
218 regmap_update_bits(rk3328->regmap,
219 playback_open_list[i].reg,
220 playback_open_list[i].msk,
221 playback_open_list[i].val);
225 msleep(rk3328->spk_depop_time);
226 rk3328_analog_output(rk3328, 1);
228 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
229 HPOUTL_GAIN_MASK, OUT_VOLUME);
230 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
231 HPOUTR_GAIN_MASK, OUT_VOLUME);
235 static struct rk3328_reg_msk_val playback_close_list[] = {
236 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
237 HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
238 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
239 DACL_UNSELECT | DACR_UNSELECT },
240 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
241 HPOUTL_MUTE | HPOUTR_MUTE },
242 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
243 HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
244 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
245 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
246 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
247 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
248 DACL_CLK_OFF | DACR_CLK_OFF },
249 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
250 DACL_REFV_OFF | DACR_REFV_OFF },
251 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
252 HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
253 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
254 DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
255 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
256 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
257 HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
258 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
259 DACL_INIT_OFF | DACR_INIT_OFF },
262 #define PLAYBACK_CLOSE_LIST_LEN ARRAY_SIZE(playback_close_list)
264 static int rk3328_codec_close_playback(struct snd_soc_codec *codec)
266 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
269 rk3328_analog_output(rk3328, 0);
271 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
272 HPOUTL_GAIN_MASK, 0);
273 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
274 HPOUTR_GAIN_MASK, 0);
276 for (i = 0; i < PLAYBACK_CLOSE_LIST_LEN; i++) {
277 regmap_update_bits(rk3328->regmap,
278 playback_close_list[i].reg,
279 playback_close_list[i].msk,
280 playback_close_list[i].val);
284 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
285 DAC_CHARGE_CURRENT_ALL_MASK,
286 DAC_CHARGE_CURRENT_I);
290 static int rk3328_hw_params(struct snd_pcm_substream *substream,
291 struct snd_pcm_hw_params *params,
292 struct snd_soc_dai *dai)
294 struct snd_soc_codec *codec = dai->codec;
295 struct rk3328_codec_priv *rk3328 = snd_soc_codec_get_drvdata(codec);
296 unsigned int val = 0;
298 switch (params_format(params)) {
299 case SNDRV_PCM_FORMAT_S16_LE:
300 val |= DAC_VDL_16BITS;
302 case SNDRV_PCM_FORMAT_S20_3LE:
303 val |= DAC_VDL_20BITS;
305 case SNDRV_PCM_FORMAT_S24_LE:
306 val |= DAC_VDL_24BITS;
308 case SNDRV_PCM_FORMAT_S32_LE:
309 val |= DAC_VDL_32BITS;
315 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
316 val = DAC_WL_32BITS | DAC_RST_DIS;
317 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
318 DAC_WL_MASK | DAC_RST_MASK, val);
323 static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
324 struct snd_soc_dai *dai)
326 struct snd_soc_codec *codec = dai->codec;
328 return rk3328_codec_open_playback(codec);
331 static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
332 struct snd_soc_dai *dai)
334 struct snd_soc_codec *codec = dai->codec;
336 rk3328_codec_close_playback(codec);
339 static struct snd_soc_dai_ops rk3328_dai_ops = {
340 .hw_params = rk3328_hw_params,
341 .set_fmt = rk3328_set_dai_fmt,
342 .digital_mute = rk3328_digital_mute,
343 .startup = rk3328_pcm_startup,
344 .shutdown = rk3328_pcm_shutdown,
347 static struct snd_soc_dai_driver rk3328_dai[] = {
349 .name = "rk3328-hifi",
352 .stream_name = "HIFI Playback",
355 .rates = SNDRV_PCM_RATE_8000_96000,
356 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
357 SNDRV_PCM_FMTBIT_S20_3LE |
358 SNDRV_PCM_FMTBIT_S24_LE |
359 SNDRV_PCM_FMTBIT_S32_LE),
361 .ops = &rk3328_dai_ops,
365 static int rk3328_codec_probe(struct snd_soc_codec *codec)
367 rk3328_codec_reset(codec);
368 rk3328_codec_power_on(codec, 0);
373 static int rk3328_codec_remove(struct snd_soc_codec *codec)
375 rk3328_codec_close_playback(codec);
376 rk3328_codec_power_off(codec, 0);
381 static struct snd_soc_codec_driver soc_codec_dev_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,
432 static const struct of_device_id rk3328codec_of_match[] = {
433 { .compatible = "rockchip,rk3328-codec", },
436 MODULE_DEVICE_TABLE(of, rk3328codec_of_match);
439 static int rk3328_platform_probe(struct platform_device *pdev)
441 struct device_node *rk3328_np = pdev->dev.of_node;
442 struct rk3328_codec_priv *rk3328;
443 struct resource *res;
448 rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
452 grf = syscon_regmap_lookup_by_phandle(rk3328_np,
455 dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
459 /* enable i2s_acodec_en */
460 regmap_write(grf, RK3328_GRF_SOC_CON2,
461 (BIT(14) << 16 | BIT(14)));
463 ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
464 &rk3328->spk_depop_time);
466 dev_info(&pdev->dev, "spk_depop_time use default value.\n");
467 rk3328->spk_depop_time = 200;
470 rk3328_analog_output(rk3328, 0);
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 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
485 base = devm_ioremap_resource(&pdev->dev, res);
487 return PTR_ERR(base);
489 rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
490 &rk3328_codec_regmap_config);
491 if (IS_ERR(rk3328->regmap))
492 return PTR_ERR(rk3328->regmap);
494 platform_set_drvdata(pdev, rk3328);
496 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3328,
497 rk3328_dai, ARRAY_SIZE(rk3328_dai));
500 static int rk3328_platform_remove(struct platform_device *pdev)
502 snd_soc_unregister_codec(&pdev->dev);
506 static struct platform_driver rk3328_codec_driver = {
508 .name = "rk3328-codec",
509 .owner = THIS_MODULE,
510 .of_match_table = of_match_ptr(rk3328codec_of_match),
512 .probe = rk3328_platform_probe,
513 .remove = rk3328_platform_remove,
515 module_platform_driver(rk3328_codec_driver);
517 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
518 MODULE_DESCRIPTION("ASoC rk3328 codec driver");
519 MODULE_LICENSE("GPL v2");