xref: /linux/sound/soc/codecs/rk3328_codec.c (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
1c3275903SKatsuhiro Suzuki // SPDX-License-Identifier: GPL-2.0
2c3275903SKatsuhiro Suzuki //
3c3275903SKatsuhiro Suzuki // rk3328 ALSA SoC Audio driver
4c3275903SKatsuhiro Suzuki //
5c3275903SKatsuhiro Suzuki // Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
6c3275903SKatsuhiro Suzuki 
7c3275903SKatsuhiro Suzuki #include <linux/clk.h>
8c3275903SKatsuhiro Suzuki #include <linux/delay.h>
9c3275903SKatsuhiro Suzuki #include <linux/device.h>
1087d12d55SRobin Murphy #include <linux/gpio/consumer.h>
11c3275903SKatsuhiro Suzuki #include <linux/module.h>
12c3275903SKatsuhiro Suzuki #include <linux/of.h>
13c3275903SKatsuhiro Suzuki #include <linux/platform_device.h>
14c3275903SKatsuhiro Suzuki #include <linux/regmap.h>
15c3275903SKatsuhiro Suzuki #include <linux/mfd/syscon.h>
16c3275903SKatsuhiro Suzuki #include <sound/dmaengine_pcm.h>
17c3275903SKatsuhiro Suzuki #include <sound/pcm_params.h>
18c3275903SKatsuhiro Suzuki #include "rk3328_codec.h"
19c3275903SKatsuhiro Suzuki 
20c3275903SKatsuhiro Suzuki /*
21c3275903SKatsuhiro Suzuki  * volume setting
22c3275903SKatsuhiro Suzuki  * 0: -39dB
23c3275903SKatsuhiro Suzuki  * 26: 0dB
24c3275903SKatsuhiro Suzuki  * 31: 6dB
25c3275903SKatsuhiro Suzuki  * Step: 1.5dB
26c3275903SKatsuhiro Suzuki  */
27c3275903SKatsuhiro Suzuki #define OUT_VOLUME	(0x18)
28c3275903SKatsuhiro Suzuki #define RK3328_GRF_SOC_CON2	(0x0408)
29c3275903SKatsuhiro Suzuki #define RK3328_GRF_SOC_CON10	(0x0428)
30c3275903SKatsuhiro Suzuki #define INITIAL_FREQ	(11289600)
31c3275903SKatsuhiro Suzuki 
32c3275903SKatsuhiro Suzuki struct rk3328_codec_priv {
33c3275903SKatsuhiro Suzuki 	struct regmap *regmap;
3487d12d55SRobin Murphy 	struct gpio_desc *mute;
35c3275903SKatsuhiro Suzuki 	struct clk *mclk;
36c3275903SKatsuhiro Suzuki 	struct clk *pclk;
37c3275903SKatsuhiro Suzuki 	unsigned int sclk;
38c3275903SKatsuhiro Suzuki 	int spk_depop_time; /* msec */
39c3275903SKatsuhiro Suzuki };
40c3275903SKatsuhiro Suzuki 
41c3275903SKatsuhiro Suzuki static const struct reg_default rk3328_codec_reg_defaults[] = {
42c3275903SKatsuhiro Suzuki 	{ CODEC_RESET, 0x03 },
43c3275903SKatsuhiro Suzuki 	{ DAC_INIT_CTRL1, 0x00 },
44c3275903SKatsuhiro Suzuki 	{ DAC_INIT_CTRL2, 0x50 },
45c3275903SKatsuhiro Suzuki 	{ DAC_INIT_CTRL3, 0x0e },
46c3275903SKatsuhiro Suzuki 	{ DAC_PRECHARGE_CTRL, 0x01 },
47c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, 0x00 },
48c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, 0x00 },
49c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, 0x00 },
50c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, 0x00 },
51c3275903SKatsuhiro Suzuki 	{ HPOUTL_GAIN_CTRL, 0x00 },
52c3275903SKatsuhiro Suzuki 	{ HPOUTR_GAIN_CTRL, 0x00 },
53c3275903SKatsuhiro Suzuki 	{ HPOUT_POP_CTRL, 0x11 },
54c3275903SKatsuhiro Suzuki };
55c3275903SKatsuhiro Suzuki 
rk3328_codec_reset(struct rk3328_codec_priv * rk3328)56c3275903SKatsuhiro Suzuki static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
57c3275903SKatsuhiro Suzuki {
58c3275903SKatsuhiro Suzuki 	regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
59c3275903SKatsuhiro Suzuki 	mdelay(10);
60c3275903SKatsuhiro Suzuki 	regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
61c3275903SKatsuhiro Suzuki 
62c3275903SKatsuhiro Suzuki 	return 0;
63c3275903SKatsuhiro Suzuki }
64c3275903SKatsuhiro Suzuki 
rk3328_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)65c3275903SKatsuhiro Suzuki static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
66c3275903SKatsuhiro Suzuki {
67c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
68c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(dai->component);
69c3275903SKatsuhiro Suzuki 	unsigned int val;
70c3275903SKatsuhiro Suzuki 
71*cd0df170SMark Brown 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
72*cd0df170SMark Brown 	case SND_SOC_DAIFMT_CBC_CFC:
73c3275903SKatsuhiro Suzuki 		val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
74c3275903SKatsuhiro Suzuki 		break;
75*cd0df170SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
76c3275903SKatsuhiro Suzuki 		val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
77c3275903SKatsuhiro Suzuki 		break;
78c3275903SKatsuhiro Suzuki 	default:
79c3275903SKatsuhiro Suzuki 		return -EINVAL;
80c3275903SKatsuhiro Suzuki 	}
81c3275903SKatsuhiro Suzuki 
82c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
83c3275903SKatsuhiro Suzuki 			   PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
84c3275903SKatsuhiro Suzuki 
85c3275903SKatsuhiro Suzuki 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
86c3275903SKatsuhiro Suzuki 	case SND_SOC_DAIFMT_DSP_A:
87c3275903SKatsuhiro Suzuki 	case SND_SOC_DAIFMT_DSP_B:
88c3275903SKatsuhiro Suzuki 		val = DAC_MODE_PCM;
89c3275903SKatsuhiro Suzuki 		break;
90c3275903SKatsuhiro Suzuki 	case SND_SOC_DAIFMT_I2S:
91c3275903SKatsuhiro Suzuki 		val = DAC_MODE_I2S;
92c3275903SKatsuhiro Suzuki 		break;
93c3275903SKatsuhiro Suzuki 	case SND_SOC_DAIFMT_RIGHT_J:
94c3275903SKatsuhiro Suzuki 		val = DAC_MODE_RJM;
95c3275903SKatsuhiro Suzuki 		break;
96c3275903SKatsuhiro Suzuki 	case SND_SOC_DAIFMT_LEFT_J:
97c3275903SKatsuhiro Suzuki 		val = DAC_MODE_LJM;
98c3275903SKatsuhiro Suzuki 		break;
99c3275903SKatsuhiro Suzuki 	default:
100c3275903SKatsuhiro Suzuki 		return -EINVAL;
101c3275903SKatsuhiro Suzuki 	}
102c3275903SKatsuhiro Suzuki 
103c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
104c3275903SKatsuhiro Suzuki 			   DAC_MODE_MASK, val);
105c3275903SKatsuhiro Suzuki 
106c3275903SKatsuhiro Suzuki 	return 0;
107c3275903SKatsuhiro Suzuki }
108c3275903SKatsuhiro Suzuki 
rk3328_mute_stream(struct snd_soc_dai * dai,int mute,int direction)10954b59270SKuninori Morimoto static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
110c3275903SKatsuhiro Suzuki {
111c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
112c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(dai->component);
113c3275903SKatsuhiro Suzuki 	unsigned int val;
114c3275903SKatsuhiro Suzuki 
115c3275903SKatsuhiro Suzuki 	if (mute)
116c3275903SKatsuhiro Suzuki 		val = HPOUTL_MUTE | HPOUTR_MUTE;
117c3275903SKatsuhiro Suzuki 	else
118c3275903SKatsuhiro Suzuki 		val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
119c3275903SKatsuhiro Suzuki 
120c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
121c3275903SKatsuhiro Suzuki 			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
122c3275903SKatsuhiro Suzuki 
123c3275903SKatsuhiro Suzuki 	return 0;
124c3275903SKatsuhiro Suzuki }
125c3275903SKatsuhiro Suzuki 
rk3328_codec_power_on(struct rk3328_codec_priv * rk3328,int wait_ms)126c3275903SKatsuhiro Suzuki static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
127c3275903SKatsuhiro Suzuki {
128c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
129c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
130c3275903SKatsuhiro Suzuki 	mdelay(10);
131c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
132c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_MASK,
133c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_ON);
134c3275903SKatsuhiro Suzuki 	mdelay(wait_ms);
135c3275903SKatsuhiro Suzuki 
136c3275903SKatsuhiro Suzuki 	return 0;
137c3275903SKatsuhiro Suzuki }
138c3275903SKatsuhiro Suzuki 
rk3328_codec_power_off(struct rk3328_codec_priv * rk3328,int wait_ms)139c3275903SKatsuhiro Suzuki static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
140c3275903SKatsuhiro Suzuki {
141c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
142c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
143c3275903SKatsuhiro Suzuki 	mdelay(10);
144c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
145c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_MASK,
146c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_ON);
147c3275903SKatsuhiro Suzuki 	mdelay(wait_ms);
148c3275903SKatsuhiro Suzuki 
149c3275903SKatsuhiro Suzuki 	return 0;
150c3275903SKatsuhiro Suzuki }
151c3275903SKatsuhiro Suzuki 
152c3275903SKatsuhiro Suzuki static const struct rk3328_reg_msk_val playback_open_list[] = {
153c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
154c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
155c3275903SKatsuhiro Suzuki 	  DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
156c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
157c3275903SKatsuhiro Suzuki 	  HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
158c3275903SKatsuhiro Suzuki 	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
159c3275903SKatsuhiro Suzuki 	  HPOUTR_POP_WORK | HPOUTL_POP_WORK },
160c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
161c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
162c3275903SKatsuhiro Suzuki 	  HPMIXL_INIT_EN | HPMIXR_INIT_EN },
163c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
164c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
165c3275903SKatsuhiro Suzuki 	  HPOUTL_INIT_EN | HPOUTR_INIT_EN },
166c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
167c3275903SKatsuhiro Suzuki 	  DACL_REFV_ON | DACR_REFV_ON },
168c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
169c3275903SKatsuhiro Suzuki 	  DACL_CLK_ON | DACR_CLK_ON },
170c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
171c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
172c3275903SKatsuhiro Suzuki 	  DACL_INIT_ON | DACR_INIT_ON },
173c3275903SKatsuhiro Suzuki 	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
174c3275903SKatsuhiro Suzuki 	  DACL_SELECT | DACR_SELECT },
175c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
176c3275903SKatsuhiro Suzuki 	  HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
177c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
178c3275903SKatsuhiro Suzuki 	  HPOUTL_UNMUTE | HPOUTR_UNMUTE },
179c3275903SKatsuhiro Suzuki };
180c3275903SKatsuhiro Suzuki 
rk3328_codec_open_playback(struct rk3328_codec_priv * rk3328)181c3275903SKatsuhiro Suzuki static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
182c3275903SKatsuhiro Suzuki {
183c3275903SKatsuhiro Suzuki 	int i;
184c3275903SKatsuhiro Suzuki 
185c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
186c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_MASK,
187c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_I);
188c3275903SKatsuhiro Suzuki 
189c3275903SKatsuhiro Suzuki 	for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
190c3275903SKatsuhiro Suzuki 		regmap_update_bits(rk3328->regmap,
191c3275903SKatsuhiro Suzuki 				   playback_open_list[i].reg,
192c3275903SKatsuhiro Suzuki 				   playback_open_list[i].msk,
193c3275903SKatsuhiro Suzuki 				   playback_open_list[i].val);
194c3275903SKatsuhiro Suzuki 		mdelay(1);
195c3275903SKatsuhiro Suzuki 	}
196c3275903SKatsuhiro Suzuki 
197c3275903SKatsuhiro Suzuki 	msleep(rk3328->spk_depop_time);
19887d12d55SRobin Murphy 	gpiod_set_value(rk3328->mute, 0);
199c3275903SKatsuhiro Suzuki 
200c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
201c3275903SKatsuhiro Suzuki 			   HPOUTL_GAIN_MASK, OUT_VOLUME);
202c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
203c3275903SKatsuhiro Suzuki 			   HPOUTR_GAIN_MASK, OUT_VOLUME);
204c3275903SKatsuhiro Suzuki 
205c3275903SKatsuhiro Suzuki 	return 0;
206c3275903SKatsuhiro Suzuki }
207c3275903SKatsuhiro Suzuki 
208c3275903SKatsuhiro Suzuki static const struct rk3328_reg_msk_val playback_close_list[] = {
209c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
210c3275903SKatsuhiro Suzuki 	  HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
211c3275903SKatsuhiro Suzuki 	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
212c3275903SKatsuhiro Suzuki 	  DACL_UNSELECT | DACR_UNSELECT },
213c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
214c3275903SKatsuhiro Suzuki 	  HPOUTL_MUTE | HPOUTR_MUTE },
215c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
216c3275903SKatsuhiro Suzuki 	  HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
217c3275903SKatsuhiro Suzuki 	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
218c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
219c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
220c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
221c3275903SKatsuhiro Suzuki 	  DACL_CLK_OFF | DACR_CLK_OFF },
222c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
223c3275903SKatsuhiro Suzuki 	  DACL_REFV_OFF | DACR_REFV_OFF },
224c3275903SKatsuhiro Suzuki 	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
225c3275903SKatsuhiro Suzuki 	  HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
226c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
227c3275903SKatsuhiro Suzuki 	  DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
228c3275903SKatsuhiro Suzuki 	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
229c3275903SKatsuhiro Suzuki 	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
230c3275903SKatsuhiro Suzuki 	  HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
231c3275903SKatsuhiro Suzuki 	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
232c3275903SKatsuhiro Suzuki 	  DACL_INIT_OFF | DACR_INIT_OFF },
233c3275903SKatsuhiro Suzuki };
234c3275903SKatsuhiro Suzuki 
rk3328_codec_close_playback(struct rk3328_codec_priv * rk3328)235c3275903SKatsuhiro Suzuki static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
236c3275903SKatsuhiro Suzuki {
237c3275903SKatsuhiro Suzuki 	size_t i;
238c3275903SKatsuhiro Suzuki 
23987d12d55SRobin Murphy 	gpiod_set_value(rk3328->mute, 1);
240c3275903SKatsuhiro Suzuki 
241c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
242c3275903SKatsuhiro Suzuki 			   HPOUTL_GAIN_MASK, 0);
243c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
244c3275903SKatsuhiro Suzuki 			   HPOUTR_GAIN_MASK, 0);
245c3275903SKatsuhiro Suzuki 
246c3275903SKatsuhiro Suzuki 	for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
247c3275903SKatsuhiro Suzuki 		regmap_update_bits(rk3328->regmap,
248c3275903SKatsuhiro Suzuki 				   playback_close_list[i].reg,
249c3275903SKatsuhiro Suzuki 				   playback_close_list[i].msk,
250c3275903SKatsuhiro Suzuki 				   playback_close_list[i].val);
251c3275903SKatsuhiro Suzuki 		mdelay(1);
252c3275903SKatsuhiro Suzuki 	}
253c3275903SKatsuhiro Suzuki 
254f5758544SKatsuhiro Suzuki 	/* Workaround for silence when changed Fs 48 -> 44.1kHz */
255f5758544SKatsuhiro Suzuki 	rk3328_codec_reset(rk3328);
256f5758544SKatsuhiro Suzuki 
257c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
258c3275903SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_MASK,
259f5758544SKatsuhiro Suzuki 			   DAC_CHARGE_CURRENT_ALL_ON);
260c3275903SKatsuhiro Suzuki 
261c3275903SKatsuhiro Suzuki 	return 0;
262c3275903SKatsuhiro Suzuki }
263c3275903SKatsuhiro Suzuki 
rk3328_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)264c3275903SKatsuhiro Suzuki static int rk3328_hw_params(struct snd_pcm_substream *substream,
265c3275903SKatsuhiro Suzuki 			    struct snd_pcm_hw_params *params,
266c3275903SKatsuhiro Suzuki 			    struct snd_soc_dai *dai)
267c3275903SKatsuhiro Suzuki {
268c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
269c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(dai->component);
270c3275903SKatsuhiro Suzuki 	unsigned int val = 0;
271c3275903SKatsuhiro Suzuki 
272c3275903SKatsuhiro Suzuki 	switch (params_format(params)) {
273c3275903SKatsuhiro Suzuki 	case SNDRV_PCM_FORMAT_S16_LE:
274c3275903SKatsuhiro Suzuki 		val = DAC_VDL_16BITS;
275c3275903SKatsuhiro Suzuki 		break;
276c3275903SKatsuhiro Suzuki 	case SNDRV_PCM_FORMAT_S20_3LE:
277c3275903SKatsuhiro Suzuki 		val = DAC_VDL_20BITS;
278c3275903SKatsuhiro Suzuki 		break;
279c3275903SKatsuhiro Suzuki 	case SNDRV_PCM_FORMAT_S24_LE:
280c3275903SKatsuhiro Suzuki 		val = DAC_VDL_24BITS;
281c3275903SKatsuhiro Suzuki 		break;
282c3275903SKatsuhiro Suzuki 	case SNDRV_PCM_FORMAT_S32_LE:
283c3275903SKatsuhiro Suzuki 		val = DAC_VDL_32BITS;
284c3275903SKatsuhiro Suzuki 		break;
285c3275903SKatsuhiro Suzuki 	default:
286c3275903SKatsuhiro Suzuki 		return -EINVAL;
287c3275903SKatsuhiro Suzuki 	}
288c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
289c3275903SKatsuhiro Suzuki 
290c3275903SKatsuhiro Suzuki 	val = DAC_WL_32BITS | DAC_RST_DIS;
291c3275903SKatsuhiro Suzuki 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
292c3275903SKatsuhiro Suzuki 			   DAC_WL_MASK | DAC_RST_MASK, val);
293c3275903SKatsuhiro Suzuki 
294c3275903SKatsuhiro Suzuki 	return 0;
295c3275903SKatsuhiro Suzuki }
296c3275903SKatsuhiro Suzuki 
rk3328_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)297c3275903SKatsuhiro Suzuki static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
298c3275903SKatsuhiro Suzuki 			      struct snd_soc_dai *dai)
299c3275903SKatsuhiro Suzuki {
300c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
301c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(dai->component);
302c3275903SKatsuhiro Suzuki 
303c3275903SKatsuhiro Suzuki 	return rk3328_codec_open_playback(rk3328);
304c3275903SKatsuhiro Suzuki }
305c3275903SKatsuhiro Suzuki 
rk3328_pcm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)306c3275903SKatsuhiro Suzuki static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
307c3275903SKatsuhiro Suzuki 				struct snd_soc_dai *dai)
308c3275903SKatsuhiro Suzuki {
309c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
310c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(dai->component);
311c3275903SKatsuhiro Suzuki 
312c3275903SKatsuhiro Suzuki 	rk3328_codec_close_playback(rk3328);
313c3275903SKatsuhiro Suzuki }
314c3275903SKatsuhiro Suzuki 
315c3275903SKatsuhiro Suzuki static const struct snd_soc_dai_ops rk3328_dai_ops = {
316c3275903SKatsuhiro Suzuki 	.hw_params = rk3328_hw_params,
317c3275903SKatsuhiro Suzuki 	.set_fmt = rk3328_set_dai_fmt,
31854b59270SKuninori Morimoto 	.mute_stream = rk3328_mute_stream,
319c3275903SKatsuhiro Suzuki 	.startup = rk3328_pcm_startup,
320c3275903SKatsuhiro Suzuki 	.shutdown = rk3328_pcm_shutdown,
32154b59270SKuninori Morimoto 	.no_capture_mute = 1,
322c3275903SKatsuhiro Suzuki };
323c3275903SKatsuhiro Suzuki 
324c3275903SKatsuhiro Suzuki static struct snd_soc_dai_driver rk3328_dai[] = {
325c3275903SKatsuhiro Suzuki 	{
326c3275903SKatsuhiro Suzuki 		.name = "rk3328-hifi",
327c3275903SKatsuhiro Suzuki 		.id = RK3328_HIFI,
328c3275903SKatsuhiro Suzuki 		.playback = {
329c3275903SKatsuhiro Suzuki 			.stream_name = "HIFI Playback",
330c3275903SKatsuhiro Suzuki 			.channels_min = 1,
331c3275903SKatsuhiro Suzuki 			.channels_max = 2,
332c3275903SKatsuhiro Suzuki 			.rates = SNDRV_PCM_RATE_8000_96000,
333c3275903SKatsuhiro Suzuki 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
334c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S20_3LE |
335c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S24_LE |
336c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S32_LE),
337c3275903SKatsuhiro Suzuki 		},
338c3275903SKatsuhiro Suzuki 		.capture = {
339c3275903SKatsuhiro Suzuki 			.stream_name = "HIFI Capture",
340c3275903SKatsuhiro Suzuki 			.channels_min = 2,
341c3275903SKatsuhiro Suzuki 			.channels_max = 8,
342c3275903SKatsuhiro Suzuki 			.rates = SNDRV_PCM_RATE_8000_96000,
343c3275903SKatsuhiro Suzuki 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
344c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S20_3LE |
345c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S24_LE |
346c3275903SKatsuhiro Suzuki 				    SNDRV_PCM_FMTBIT_S32_LE),
347c3275903SKatsuhiro Suzuki 		},
348c3275903SKatsuhiro Suzuki 		.ops = &rk3328_dai_ops,
349c3275903SKatsuhiro Suzuki 	},
350c3275903SKatsuhiro Suzuki };
351c3275903SKatsuhiro Suzuki 
rk3328_codec_probe(struct snd_soc_component * component)352c3275903SKatsuhiro Suzuki static int rk3328_codec_probe(struct snd_soc_component *component)
353c3275903SKatsuhiro Suzuki {
354c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
355c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(component);
356c3275903SKatsuhiro Suzuki 
357c3275903SKatsuhiro Suzuki 	rk3328_codec_reset(rk3328);
358c3275903SKatsuhiro Suzuki 	rk3328_codec_power_on(rk3328, 0);
359c3275903SKatsuhiro Suzuki 
360c3275903SKatsuhiro Suzuki 	return 0;
361c3275903SKatsuhiro Suzuki }
362c3275903SKatsuhiro Suzuki 
rk3328_codec_remove(struct snd_soc_component * component)363c3275903SKatsuhiro Suzuki static void rk3328_codec_remove(struct snd_soc_component *component)
364c3275903SKatsuhiro Suzuki {
365c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328 =
366c3275903SKatsuhiro Suzuki 		snd_soc_component_get_drvdata(component);
367c3275903SKatsuhiro Suzuki 
368c3275903SKatsuhiro Suzuki 	rk3328_codec_close_playback(rk3328);
369c3275903SKatsuhiro Suzuki 	rk3328_codec_power_off(rk3328, 0);
370c3275903SKatsuhiro Suzuki }
371c3275903SKatsuhiro Suzuki 
372c3275903SKatsuhiro Suzuki static const struct snd_soc_component_driver soc_codec_rk3328 = {
373c3275903SKatsuhiro Suzuki 	.probe = rk3328_codec_probe,
374c3275903SKatsuhiro Suzuki 	.remove = rk3328_codec_remove,
375c3275903SKatsuhiro Suzuki };
376c3275903SKatsuhiro Suzuki 
rk3328_codec_write_read_reg(struct device * dev,unsigned int reg)377c3275903SKatsuhiro Suzuki static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
378c3275903SKatsuhiro Suzuki {
379c3275903SKatsuhiro Suzuki 	switch (reg) {
380c3275903SKatsuhiro Suzuki 	case CODEC_RESET:
381c3275903SKatsuhiro Suzuki 	case DAC_INIT_CTRL1:
382c3275903SKatsuhiro Suzuki 	case DAC_INIT_CTRL2:
383c3275903SKatsuhiro Suzuki 	case DAC_INIT_CTRL3:
384c3275903SKatsuhiro Suzuki 	case DAC_PRECHARGE_CTRL:
385c3275903SKatsuhiro Suzuki 	case DAC_PWR_CTRL:
386c3275903SKatsuhiro Suzuki 	case DAC_CLK_CTRL:
387c3275903SKatsuhiro Suzuki 	case HPMIX_CTRL:
388c3275903SKatsuhiro Suzuki 	case DAC_SELECT:
389c3275903SKatsuhiro Suzuki 	case HPOUT_CTRL:
390c3275903SKatsuhiro Suzuki 	case HPOUTL_GAIN_CTRL:
391c3275903SKatsuhiro Suzuki 	case HPOUTR_GAIN_CTRL:
392c3275903SKatsuhiro Suzuki 	case HPOUT_POP_CTRL:
393c3275903SKatsuhiro Suzuki 		return true;
394c3275903SKatsuhiro Suzuki 	default:
395c3275903SKatsuhiro Suzuki 		return false;
396c3275903SKatsuhiro Suzuki 	}
397c3275903SKatsuhiro Suzuki }
398c3275903SKatsuhiro Suzuki 
rk3328_codec_volatile_reg(struct device * dev,unsigned int reg)399c3275903SKatsuhiro Suzuki static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
400c3275903SKatsuhiro Suzuki {
401c3275903SKatsuhiro Suzuki 	switch (reg) {
402c3275903SKatsuhiro Suzuki 	case CODEC_RESET:
403c3275903SKatsuhiro Suzuki 		return true;
404c3275903SKatsuhiro Suzuki 	default:
405c3275903SKatsuhiro Suzuki 		return false;
406c3275903SKatsuhiro Suzuki 	}
407c3275903SKatsuhiro Suzuki }
408c3275903SKatsuhiro Suzuki 
409c3275903SKatsuhiro Suzuki static const struct regmap_config rk3328_codec_regmap_config = {
410c3275903SKatsuhiro Suzuki 	.reg_bits = 32,
411c3275903SKatsuhiro Suzuki 	.reg_stride = 4,
412c3275903SKatsuhiro Suzuki 	.val_bits = 32,
413c3275903SKatsuhiro Suzuki 	.max_register = HPOUT_POP_CTRL,
414c3275903SKatsuhiro Suzuki 	.writeable_reg = rk3328_codec_write_read_reg,
415c3275903SKatsuhiro Suzuki 	.readable_reg = rk3328_codec_write_read_reg,
416c3275903SKatsuhiro Suzuki 	.volatile_reg = rk3328_codec_volatile_reg,
417c3275903SKatsuhiro Suzuki 	.reg_defaults = rk3328_codec_reg_defaults,
418c3275903SKatsuhiro Suzuki 	.num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
419c3275903SKatsuhiro Suzuki 	.cache_type = REGCACHE_FLAT,
420c3275903SKatsuhiro Suzuki };
421c3275903SKatsuhiro Suzuki 
rk3328_platform_probe(struct platform_device * pdev)422c3275903SKatsuhiro Suzuki static int rk3328_platform_probe(struct platform_device *pdev)
423c3275903SKatsuhiro Suzuki {
424c3275903SKatsuhiro Suzuki 	struct device_node *rk3328_np = pdev->dev.of_node;
425c3275903SKatsuhiro Suzuki 	struct rk3328_codec_priv *rk3328;
426c3275903SKatsuhiro Suzuki 	struct regmap *grf;
427c3275903SKatsuhiro Suzuki 	void __iomem *base;
428c3275903SKatsuhiro Suzuki 	int ret = 0;
429c3275903SKatsuhiro Suzuki 
430c3275903SKatsuhiro Suzuki 	rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
431c3275903SKatsuhiro Suzuki 	if (!rk3328)
432c3275903SKatsuhiro Suzuki 		return -ENOMEM;
433c3275903SKatsuhiro Suzuki 
434c3275903SKatsuhiro Suzuki 	grf = syscon_regmap_lookup_by_phandle(rk3328_np,
435c3275903SKatsuhiro Suzuki 					      "rockchip,grf");
436c3275903SKatsuhiro Suzuki 	if (IS_ERR(grf)) {
437c3275903SKatsuhiro Suzuki 		dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
438c3275903SKatsuhiro Suzuki 		return PTR_ERR(grf);
439c3275903SKatsuhiro Suzuki 	}
440c3275903SKatsuhiro Suzuki 	/* enable i2s_acodec_en */
441c3275903SKatsuhiro Suzuki 	regmap_write(grf, RK3328_GRF_SOC_CON2,
442c3275903SKatsuhiro Suzuki 		     (BIT(14) << 16 | BIT(14)));
443c3275903SKatsuhiro Suzuki 
444c3275903SKatsuhiro Suzuki 	ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
445c3275903SKatsuhiro Suzuki 				   &rk3328->spk_depop_time);
446c3275903SKatsuhiro Suzuki 	if (ret < 0) {
447c3275903SKatsuhiro Suzuki 		dev_info(&pdev->dev, "spk_depop_time use default value.\n");
448c3275903SKatsuhiro Suzuki 		rk3328->spk_depop_time = 200;
449c3275903SKatsuhiro Suzuki 	}
450c3275903SKatsuhiro Suzuki 
45187d12d55SRobin Murphy 	rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
45287d12d55SRobin Murphy 	if (IS_ERR(rk3328->mute))
45387d12d55SRobin Murphy 		return PTR_ERR(rk3328->mute);
45487d12d55SRobin Murphy 	/*
45587d12d55SRobin Murphy 	 * Rock64 is the only supported platform to have widely relied on
45687d12d55SRobin Murphy 	 * this; if we do happen to come across an old DTB, just leave the
45787d12d55SRobin Murphy 	 * external mute forced off.
45887d12d55SRobin Murphy 	 */
45987d12d55SRobin Murphy 	if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {
46087d12d55SRobin Murphy 		dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");
46187d12d55SRobin Murphy 		regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
46287d12d55SRobin Murphy 	}
463c3275903SKatsuhiro Suzuki 
464c3275903SKatsuhiro Suzuki 	rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
465c3275903SKatsuhiro Suzuki 	if (IS_ERR(rk3328->mclk))
466c3275903SKatsuhiro Suzuki 		return PTR_ERR(rk3328->mclk);
467c3275903SKatsuhiro Suzuki 
468c3275903SKatsuhiro Suzuki 	ret = clk_prepare_enable(rk3328->mclk);
469c3275903SKatsuhiro Suzuki 	if (ret)
470c3275903SKatsuhiro Suzuki 		return ret;
471c3275903SKatsuhiro Suzuki 	clk_set_rate(rk3328->mclk, INITIAL_FREQ);
472c3275903SKatsuhiro Suzuki 
473c3275903SKatsuhiro Suzuki 	rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
474c3275903SKatsuhiro Suzuki 	if (IS_ERR(rk3328->pclk)) {
475c3275903SKatsuhiro Suzuki 		dev_err(&pdev->dev, "can't get acodec pclk\n");
476d14eece9SYang Yingliang 		ret = PTR_ERR(rk3328->pclk);
477d14eece9SYang Yingliang 		goto err_unprepare_mclk;
478c3275903SKatsuhiro Suzuki 	}
479c3275903SKatsuhiro Suzuki 
480c3275903SKatsuhiro Suzuki 	ret = clk_prepare_enable(rk3328->pclk);
481c3275903SKatsuhiro Suzuki 	if (ret < 0) {
482c3275903SKatsuhiro Suzuki 		dev_err(&pdev->dev, "failed to enable acodec pclk\n");
48335a9b000SNicolas Frattaroli 		goto err_unprepare_mclk;
484c3275903SKatsuhiro Suzuki 	}
485c3275903SKatsuhiro Suzuki 
486f052172aSYueHaibing 	base = devm_platform_ioremap_resource(pdev, 0);
487d14eece9SYang Yingliang 	if (IS_ERR(base)) {
488d14eece9SYang Yingliang 		ret = PTR_ERR(base);
489d14eece9SYang Yingliang 		goto err_unprepare_pclk;
490d14eece9SYang Yingliang 	}
491c3275903SKatsuhiro Suzuki 
492c3275903SKatsuhiro Suzuki 	rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
493c3275903SKatsuhiro Suzuki 					       &rk3328_codec_regmap_config);
494d14eece9SYang Yingliang 	if (IS_ERR(rk3328->regmap)) {
495d14eece9SYang Yingliang 		ret = PTR_ERR(rk3328->regmap);
496d14eece9SYang Yingliang 		goto err_unprepare_pclk;
497d14eece9SYang Yingliang 	}
498c3275903SKatsuhiro Suzuki 
499c3275903SKatsuhiro Suzuki 	platform_set_drvdata(pdev, rk3328);
500c3275903SKatsuhiro Suzuki 
501d14eece9SYang Yingliang 	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
502c3275903SKatsuhiro Suzuki 					       rk3328_dai,
503c3275903SKatsuhiro Suzuki 					       ARRAY_SIZE(rk3328_dai));
504d14eece9SYang Yingliang 	if (ret)
505d14eece9SYang Yingliang 		goto err_unprepare_pclk;
506d14eece9SYang Yingliang 
507d14eece9SYang Yingliang 	return 0;
508d14eece9SYang Yingliang 
509d14eece9SYang Yingliang err_unprepare_pclk:
510d14eece9SYang Yingliang 	clk_disable_unprepare(rk3328->pclk);
511d14eece9SYang Yingliang 
512d14eece9SYang Yingliang err_unprepare_mclk:
513d14eece9SYang Yingliang 	clk_disable_unprepare(rk3328->mclk);
514d14eece9SYang Yingliang 	return ret;
515c3275903SKatsuhiro Suzuki }
516c3275903SKatsuhiro Suzuki 
51784902aecSKrzysztof Kozlowski static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {
518c3275903SKatsuhiro Suzuki 		{ .compatible = "rockchip,rk3328-codec", },
519c3275903SKatsuhiro Suzuki 		{},
520c3275903SKatsuhiro Suzuki };
521c3275903SKatsuhiro Suzuki MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
522c3275903SKatsuhiro Suzuki 
523c3275903SKatsuhiro Suzuki static struct platform_driver rk3328_codec_driver = {
524c3275903SKatsuhiro Suzuki 	.driver = {
525c3275903SKatsuhiro Suzuki 		   .name = "rk3328-codec",
526c3275903SKatsuhiro Suzuki 		   .of_match_table = of_match_ptr(rk3328_codec_of_match),
527c3275903SKatsuhiro Suzuki 	},
528c3275903SKatsuhiro Suzuki 	.probe = rk3328_platform_probe,
529c3275903SKatsuhiro Suzuki };
530c3275903SKatsuhiro Suzuki module_platform_driver(rk3328_codec_driver);
531c3275903SKatsuhiro Suzuki 
532c3275903SKatsuhiro Suzuki MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
533c3275903SKatsuhiro Suzuki MODULE_DESCRIPTION("ASoC rk3328 codec driver");
534c3275903SKatsuhiro Suzuki MODULE_LICENSE("GPL v2");
535