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