1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Rockchip Audio Codec Digital Interface
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2020 Rockchip Electronics Co.,Ltd
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/of.h>
13*4882a593Smuzhiyun #include <linux/of_gpio.h>
14*4882a593Smuzhiyun #include <linux/of_platform.h>
15*4882a593Smuzhiyun #include <linux/clk.h>
16*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
17*4882a593Smuzhiyun #include <linux/platform_device.h>
18*4882a593Smuzhiyun #include <linux/pm_runtime.h>
19*4882a593Smuzhiyun #include <linux/regmap.h>
20*4882a593Smuzhiyun #include <linux/reset.h>
21*4882a593Smuzhiyun #include <sound/pcm_params.h>
22*4882a593Smuzhiyun #include <sound/dmaengine_pcm.h>
23*4882a593Smuzhiyun #include <sound/tlv.h>
24*4882a593Smuzhiyun #include "rk_codec_digital.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define RK3568_GRF_SOC_CON2 (0x0508)
27*4882a593Smuzhiyun #define RK3588_GRF_SOC_CON6 (0x0318)
28*4882a593Smuzhiyun #define RV1106_GRF_SOC_CON1 (0x0004)
29*4882a593Smuzhiyun #define RV1126_GRF_SOC_CON2 (0x0008)
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun struct rk_codec_digital_soc_data {
32*4882a593Smuzhiyun int (*init)(struct device *dev);
33*4882a593Smuzhiyun void (*deinit)(struct device *dev);
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun struct rk_codec_digital_priv {
37*4882a593Smuzhiyun struct regmap *grf;
38*4882a593Smuzhiyun struct regmap *regmap;
39*4882a593Smuzhiyun struct clk *clk_adc;
40*4882a593Smuzhiyun struct clk *clk_dac;
41*4882a593Smuzhiyun struct clk *clk_i2c;
42*4882a593Smuzhiyun struct clk *pclk;
43*4882a593Smuzhiyun bool pwmout;
44*4882a593Smuzhiyun bool sync;
45*4882a593Smuzhiyun unsigned int pa_ctl_delay_ms;
46*4882a593Smuzhiyun struct gpio_desc *pa_ctl;
47*4882a593Smuzhiyun struct reset_control *rc;
48*4882a593Smuzhiyun const struct rk_codec_digital_soc_data *data;
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /* ADC digital gain */
52*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(adc_tlv, -95625, 375, 0);
53*4882a593Smuzhiyun /* PGA gain */
54*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(pga_tlv, -18, 3, 0);
55*4882a593Smuzhiyun /* DAC digital gain */
56*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(dac_tlv, -95625, 375, 0);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /* ADC Cutoff Freq for High Pass Filter */
59*4882a593Smuzhiyun static const char * const adc_hpf_cutoff_text[] = {
60*4882a593Smuzhiyun "3.79Hz", "60Hz", "243Hz", "493Hz",
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(adc_hpf_cutoff_enum, ADCHPFCF, 0,
64*4882a593Smuzhiyun adc_hpf_cutoff_text);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* DAC Cutoff for High Pass Filter */
67*4882a593Smuzhiyun static const char * const dac_hpf_cutoff_text[] = {
68*4882a593Smuzhiyun "80Hz", "100Hz", "120Hz", "140Hz",
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(dac_hpf_cutoff_enum, DACHPF, 4,
72*4882a593Smuzhiyun dac_hpf_cutoff_text);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun static const char * const pa_ctl[] = {"Off", "On"};
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun static const struct soc_enum pa_enum =
77*4882a593Smuzhiyun SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pa_ctl), pa_ctl);
78*4882a593Smuzhiyun
rk_codec_digital_adc_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)79*4882a593Smuzhiyun static int rk_codec_digital_adc_vol_get(struct snd_kcontrol *kcontrol,
80*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
83*4882a593Smuzhiyun struct soc_mixer_control *mc =
84*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
85*4882a593Smuzhiyun unsigned int val = snd_soc_component_read(component, mc->reg);
86*4882a593Smuzhiyun unsigned int sign = snd_soc_component_read(component, ADCVOGP);
87*4882a593Smuzhiyun unsigned int mask = (1 << fls(mc->max)) - 1;
88*4882a593Smuzhiyun unsigned int shift = mc->shift;
89*4882a593Smuzhiyun int mid = mc->max / 2;
90*4882a593Smuzhiyun int uv;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun switch (mc->reg) {
93*4882a593Smuzhiyun case ADCVOLL0:
94*4882a593Smuzhiyun sign &= ACDCDIG_ADCVOGP_VOLGPL0_MASK;
95*4882a593Smuzhiyun break;
96*4882a593Smuzhiyun case ADCVOLL1:
97*4882a593Smuzhiyun sign &= ACDCDIG_ADCVOGP_VOLGPL1_MASK;
98*4882a593Smuzhiyun break;
99*4882a593Smuzhiyun case ADCVOLR0:
100*4882a593Smuzhiyun sign &= ACDCDIG_ADCVOGP_VOLGPR0_MASK;
101*4882a593Smuzhiyun break;
102*4882a593Smuzhiyun default:
103*4882a593Smuzhiyun return -EINVAL;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun uv = (val >> shift) & mask;
107*4882a593Smuzhiyun if (sign)
108*4882a593Smuzhiyun uv = mid + uv;
109*4882a593Smuzhiyun else
110*4882a593Smuzhiyun uv = mid - uv;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun ucontrol->value.integer.value[0] = uv;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun return 0;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
rk_codec_digital_adc_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)117*4882a593Smuzhiyun static int rk_codec_digital_adc_vol_put(struct snd_kcontrol *kcontrol,
118*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
121*4882a593Smuzhiyun struct soc_mixer_control *mc =
122*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
123*4882a593Smuzhiyun unsigned int reg = mc->reg;
124*4882a593Smuzhiyun unsigned int shift = mc->shift;
125*4882a593Smuzhiyun unsigned int mask = (1 << fls(mc->max)) - 1;
126*4882a593Smuzhiyun unsigned int val, val_mask, sign, sign_mask;
127*4882a593Smuzhiyun int uv = ucontrol->value.integer.value[0];
128*4882a593Smuzhiyun int min = mc->min;
129*4882a593Smuzhiyun int mid = mc->max / 2;
130*4882a593Smuzhiyun bool pos = (uv > mid);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun switch (mc->reg) {
133*4882a593Smuzhiyun case ADCVOLL0:
134*4882a593Smuzhiyun sign_mask = ACDCDIG_ADCVOGP_VOLGPL0_MASK;
135*4882a593Smuzhiyun sign = pos ? ACDCDIG_ADCVOGP_VOLGPL0_POS : ACDCDIG_ADCVOGP_VOLGPL0_NEG;
136*4882a593Smuzhiyun break;
137*4882a593Smuzhiyun case ADCVOLL1:
138*4882a593Smuzhiyun sign_mask = ACDCDIG_ADCVOGP_VOLGPL1_MASK;
139*4882a593Smuzhiyun sign = pos ? ACDCDIG_ADCVOGP_VOLGPL1_POS : ACDCDIG_ADCVOGP_VOLGPL1_NEG;
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun case ADCVOLR0:
142*4882a593Smuzhiyun sign_mask = ACDCDIG_ADCVOGP_VOLGPR0_MASK;
143*4882a593Smuzhiyun sign = pos ? ACDCDIG_ADCVOGP_VOLGPR0_POS : ACDCDIG_ADCVOGP_VOLGPR0_NEG;
144*4882a593Smuzhiyun break;
145*4882a593Smuzhiyun default:
146*4882a593Smuzhiyun return -EINVAL;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun uv = pos ? (uv - mid) : (mid - uv);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun val = ((uv + min) & mask);
152*4882a593Smuzhiyun val_mask = mask << shift;
153*4882a593Smuzhiyun val = val << shift;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun snd_soc_component_update_bits(component, reg, val_mask, val);
156*4882a593Smuzhiyun snd_soc_component_update_bits(component, ADCVOGP, sign_mask, sign);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun return 0;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
rk_codec_digital_dac_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)161*4882a593Smuzhiyun static int rk_codec_digital_dac_vol_get(struct snd_kcontrol *kcontrol,
162*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
165*4882a593Smuzhiyun struct soc_mixer_control *mc =
166*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
167*4882a593Smuzhiyun unsigned int val = snd_soc_component_read(component, mc->reg);
168*4882a593Smuzhiyun unsigned int sign = snd_soc_component_read(component, DACVOGP);
169*4882a593Smuzhiyun unsigned int mask = (1 << fls(mc->max)) - 1;
170*4882a593Smuzhiyun unsigned int shift = mc->shift;
171*4882a593Smuzhiyun int mid = mc->max / 2;
172*4882a593Smuzhiyun int uv;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun uv = (val >> shift) & mask;
175*4882a593Smuzhiyun if (sign)
176*4882a593Smuzhiyun uv = mid + uv;
177*4882a593Smuzhiyun else
178*4882a593Smuzhiyun uv = mid - uv;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun ucontrol->value.integer.value[0] = uv;
181*4882a593Smuzhiyun ucontrol->value.integer.value[1] = uv;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
rk_codec_digital_dac_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)186*4882a593Smuzhiyun static int rk_codec_digital_dac_vol_put(struct snd_kcontrol *kcontrol,
187*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
190*4882a593Smuzhiyun struct soc_mixer_control *mc =
191*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
192*4882a593Smuzhiyun unsigned int reg = mc->reg;
193*4882a593Smuzhiyun unsigned int rreg = mc->rreg;
194*4882a593Smuzhiyun unsigned int shift = mc->shift;
195*4882a593Smuzhiyun unsigned int mask = (1 << fls(mc->max)) - 1;
196*4882a593Smuzhiyun unsigned int val, val_mask, sign;
197*4882a593Smuzhiyun int uv = ucontrol->value.integer.value[0];
198*4882a593Smuzhiyun int min = mc->min;
199*4882a593Smuzhiyun int mid = mc->max / 2;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (uv > mid) {
202*4882a593Smuzhiyun sign = ACDCDIG_DACVOGP_VOLGPL0_POS | ACDCDIG_DACVOGP_VOLGPR0_POS;
203*4882a593Smuzhiyun uv = uv - mid;
204*4882a593Smuzhiyun } else {
205*4882a593Smuzhiyun sign = ACDCDIG_DACVOGP_VOLGPL0_NEG | ACDCDIG_DACVOGP_VOLGPR0_NEG;
206*4882a593Smuzhiyun uv = mid - uv;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun val = ((uv + min) & mask);
210*4882a593Smuzhiyun val_mask = mask << shift;
211*4882a593Smuzhiyun val = val << shift;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun snd_soc_component_update_bits(component, reg, val_mask, val);
214*4882a593Smuzhiyun snd_soc_component_update_bits(component, rreg, val_mask, val);
215*4882a593Smuzhiyun snd_soc_component_write(component, DACVOGP, sign);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
rk_codec_digital_dac_pa_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)220*4882a593Smuzhiyun static int rk_codec_digital_dac_pa_get(struct snd_kcontrol *kcontrol,
221*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
224*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = snd_soc_component_get_drvdata(component);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (!rcd->pa_ctl)
227*4882a593Smuzhiyun return -EINVAL;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun ucontrol->value.enumerated.item[0] = gpiod_get_value(rcd->pa_ctl);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
rk_codec_digital_dac_pa_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)234*4882a593Smuzhiyun static int rk_codec_digital_dac_pa_put(struct snd_kcontrol *kcontrol,
235*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
238*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = snd_soc_component_get_drvdata(component);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun if (!rcd->pa_ctl)
241*4882a593Smuzhiyun return -EINVAL;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun gpiod_set_value(rcd->pa_ctl, ucontrol->value.enumerated.item[0]);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun return 0;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun static const struct snd_kcontrol_new rk_codec_digital_snd_controls[] = {
249*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADCL0 Digital Volume",
250*4882a593Smuzhiyun ADCVOLL0, 0, 0X1fe, 0,
251*4882a593Smuzhiyun rk_codec_digital_adc_vol_get,
252*4882a593Smuzhiyun rk_codec_digital_adc_vol_put,
253*4882a593Smuzhiyun adc_tlv),
254*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADCL1 Digital Volume",
255*4882a593Smuzhiyun ADCVOLL1, 0, 0x1fe, 0,
256*4882a593Smuzhiyun rk_codec_digital_adc_vol_get,
257*4882a593Smuzhiyun rk_codec_digital_adc_vol_put,
258*4882a593Smuzhiyun adc_tlv),
259*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADCR0 Digital Volume",
260*4882a593Smuzhiyun ADCVOLR0, 0, 0x1fe, 0,
261*4882a593Smuzhiyun rk_codec_digital_adc_vol_get,
262*4882a593Smuzhiyun rk_codec_digital_adc_vol_put,
263*4882a593Smuzhiyun adc_tlv),
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun SOC_SINGLE_TLV("ADCL0 PGA Gain",
266*4882a593Smuzhiyun ADCPGL0, 0, 0Xf, 0, pga_tlv),
267*4882a593Smuzhiyun SOC_SINGLE_TLV("ADCL1 PGA Gain",
268*4882a593Smuzhiyun ADCPGL1, 0, 0xf, 0, pga_tlv),
269*4882a593Smuzhiyun SOC_SINGLE_TLV("ADCR0 PGA Gain",
270*4882a593Smuzhiyun ADCPGR0, 0, 0xf, 0, pga_tlv),
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("DAC Digital Volume",
273*4882a593Smuzhiyun DACVOLL0, DACVOLR0, 0, 0x1fe, 0,
274*4882a593Smuzhiyun rk_codec_digital_dac_vol_get,
275*4882a593Smuzhiyun rk_codec_digital_dac_vol_put,
276*4882a593Smuzhiyun dac_tlv),
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun SOC_ENUM("ADC HPF Cutoff", adc_hpf_cutoff_enum),
279*4882a593Smuzhiyun SOC_SINGLE("ADC L0 HPF Switch", ADCHPFEN, 0, 1, 0),
280*4882a593Smuzhiyun SOC_SINGLE("ADC R0 HPF Switch", ADCHPFEN, 1, 1, 0),
281*4882a593Smuzhiyun SOC_SINGLE("ADC L1 HPF Switch", ADCHPFEN, 2, 1, 0),
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun SOC_ENUM("DAC HPF Cutoff", dac_hpf_cutoff_enum),
284*4882a593Smuzhiyun SOC_SINGLE("DAC HPF Switch", DACHPF, 0, 1, 0),
285*4882a593Smuzhiyun SOC_ENUM_EXT("Power Amplifier", pa_enum,
286*4882a593Smuzhiyun rk_codec_digital_dac_pa_get,
287*4882a593Smuzhiyun rk_codec_digital_dac_pa_put),
288*4882a593Smuzhiyun };
289*4882a593Smuzhiyun
rk_codec_digital_reset(struct rk_codec_digital_priv * rcd)290*4882a593Smuzhiyun static void rk_codec_digital_reset(struct rk_codec_digital_priv *rcd)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun if (IS_ERR(rcd->rc))
293*4882a593Smuzhiyun return;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun reset_control_assert(rcd->rc);
296*4882a593Smuzhiyun udelay(1);
297*4882a593Smuzhiyun reset_control_deassert(rcd->rc);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /*
301*4882a593Smuzhiyun * ACDC_CLK D2A_CLK D2A_SYNC Sample rates supported
302*4882a593Smuzhiyun * 49.152MHz 49.152MHz 6.144MHz 12/24/48/96/192kHz
303*4882a593Smuzhiyun * 45.154MHz 45.154MHz 5.644MHz 11.025/22.05/44.1/88.2/176.4kHz
304*4882a593Smuzhiyun * 32.768MHz 32.768MHz 4.096MHz 8/16/32/64/128kHz
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun */
rk_codec_digital_get_clk(unsigned int samplerate,unsigned int * mclk,unsigned int * sclk)307*4882a593Smuzhiyun static void rk_codec_digital_get_clk(unsigned int samplerate,
308*4882a593Smuzhiyun unsigned int *mclk,
309*4882a593Smuzhiyun unsigned int *sclk)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun switch (samplerate) {
312*4882a593Smuzhiyun case 12000:
313*4882a593Smuzhiyun case 24000:
314*4882a593Smuzhiyun case 48000:
315*4882a593Smuzhiyun case 96000:
316*4882a593Smuzhiyun case 192000:
317*4882a593Smuzhiyun *mclk = 49152000;
318*4882a593Smuzhiyun *sclk = 6144000;
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun case 11025:
321*4882a593Smuzhiyun case 22050:
322*4882a593Smuzhiyun case 44100:
323*4882a593Smuzhiyun case 88200:
324*4882a593Smuzhiyun case 176400:
325*4882a593Smuzhiyun *mclk = 45158400;
326*4882a593Smuzhiyun *sclk = 5644800;
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun case 8000:
329*4882a593Smuzhiyun case 16000:
330*4882a593Smuzhiyun case 32000:
331*4882a593Smuzhiyun case 64000:
332*4882a593Smuzhiyun case 128000:
333*4882a593Smuzhiyun *mclk = 32768000;
334*4882a593Smuzhiyun *sclk = 4096000;
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun default:
337*4882a593Smuzhiyun *mclk = 0;
338*4882a593Smuzhiyun *sclk = 0;
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
rk_codec_digital_enable_clk_adc(struct rk_codec_digital_priv * rcd)343*4882a593Smuzhiyun static void rk_codec_digital_enable_clk_adc(struct rk_codec_digital_priv *rcd)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCCLKCTRL,
346*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_CIC_DS_RATIO_MASK |
347*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_ADC_CKE_MASK |
348*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_I2STX_CKE_MASK |
349*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_CKE_BCLKTX_MASK |
350*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_FILTER_GATE_EN_MASK |
351*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_ADC_SYNC_ENA_MASK,
352*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_CIC_DS_RATIO_16 |
353*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_ADC_CKE_EN |
354*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_I2STX_CKE_EN |
355*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_CKE_BCLKTX_EN |
356*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_FILTER_GATE_EN |
357*4882a593Smuzhiyun ACDCDIG_ADCCLKCTRL_ADC_SYNC_ENA_EN);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
rk_codec_digital_enable_clk_dac(struct rk_codec_digital_priv * rcd)360*4882a593Smuzhiyun static void rk_codec_digital_enable_clk_dac(struct rk_codec_digital_priv *rcd)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACCLKCTRL,
363*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_CKE_MASK |
364*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_I2SRX_CKE_MASK |
365*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_CKE_BCLKRX_MASK |
366*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_SYNC_ENA_MASK |
367*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_MODE_ATTENU_MASK,
368*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_CKE_EN |
369*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_I2SRX_CKE_EN |
370*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_CKE_BCLKRX_EN |
371*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_SYNC_ENA_EN |
372*4882a593Smuzhiyun ACDCDIG_DACCLKCTRL_DAC_MODE_ATTENU_EN);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
rk_codec_digital_set_clk_sync(struct rk_codec_digital_priv * rcd,unsigned int mclk,unsigned int sclk,unsigned int bclk)375*4882a593Smuzhiyun static int rk_codec_digital_set_clk_sync(struct rk_codec_digital_priv *rcd,
376*4882a593Smuzhiyun unsigned int mclk,
377*4882a593Smuzhiyun unsigned int sclk,
378*4882a593Smuzhiyun unsigned int bclk)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun unsigned int div_sync, div_bclk;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun div_bclk = DIV_ROUND_CLOSEST(mclk, bclk);
383*4882a593Smuzhiyun div_sync = DIV_ROUND_CLOSEST(mclk, sclk);
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun clk_set_rate(rcd->clk_adc, mclk);
386*4882a593Smuzhiyun clk_set_rate(rcd->clk_dac, mclk);
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /* select clock sync is from ADC. */
389*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, SYSCTRL0,
390*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_SYNC_MODE_MASK |
391*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_CLK_COM_SEL_MASK,
392*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_SYNC_MODE_SYNC |
393*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_CLK_COM_SEL_ADC);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCINT_DIV,
396*4882a593Smuzhiyun ACDCDIG_ADCINT_DIV_INT_DIV_CON_MASK,
397*4882a593Smuzhiyun ACDCDIG_ADCINT_DIV_INT_DIV_CON(div_sync));
398*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACINT_DIV,
399*4882a593Smuzhiyun ACDCDIG_DACINT_DIV_INT_DIV_CON_MASK,
400*4882a593Smuzhiyun ACDCDIG_DACINT_DIV_INT_DIV_CON(div_sync));
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun rk_codec_digital_enable_clk_adc(rcd);
403*4882a593Smuzhiyun rk_codec_digital_enable_clk_dac(rcd);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACSCLKRXINT_DIV,
406*4882a593Smuzhiyun ACDCDIG_DACSCLKRXINT_DIV_SCKRXDIV_MASK,
407*4882a593Smuzhiyun ACDCDIG_DACSCLKRXINT_DIV_SCKRXDIV(div_bclk));
408*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR0,
409*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_RSD_MASK,
410*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_RSD_64);
411*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCSCLKTXINT_DIV,
412*4882a593Smuzhiyun ACDCDIG_ADCSCLKTXINT_DIV_SCKTXDIV_MASK,
413*4882a593Smuzhiyun ACDCDIG_ADCSCLKTXINT_DIV_SCKTXDIV(div_bclk));
414*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR0,
415*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_TSD_MASK,
416*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_TSD_64);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun return 0;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
rk_codec_digital_set_clk(struct rk_codec_digital_priv * rcd,struct snd_pcm_substream * substream,unsigned int samplerate)421*4882a593Smuzhiyun static int rk_codec_digital_set_clk(struct rk_codec_digital_priv *rcd,
422*4882a593Smuzhiyun struct snd_pcm_substream *substream,
423*4882a593Smuzhiyun unsigned int samplerate)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun unsigned int mclk, sclk, bclk;
426*4882a593Smuzhiyun unsigned int div_sync, div_bclk;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun rk_codec_digital_get_clk(samplerate, &mclk, &sclk);
429*4882a593Smuzhiyun if (!mclk || !sclk)
430*4882a593Smuzhiyun return -EINVAL;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun bclk = 64 * samplerate;
433*4882a593Smuzhiyun div_bclk = DIV_ROUND_CLOSEST(mclk, bclk);
434*4882a593Smuzhiyun div_sync = DIV_ROUND_CLOSEST(mclk, sclk);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (rcd->sync)
437*4882a593Smuzhiyun return rk_codec_digital_set_clk_sync(rcd, mclk, sclk, bclk);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
440*4882a593Smuzhiyun clk_set_rate(rcd->clk_dac, mclk);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACINT_DIV,
443*4882a593Smuzhiyun ACDCDIG_DACINT_DIV_INT_DIV_CON_MASK,
444*4882a593Smuzhiyun ACDCDIG_DACINT_DIV_INT_DIV_CON(div_sync));
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun rk_codec_digital_enable_clk_dac(rcd);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACSCLKRXINT_DIV,
449*4882a593Smuzhiyun ACDCDIG_DACSCLKRXINT_DIV_SCKRXDIV_MASK,
450*4882a593Smuzhiyun ACDCDIG_DACSCLKRXINT_DIV_SCKRXDIV(div_bclk));
451*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR0,
452*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_RSD_MASK,
453*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_RSD_64);
454*4882a593Smuzhiyun } else {
455*4882a593Smuzhiyun clk_set_rate(rcd->clk_adc, mclk);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCINT_DIV,
458*4882a593Smuzhiyun ACDCDIG_ADCINT_DIV_INT_DIV_CON_MASK,
459*4882a593Smuzhiyun ACDCDIG_ADCINT_DIV_INT_DIV_CON(div_sync));
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun rk_codec_digital_enable_clk_adc(rcd);
462*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCSCLKTXINT_DIV,
463*4882a593Smuzhiyun ACDCDIG_ADCSCLKTXINT_DIV_SCKTXDIV_MASK,
464*4882a593Smuzhiyun ACDCDIG_ADCSCLKTXINT_DIV_SCKTXDIV(div_bclk));
465*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR0,
466*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_TSD_MASK,
467*4882a593Smuzhiyun ACDCDIG_I2S_CKR0_TSD_64);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun return 0;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
rk_codec_digital_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)473*4882a593Smuzhiyun static int rk_codec_digital_set_dai_fmt(struct snd_soc_dai *dai,
474*4882a593Smuzhiyun unsigned int fmt)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd =
477*4882a593Smuzhiyun snd_soc_component_get_drvdata(dai->component);
478*4882a593Smuzhiyun unsigned int mask = 0, val = 0;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun /* master mode only */
481*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR1,
482*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_MSS_MASK,
483*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_MSS_MASTER);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun mask = ACDCDIG_I2S_CKR1_CKP_MASK |
486*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_RLP_MASK |
487*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_TLP_MASK;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
490*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_NF:
491*4882a593Smuzhiyun val = ACDCDIG_I2S_CKR1_CKP_NORMAL |
492*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_RLP_NORMAL |
493*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_TLP_NORMAL;
494*4882a593Smuzhiyun break;
495*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_IF:
496*4882a593Smuzhiyun val = ACDCDIG_I2S_CKR1_CKP_INVERTED |
497*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_RLP_INVERTED |
498*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_TLP_INVERTED;
499*4882a593Smuzhiyun break;
500*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_NF:
501*4882a593Smuzhiyun val = ACDCDIG_I2S_CKR1_CKP_INVERTED |
502*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_RLP_NORMAL |
503*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_TLP_NORMAL;
504*4882a593Smuzhiyun break;
505*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_IF:
506*4882a593Smuzhiyun val = ACDCDIG_I2S_CKR1_CKP_NORMAL |
507*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_RLP_INVERTED |
508*4882a593Smuzhiyun ACDCDIG_I2S_CKR1_TLP_INVERTED;
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun default:
511*4882a593Smuzhiyun return -EINVAL;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CKR1, mask, val);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun return 0;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
rk_codec_digital_enable_sync(struct rk_codec_digital_priv * rcd)519*4882a593Smuzhiyun static int rk_codec_digital_enable_sync(struct rk_codec_digital_priv *rcd)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
522*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_MASK |
523*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_MASK,
524*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_START |
525*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_START);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, SYSCTRL0,
528*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_GLB_CKE_MASK,
529*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_GLB_CKE_EN);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCDIGEN,
532*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_MASK |
533*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_MASK |
534*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_MASK,
535*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_EN |
536*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_EN |
537*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_EN);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACDIGEN,
540*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_MASK |
541*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_MASK,
542*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_EN |
543*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_EN);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun return 0;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
rk_codec_digital_disable_sync(struct rk_codec_digital_priv * rcd)548*4882a593Smuzhiyun static int rk_codec_digital_disable_sync(struct rk_codec_digital_priv *rcd)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
551*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_MASK |
552*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_MASK,
553*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_STOP |
554*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_STOP);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CLR,
557*4882a593Smuzhiyun ACDCDIG_I2S_CLR_RXC_MASK |
558*4882a593Smuzhiyun ACDCDIG_I2S_CLR_TXC_MASK,
559*4882a593Smuzhiyun ACDCDIG_I2S_CLR_RXC_CLR |
560*4882a593Smuzhiyun ACDCDIG_I2S_CLR_TXC_CLR);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, SYSCTRL0,
563*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_GLB_CKE_MASK,
564*4882a593Smuzhiyun ACDCDIG_SYSCTRL0_GLB_CKE_DIS);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCDIGEN,
567*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_MASK |
568*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_MASK |
569*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_MASK,
570*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_DIS |
571*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_DIS |
572*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_DIS);
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACDIGEN,
575*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_MASK |
576*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_MASK,
577*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_DIS |
578*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_DIS);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun return 0;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
rk_codec_digital_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)583*4882a593Smuzhiyun static int rk_codec_digital_hw_params(struct snd_pcm_substream *substream,
584*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
585*4882a593Smuzhiyun struct snd_soc_dai *dai)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd =
588*4882a593Smuzhiyun snd_soc_component_get_drvdata(dai->component);
589*4882a593Smuzhiyun unsigned int srt = 0, val = 0;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun rk_codec_digital_set_clk(rcd, substream, params_rate(params));
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
594*4882a593Smuzhiyun switch (params_rate(params)) {
595*4882a593Smuzhiyun case 8000:
596*4882a593Smuzhiyun case 11025:
597*4882a593Smuzhiyun case 12000:
598*4882a593Smuzhiyun srt = 0;
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun case 16000:
601*4882a593Smuzhiyun case 22050:
602*4882a593Smuzhiyun case 24000:
603*4882a593Smuzhiyun srt = 1;
604*4882a593Smuzhiyun break;
605*4882a593Smuzhiyun case 32000:
606*4882a593Smuzhiyun case 44100:
607*4882a593Smuzhiyun case 48000:
608*4882a593Smuzhiyun srt = 2;
609*4882a593Smuzhiyun break;
610*4882a593Smuzhiyun case 64000:
611*4882a593Smuzhiyun case 88200:
612*4882a593Smuzhiyun case 96000:
613*4882a593Smuzhiyun srt = 3;
614*4882a593Smuzhiyun break;
615*4882a593Smuzhiyun case 128000:
616*4882a593Smuzhiyun case 176400:
617*4882a593Smuzhiyun case 192000:
618*4882a593Smuzhiyun srt = 4;
619*4882a593Smuzhiyun break;
620*4882a593Smuzhiyun default:
621*4882a593Smuzhiyun return -EINVAL;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACCFG1,
625*4882a593Smuzhiyun ACDCDIG_DACCFG1_DACSRT_MASK,
626*4882a593Smuzhiyun ACDCDIG_DACCFG1_DACSRT(srt));
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun switch (params_format(params)) {
629*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
630*4882a593Smuzhiyun val = 16;
631*4882a593Smuzhiyun break;
632*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
633*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
634*4882a593Smuzhiyun val = 24;
635*4882a593Smuzhiyun break;
636*4882a593Smuzhiyun default:
637*4882a593Smuzhiyun return -EINVAL;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_RXCR0,
641*4882a593Smuzhiyun ACDCDIG_I2S_RXCR0_VDW_MASK,
642*4882a593Smuzhiyun ACDCDIG_I2S_RXCR0_VDW(val));
643*4882a593Smuzhiyun if (rcd->pwmout)
644*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACPWM_CTRL,
645*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_CKE_MASK |
646*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_EN_MASK,
647*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_CKE_EN |
648*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_EN);
649*4882a593Smuzhiyun } else {
650*4882a593Smuzhiyun switch (params_rate(params)) {
651*4882a593Smuzhiyun case 8000:
652*4882a593Smuzhiyun case 11025:
653*4882a593Smuzhiyun case 12000:
654*4882a593Smuzhiyun srt = 0;
655*4882a593Smuzhiyun break;
656*4882a593Smuzhiyun case 16000:
657*4882a593Smuzhiyun case 22050:
658*4882a593Smuzhiyun case 24000:
659*4882a593Smuzhiyun srt = 1;
660*4882a593Smuzhiyun break;
661*4882a593Smuzhiyun case 32000:
662*4882a593Smuzhiyun srt = 2;
663*4882a593Smuzhiyun break;
664*4882a593Smuzhiyun case 44100:
665*4882a593Smuzhiyun case 48000:
666*4882a593Smuzhiyun srt = 3;
667*4882a593Smuzhiyun break;
668*4882a593Smuzhiyun case 64000:
669*4882a593Smuzhiyun case 88200:
670*4882a593Smuzhiyun case 96000:
671*4882a593Smuzhiyun srt = 4;
672*4882a593Smuzhiyun break;
673*4882a593Smuzhiyun case 128000:
674*4882a593Smuzhiyun case 176400:
675*4882a593Smuzhiyun case 192000:
676*4882a593Smuzhiyun srt = 5;
677*4882a593Smuzhiyun break;
678*4882a593Smuzhiyun default:
679*4882a593Smuzhiyun return -EINVAL;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCCFG1,
683*4882a593Smuzhiyun ACDCDIG_ADCCFG1_ADCSRT_MASK,
684*4882a593Smuzhiyun ACDCDIG_ADCCFG1_ADCSRT(srt));
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun switch (params_format(params)) {
687*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
688*4882a593Smuzhiyun val = 16;
689*4882a593Smuzhiyun break;
690*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
691*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
692*4882a593Smuzhiyun val = 24;
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun default:
695*4882a593Smuzhiyun return -EINVAL;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_TXCR0,
699*4882a593Smuzhiyun ACDCDIG_I2S_TXCR0_VDW_MASK,
700*4882a593Smuzhiyun ACDCDIG_I2S_TXCR0_VDW(val));
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun switch (params_channels(params)) {
703*4882a593Smuzhiyun case 4:
704*4882a593Smuzhiyun val = ACDCDIG_I2S_TXCR1_TCSR_4CH;
705*4882a593Smuzhiyun break;
706*4882a593Smuzhiyun case 2:
707*4882a593Smuzhiyun val = ACDCDIG_I2S_TXCR1_TCSR_2CH;
708*4882a593Smuzhiyun break;
709*4882a593Smuzhiyun default:
710*4882a593Smuzhiyun return -EINVAL;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_TXCR1,
714*4882a593Smuzhiyun ACDCDIG_I2S_TXCR1_TCSR_MASK, val);
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (rcd->sync)
718*4882a593Smuzhiyun return rk_codec_digital_enable_sync(rcd);
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
721*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
722*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_MASK,
723*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_START);
724*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACDIGEN,
725*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_MASK |
726*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_MASK,
727*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_EN |
728*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_EN);
729*4882a593Smuzhiyun } else {
730*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
731*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_MASK,
732*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_START);
733*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCDIGEN,
734*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_MASK |
735*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_MASK |
736*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_MASK,
737*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_EN |
738*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_EN |
739*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_EN);
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun return 0;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun
rk_codec_digital_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)745*4882a593Smuzhiyun static int rk_codec_digital_pcm_startup(struct snd_pcm_substream *substream,
746*4882a593Smuzhiyun struct snd_soc_dai *dai)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd =
749*4882a593Smuzhiyun snd_soc_component_get_drvdata(dai->component);
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun if (rcd->pa_ctl) {
752*4882a593Smuzhiyun gpiod_set_value_cansleep(rcd->pa_ctl, 1);
753*4882a593Smuzhiyun if (rcd->pa_ctl_delay_ms)
754*4882a593Smuzhiyun msleep(rcd->pa_ctl_delay_ms);
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun return 0;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
rk_codec_digital_pcm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)760*4882a593Smuzhiyun static void rk_codec_digital_pcm_shutdown(struct snd_pcm_substream *substream,
761*4882a593Smuzhiyun struct snd_soc_dai *dai)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd =
764*4882a593Smuzhiyun snd_soc_component_get_drvdata(dai->component);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun if (rcd->pa_ctl)
767*4882a593Smuzhiyun gpiod_set_value_cansleep(rcd->pa_ctl, 0);
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun if (rcd->sync) {
770*4882a593Smuzhiyun if (!snd_soc_component_active(dai->component)) {
771*4882a593Smuzhiyun rk_codec_digital_disable_sync(rcd);
772*4882a593Smuzhiyun rk_codec_digital_reset(rcd);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun return;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
779*4882a593Smuzhiyun if (rcd->pwmout)
780*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACPWM_CTRL,
781*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_CKE_MASK |
782*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_EN_MASK,
783*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_CKE_DIS |
784*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_DIS);
785*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
786*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_MASK,
787*4882a593Smuzhiyun ACDCDIG_I2S_XFER_RXS_STOP);
788*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CLR,
789*4882a593Smuzhiyun ACDCDIG_I2S_CLR_RXC_MASK,
790*4882a593Smuzhiyun ACDCDIG_I2S_CLR_RXC_CLR);
791*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACDIGEN,
792*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_MASK |
793*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_MASK,
794*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DAC_GLBEN_DIS |
795*4882a593Smuzhiyun ACDCDIG_DACDIGEN_DACEN_L0R1_DIS);
796*4882a593Smuzhiyun } else {
797*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_XFER,
798*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_MASK,
799*4882a593Smuzhiyun ACDCDIG_I2S_XFER_TXS_STOP);
800*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, I2S_CLR,
801*4882a593Smuzhiyun ACDCDIG_I2S_CLR_TXC_MASK,
802*4882a593Smuzhiyun ACDCDIG_I2S_CLR_TXC_CLR);
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, ADCDIGEN,
805*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_MASK |
806*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_MASK |
807*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_MASK,
808*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADC_GLBEN_DIS |
809*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L2_DIS |
810*4882a593Smuzhiyun ACDCDIG_ADCDIGEN_ADCEN_L0R1_DIS);
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun static const struct snd_soc_dai_ops rcd_dai_ops = {
815*4882a593Smuzhiyun .hw_params = rk_codec_digital_hw_params,
816*4882a593Smuzhiyun .set_fmt = rk_codec_digital_set_dai_fmt,
817*4882a593Smuzhiyun .startup = rk_codec_digital_pcm_startup,
818*4882a593Smuzhiyun .shutdown = rk_codec_digital_pcm_shutdown,
819*4882a593Smuzhiyun };
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun static struct snd_soc_dai_driver rcd_dai[] = {
822*4882a593Smuzhiyun {
823*4882a593Smuzhiyun .name = "rk_codec_digital",
824*4882a593Smuzhiyun .id = 0,
825*4882a593Smuzhiyun .playback = {
826*4882a593Smuzhiyun .stream_name = "Playback",
827*4882a593Smuzhiyun .channels_min = 2,
828*4882a593Smuzhiyun .channels_max = 2,
829*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_8000_192000,
830*4882a593Smuzhiyun .formats = (SNDRV_PCM_FMTBIT_S16_LE |
831*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |
832*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE),
833*4882a593Smuzhiyun },
834*4882a593Smuzhiyun .capture = {
835*4882a593Smuzhiyun .stream_name = "Capture",
836*4882a593Smuzhiyun .channels_min = 2,
837*4882a593Smuzhiyun .channels_max = 4,
838*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_8000_192000,
839*4882a593Smuzhiyun .formats = (SNDRV_PCM_FMTBIT_S16_LE |
840*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |
841*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE),
842*4882a593Smuzhiyun },
843*4882a593Smuzhiyun .ops = &rcd_dai_ops,
844*4882a593Smuzhiyun },
845*4882a593Smuzhiyun };
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rcd = {
848*4882a593Smuzhiyun .controls = rk_codec_digital_snd_controls,
849*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(rk_codec_digital_snd_controls),
850*4882a593Smuzhiyun };
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun static const struct regmap_config rcd_regmap_config = {
853*4882a593Smuzhiyun .reg_bits = 32,
854*4882a593Smuzhiyun .reg_stride = 4,
855*4882a593Smuzhiyun .val_bits = 32,
856*4882a593Smuzhiyun .max_register = VERSION,
857*4882a593Smuzhiyun .cache_type = REGCACHE_FLAT,
858*4882a593Smuzhiyun };
859*4882a593Smuzhiyun
rk3568_soc_init(struct device * dev)860*4882a593Smuzhiyun static int rk3568_soc_init(struct device *dev)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
865*4882a593Smuzhiyun return PTR_ERR(rcd->grf);
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun /* enable internal codec to i2s3 */
868*4882a593Smuzhiyun return regmap_write(rcd->grf, RK3568_GRF_SOC_CON2,
869*4882a593Smuzhiyun (BIT(13) << 16 | BIT(13)));
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
rk3568_soc_deinit(struct device * dev)872*4882a593Smuzhiyun static void rk3568_soc_deinit(struct device *dev)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
877*4882a593Smuzhiyun return;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun regmap_write(rcd->grf, RK3568_GRF_SOC_CON2, (BIT(13) << 16));
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun static const struct rk_codec_digital_soc_data rk3568_data = {
883*4882a593Smuzhiyun .init = rk3568_soc_init,
884*4882a593Smuzhiyun .deinit = rk3568_soc_deinit,
885*4882a593Smuzhiyun };
886*4882a593Smuzhiyun
rk3588_soc_init(struct device * dev)887*4882a593Smuzhiyun static int rk3588_soc_init(struct device *dev)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
892*4882a593Smuzhiyun return PTR_ERR(rcd->grf);
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun /* enable internal codec to i2s3 */
895*4882a593Smuzhiyun return regmap_write(rcd->grf, RK3588_GRF_SOC_CON6,
896*4882a593Smuzhiyun (BIT(11) << 16 | BIT(11)));
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun
rk3588_soc_deinit(struct device * dev)899*4882a593Smuzhiyun static void rk3588_soc_deinit(struct device *dev)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
904*4882a593Smuzhiyun return;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun regmap_write(rcd->grf, RK3588_GRF_SOC_CON6, (BIT(11) << 16));
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun static const struct rk_codec_digital_soc_data rk3588_data = {
910*4882a593Smuzhiyun .init = rk3588_soc_init,
911*4882a593Smuzhiyun .deinit = rk3588_soc_deinit,
912*4882a593Smuzhiyun };
913*4882a593Smuzhiyun
rv1106_soc_init(struct device * dev)914*4882a593Smuzhiyun static int rv1106_soc_init(struct device *dev)
915*4882a593Smuzhiyun {
916*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
919*4882a593Smuzhiyun return PTR_ERR(rcd->grf);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* enable internal codec to i2s0 */
922*4882a593Smuzhiyun return regmap_write(rcd->grf, RV1106_GRF_SOC_CON1,
923*4882a593Smuzhiyun (BIT(8) << 16 | BIT(8)));
924*4882a593Smuzhiyun }
925*4882a593Smuzhiyun
rv1106_soc_deinit(struct device * dev)926*4882a593Smuzhiyun static void rv1106_soc_deinit(struct device *dev)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
931*4882a593Smuzhiyun return;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun regmap_write(rcd->grf, RV1106_GRF_SOC_CON1, (BIT(8) << 16));
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun static const struct rk_codec_digital_soc_data rv1106_data = {
937*4882a593Smuzhiyun .init = rv1106_soc_init,
938*4882a593Smuzhiyun .deinit = rv1106_soc_deinit,
939*4882a593Smuzhiyun };
940*4882a593Smuzhiyun
rv1126_soc_init(struct device * dev)941*4882a593Smuzhiyun static int rv1126_soc_init(struct device *dev)
942*4882a593Smuzhiyun {
943*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
946*4882a593Smuzhiyun return PTR_ERR(rcd->grf);
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun /* enable internal codec to i2s0 */
949*4882a593Smuzhiyun return regmap_write(rcd->grf, RV1126_GRF_SOC_CON2,
950*4882a593Smuzhiyun (BIT(13) << 16 | BIT(13)));
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun
rv1126_soc_deinit(struct device * dev)953*4882a593Smuzhiyun static void rv1126_soc_deinit(struct device *dev)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (IS_ERR(rcd->grf))
958*4882a593Smuzhiyun return;
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun regmap_write(rcd->grf, RV1126_GRF_SOC_CON2, (BIT(13) << 16));
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun static const struct rk_codec_digital_soc_data rv1126_data = {
964*4882a593Smuzhiyun .init = rv1126_soc_init,
965*4882a593Smuzhiyun .deinit = rv1126_soc_deinit,
966*4882a593Smuzhiyun };
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun #ifdef CONFIG_OF
969*4882a593Smuzhiyun static const struct of_device_id rcd_of_match[] = {
970*4882a593Smuzhiyun { .compatible = "rockchip,codec-digital-v1", },
971*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3568
972*4882a593Smuzhiyun { .compatible = "rockchip,rk3568-codec-digital", .data = &rk3568_data },
973*4882a593Smuzhiyun #endif
974*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3588
975*4882a593Smuzhiyun { .compatible = "rockchip,rk3588-codec-digital", .data = &rk3588_data },
976*4882a593Smuzhiyun #endif
977*4882a593Smuzhiyun #ifdef CONFIG_CPU_RV1106
978*4882a593Smuzhiyun { .compatible = "rockchip,rv1106-codec-digital", .data = &rv1106_data },
979*4882a593Smuzhiyun #endif
980*4882a593Smuzhiyun #ifdef CONFIG_CPU_RV1126
981*4882a593Smuzhiyun { .compatible = "rockchip,rv1126-codec-digital", .data = &rv1126_data },
982*4882a593Smuzhiyun #endif
983*4882a593Smuzhiyun {},
984*4882a593Smuzhiyun };
985*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rcd_of_match);
986*4882a593Smuzhiyun #endif
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun #ifdef CONFIG_PM
rk_codec_digital_runtime_resume(struct device * dev)989*4882a593Smuzhiyun static int rk_codec_digital_runtime_resume(struct device *dev)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
992*4882a593Smuzhiyun int ret = 0;
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun ret = clk_prepare_enable(rcd->pclk);
995*4882a593Smuzhiyun if (ret)
996*4882a593Smuzhiyun return ret;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun regcache_cache_only(rcd->regmap, false);
999*4882a593Smuzhiyun regcache_mark_dirty(rcd->regmap);
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun ret = regcache_sync(rcd->regmap);
1002*4882a593Smuzhiyun if (ret)
1003*4882a593Smuzhiyun goto err;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun ret = clk_prepare_enable(rcd->clk_adc);
1006*4882a593Smuzhiyun if (ret)
1007*4882a593Smuzhiyun goto err;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun ret = clk_prepare_enable(rcd->clk_dac);
1010*4882a593Smuzhiyun if (ret)
1011*4882a593Smuzhiyun goto err_adc;
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun ret = clk_prepare_enable(rcd->clk_i2c);
1014*4882a593Smuzhiyun if (ret)
1015*4882a593Smuzhiyun goto err_dac;
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun return 0;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun err_dac:
1020*4882a593Smuzhiyun clk_disable_unprepare(rcd->clk_dac);
1021*4882a593Smuzhiyun err_adc:
1022*4882a593Smuzhiyun clk_disable_unprepare(rcd->clk_adc);
1023*4882a593Smuzhiyun err:
1024*4882a593Smuzhiyun clk_disable_unprepare(rcd->pclk);
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun return ret;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun
rk_codec_digital_runtime_suspend(struct device * dev)1029*4882a593Smuzhiyun static int rk_codec_digital_runtime_suspend(struct device *dev)
1030*4882a593Smuzhiyun {
1031*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(dev);
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun regcache_cache_only(rcd->regmap, true);
1034*4882a593Smuzhiyun clk_disable_unprepare(rcd->clk_adc);
1035*4882a593Smuzhiyun clk_disable_unprepare(rcd->clk_dac);
1036*4882a593Smuzhiyun clk_disable_unprepare(rcd->clk_i2c);
1037*4882a593Smuzhiyun clk_disable_unprepare(rcd->pclk);
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun return 0;
1040*4882a593Smuzhiyun }
1041*4882a593Smuzhiyun #endif
1042*4882a593Smuzhiyun
rk_codec_digital_platform_probe(struct platform_device * pdev)1043*4882a593Smuzhiyun static int rk_codec_digital_platform_probe(struct platform_device *pdev)
1044*4882a593Smuzhiyun {
1045*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
1046*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd;
1047*4882a593Smuzhiyun struct resource *res;
1048*4882a593Smuzhiyun void __iomem *base;
1049*4882a593Smuzhiyun int ret = 0;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun rcd = devm_kzalloc(&pdev->dev, sizeof(*rcd), GFP_KERNEL);
1052*4882a593Smuzhiyun if (!rcd)
1053*4882a593Smuzhiyun return -ENOMEM;
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun rcd->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
1056*4882a593Smuzhiyun rcd->pwmout = of_property_read_bool(np, "rockchip,pwm-output-mode");
1057*4882a593Smuzhiyun rcd->sync = of_property_read_bool(np, "rockchip,clk-sync-mode");
1058*4882a593Smuzhiyun if (of_property_read_u32(np, "rockchip,pa-ctl-delay-ms",
1059*4882a593Smuzhiyun &rcd->pa_ctl_delay_ms))
1060*4882a593Smuzhiyun rcd->pa_ctl_delay_ms = 0;
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun rcd->rc = devm_reset_control_get(&pdev->dev, "reset");
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun /* optional on some platform */
1065*4882a593Smuzhiyun rcd->clk_adc = devm_clk_get_optional(&pdev->dev, "adc");
1066*4882a593Smuzhiyun if (IS_ERR(rcd->clk_adc))
1067*4882a593Smuzhiyun return PTR_ERR(rcd->clk_adc);
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun rcd->clk_dac = devm_clk_get(&pdev->dev, "dac");
1070*4882a593Smuzhiyun if (IS_ERR(rcd->clk_dac))
1071*4882a593Smuzhiyun return PTR_ERR(rcd->clk_dac);
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun /* optional on some platform */
1074*4882a593Smuzhiyun rcd->clk_i2c = devm_clk_get_optional(&pdev->dev, "i2c");
1075*4882a593Smuzhiyun if (IS_ERR(rcd->clk_i2c))
1076*4882a593Smuzhiyun return PTR_ERR(rcd->clk_i2c);
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun rcd->pclk = devm_clk_get(&pdev->dev, "pclk");
1079*4882a593Smuzhiyun if (IS_ERR(rcd->pclk))
1080*4882a593Smuzhiyun return PTR_ERR(rcd->pclk);
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1083*4882a593Smuzhiyun base = devm_ioremap_resource(&pdev->dev, res);
1084*4882a593Smuzhiyun if (IS_ERR(base))
1085*4882a593Smuzhiyun return PTR_ERR(base);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun rcd->regmap =
1088*4882a593Smuzhiyun devm_regmap_init_mmio(&pdev->dev, base, &rcd_regmap_config);
1089*4882a593Smuzhiyun if (IS_ERR(rcd->regmap))
1090*4882a593Smuzhiyun return PTR_ERR(rcd->regmap);
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun platform_set_drvdata(pdev, rcd);
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun rcd->data = of_device_get_match_data(&pdev->dev);
1095*4882a593Smuzhiyun if (rcd->data && rcd->data->init) {
1096*4882a593Smuzhiyun ret = rcd->data->init(&pdev->dev);
1097*4882a593Smuzhiyun if (ret)
1098*4882a593Smuzhiyun return ret;
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun pm_runtime_enable(&pdev->dev);
1102*4882a593Smuzhiyun if (!pm_runtime_enabled(&pdev->dev)) {
1103*4882a593Smuzhiyun ret = rk_codec_digital_runtime_resume(&pdev->dev);
1104*4882a593Smuzhiyun if (ret)
1105*4882a593Smuzhiyun goto err_pm_disable;
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun if (rcd->pwmout)
1109*4882a593Smuzhiyun regmap_update_bits(rcd->regmap, DACPWM_CTRL,
1110*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_MASK,
1111*4882a593Smuzhiyun ACDCDIG_DACPWM_CTRL_PWM_MODE_0);
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun rcd->pa_ctl = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
1114*4882a593Smuzhiyun GPIOD_OUT_LOW);
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun if (!rcd->pa_ctl) {
1117*4882a593Smuzhiyun dev_info(&pdev->dev, "no need pa-ctl gpio\n");
1118*4882a593Smuzhiyun } else if (IS_ERR(rcd->pa_ctl)) {
1119*4882a593Smuzhiyun ret = PTR_ERR(rcd->pa_ctl);
1120*4882a593Smuzhiyun dev_err(&pdev->dev, "fail to request gpio pa-ctl\n");
1121*4882a593Smuzhiyun goto err_suspend;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rcd,
1125*4882a593Smuzhiyun rcd_dai, ARRAY_SIZE(rcd_dai));
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun if (ret)
1128*4882a593Smuzhiyun goto err_suspend;
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun return 0;
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun err_suspend:
1133*4882a593Smuzhiyun if (!pm_runtime_status_suspended(&pdev->dev))
1134*4882a593Smuzhiyun rk_codec_digital_runtime_suspend(&pdev->dev);
1135*4882a593Smuzhiyun err_pm_disable:
1136*4882a593Smuzhiyun pm_runtime_disable(&pdev->dev);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun if (rcd->data && rcd->data->deinit)
1139*4882a593Smuzhiyun rcd->data->deinit(&pdev->dev);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun return ret;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun
rk_codec_digital_platform_remove(struct platform_device * pdev)1144*4882a593Smuzhiyun static int rk_codec_digital_platform_remove(struct platform_device *pdev)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun struct rk_codec_digital_priv *rcd = dev_get_drvdata(&pdev->dev);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun pm_runtime_disable(&pdev->dev);
1149*4882a593Smuzhiyun if (!pm_runtime_status_suspended(&pdev->dev))
1150*4882a593Smuzhiyun rk_codec_digital_runtime_suspend(&pdev->dev);
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun if (rcd->data && rcd->data->deinit)
1153*4882a593Smuzhiyun rcd->data->deinit(&pdev->dev);
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun return 0;
1156*4882a593Smuzhiyun }
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun static const struct dev_pm_ops rcd_pm = {
1159*4882a593Smuzhiyun SET_RUNTIME_PM_OPS(rk_codec_digital_runtime_suspend,
1160*4882a593Smuzhiyun rk_codec_digital_runtime_resume, NULL)
1161*4882a593Smuzhiyun };
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun static struct platform_driver rk_codec_digital_driver = {
1164*4882a593Smuzhiyun .driver = {
1165*4882a593Smuzhiyun .name = "rk_codec_digital",
1166*4882a593Smuzhiyun .of_match_table = of_match_ptr(rcd_of_match),
1167*4882a593Smuzhiyun .pm = &rcd_pm,
1168*4882a593Smuzhiyun },
1169*4882a593Smuzhiyun .probe = rk_codec_digital_platform_probe,
1170*4882a593Smuzhiyun .remove = rk_codec_digital_platform_remove,
1171*4882a593Smuzhiyun };
1172*4882a593Smuzhiyun module_platform_driver(rk_codec_digital_driver);
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
1175*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC Rockchip codec digital driver");
1176*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1177