1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // rxk1000_codec.c -- rk1000 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/delay.h>
8*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
9*4882a593Smuzhiyun #include <linux/i2c.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <sound/core.h>
12*4882a593Smuzhiyun #include <sound/pcm.h>
13*4882a593Smuzhiyun #include <sound/pcm_params.h>
14*4882a593Smuzhiyun #include <sound/soc.h>
15*4882a593Smuzhiyun #include <sound/soc-dapm.h>
16*4882a593Smuzhiyun #include "rk1000_codec.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define FREQ441KHZ (0x11 << 1)
19*4882a593Smuzhiyun /* rk1000 output volume, DAC Digital Gain */
20*4882a593Smuzhiyun /* 0x0000 ~ 0xF42 */
21*4882a593Smuzhiyun #define VOLUME_OUTPUT 0xF42
22*4882a593Smuzhiyun /* 0x0 ~ 0x3f(bit0-bit5) max=0x0(+6DB) min=0x3f(-60DB) Analog Gain */
23*4882a593Smuzhiyun #define VOLUME_CODEC_PA 0x0
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* rk1000 input volume, rk610 can not adjust the recording volume */
26*4882a593Smuzhiyun #define VOLUME_INPUT 0x07
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define OUT_CAPLESS (1)
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static const struct reg_default rk1000_codec_reg[] = {
31*4882a593Smuzhiyun { 0x00, 0x05 },
32*4882a593Smuzhiyun { 0x01, 0x04 },
33*4882a593Smuzhiyun { 0x02, 0xfd },
34*4882a593Smuzhiyun { 0x03, 0xf3 },
35*4882a593Smuzhiyun { 0x04, 0x03 },
36*4882a593Smuzhiyun { 0x05, 0x00 },
37*4882a593Smuzhiyun { 0x06, 0x00 },
38*4882a593Smuzhiyun { 0x07, 0x00 },
39*4882a593Smuzhiyun { 0x08, 0x00 },
40*4882a593Smuzhiyun { 0x09, 0x05 },
41*4882a593Smuzhiyun { 0x0a, 0x00 },
42*4882a593Smuzhiyun { 0x0b, 0x00 },
43*4882a593Smuzhiyun { 0x0c, 0x97 },
44*4882a593Smuzhiyun { 0x0d, 0x97 },
45*4882a593Smuzhiyun { 0x0e, 0x97 },
46*4882a593Smuzhiyun { 0x0f, 0x97 },
47*4882a593Smuzhiyun { 0x10, 0x97 },
48*4882a593Smuzhiyun { 0x11, 0x97 },
49*4882a593Smuzhiyun { 0x12, 0xcc },
50*4882a593Smuzhiyun { 0x13, 0x00 },
51*4882a593Smuzhiyun { 0x14, 0x00 },
52*4882a593Smuzhiyun { 0x15, 0xf1 },
53*4882a593Smuzhiyun { 0x16, 0x90 },
54*4882a593Smuzhiyun { 0x17, 0xff },
55*4882a593Smuzhiyun { 0x18, 0xff },
56*4882a593Smuzhiyun { 0x19, 0xff },
57*4882a593Smuzhiyun { 0x1a, 0x9c },
58*4882a593Smuzhiyun { 0x1b, 0x00 },
59*4882a593Smuzhiyun { 0x1c, 0x00 },
60*4882a593Smuzhiyun { 0x1d, 0xff },
61*4882a593Smuzhiyun { 0x1e, 0xff },
62*4882a593Smuzhiyun { 0x1f, 0xff },
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun struct rk1000_codec_priv {
66*4882a593Smuzhiyun struct regmap *regmap;
67*4882a593Smuzhiyun struct regmap *ctlmap;
68*4882a593Smuzhiyun struct snd_soc_component *component;
69*4882a593Smuzhiyun struct delayed_work pa_delayed_work;
70*4882a593Smuzhiyun struct gpio_desc *spk_en_gpio;
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun * Some amplifiers enable a longer time.
73*4882a593Smuzhiyun * config after pa_enable_io delay pa_enable_time(ms)
74*4882a593Smuzhiyun * so value range is 0 - 8000.
75*4882a593Smuzhiyun */
76*4882a593Smuzhiyun unsigned int pa_enable_time;
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun
spk_ctrl_fun(struct snd_soc_component * component,int status)79*4882a593Smuzhiyun static void spk_ctrl_fun(struct snd_soc_component *component, int status)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000_codec;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun rk1000_codec = snd_soc_component_get_drvdata(component);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun if (rk1000_codec->spk_en_gpio)
86*4882a593Smuzhiyun gpiod_set_value(rk1000_codec->spk_en_gpio, status);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
rk1000_codec_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)89*4882a593Smuzhiyun static int rk1000_codec_set_bias_level(struct snd_soc_component *component,
90*4882a593Smuzhiyun enum snd_soc_bias_level level)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun switch (level) {
93*4882a593Smuzhiyun case SND_SOC_BIAS_ON:
94*4882a593Smuzhiyun break;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
97*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1D, 0x2a);
98*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0x40);
99*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F, 0x49);
100*4882a593Smuzhiyun break;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
103*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1D, 0x2a);
104*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0x40);
105*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F, 0x49);
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
109*4882a593Smuzhiyun spk_ctrl_fun(component, GPIO_LOW);
110*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1D, 0xFF);
111*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0xFF);
112*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F, 0xFF);
113*4882a593Smuzhiyun break;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun return 0;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
rk1000_codec_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)118*4882a593Smuzhiyun static int rk1000_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
119*4882a593Smuzhiyun unsigned int fmt)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun struct snd_soc_component *component = codec_dai->component;
122*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000_codec;
123*4882a593Smuzhiyun u16 iface = 0;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun rk1000_codec = snd_soc_component_get_drvdata(component);
126*4882a593Smuzhiyun /* setup Vmid and Vref, other module power down */
127*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1D, 0x2a);
128*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0x40);
129*4882a593Smuzhiyun /* set master/slave audio interface */
130*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
131*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
132*4882a593Smuzhiyun iface = 0x0040;
133*4882a593Smuzhiyun break;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
136*4882a593Smuzhiyun iface = 0x0000;
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun default:
140*4882a593Smuzhiyun return -EINVAL;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun /* interface format */
143*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
144*4882a593Smuzhiyun case SND_SOC_DAIFMT_I2S:
145*4882a593Smuzhiyun iface |= 0x0002;
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun case SND_SOC_DAIFMT_RIGHT_J:
149*4882a593Smuzhiyun break;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun case SND_SOC_DAIFMT_LEFT_J:
152*4882a593Smuzhiyun iface |= 0x0001;
153*4882a593Smuzhiyun break;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_A:
156*4882a593Smuzhiyun iface |= 0x0003;
157*4882a593Smuzhiyun break;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_B:
160*4882a593Smuzhiyun iface |= 0x0013;
161*4882a593Smuzhiyun break;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun default:
164*4882a593Smuzhiyun return -EINVAL;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* clock inversion */
168*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
169*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_NF:
170*4882a593Smuzhiyun break;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_IF:
173*4882a593Smuzhiyun iface |= 0x0090;
174*4882a593Smuzhiyun break;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_NF:
177*4882a593Smuzhiyun iface |= 0x0080;
178*4882a593Smuzhiyun break;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_IF:
181*4882a593Smuzhiyun iface |= 0x0010;
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun default:
185*4882a593Smuzhiyun return -EINVAL;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R09, iface);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
rk1000_codec_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)193*4882a593Smuzhiyun static int rk1000_codec_pcm_hw_params(struct snd_pcm_substream *substream,
194*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
195*4882a593Smuzhiyun struct snd_soc_dai *dai)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun u32 iface;
198*4882a593Smuzhiyun struct snd_soc_pcm_runtime *rtd = substream->private_data;
199*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
200*4882a593Smuzhiyun unsigned int dai_fmt;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun dai_fmt = rtd->card->dai_link[0].dai_fmt;
203*4882a593Smuzhiyun iface = snd_soc_component_read(component, ACCELCODEC_R09) & 0x1f3;
204*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0C, 0x17);
205*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R04,
206*4882a593Smuzhiyun ASC_INT_MUTE_L | ASC_INT_MUTE_R |
207*4882a593Smuzhiyun ASC_SIDETONE_L_OFF | ASC_SIDETONE_R_OFF);
208*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0B,
209*4882a593Smuzhiyun ASC_DEC_DISABLE | ASC_INT_DISABLE);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)
212*4882a593Smuzhiyun iface |= ASC_INVERT_BCLK;
213*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R09, iface);
214*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0A, 0xa0);
215*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0B, ASC_DEC_ENABLE | ASC_INT_ENABLE);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
rk1000_codec_mute(struct snd_soc_dai * dai,int mute,int stream)220*4882a593Smuzhiyun static int rk1000_codec_mute(struct snd_soc_dai *dai, int mute, int stream)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
223*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000_codec;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun rk1000_codec = snd_soc_component_get_drvdata(component);
226*4882a593Smuzhiyun if (mute) {
227*4882a593Smuzhiyun /* AOL */
228*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R17, 0xFF);
229*4882a593Smuzhiyun /* AOR */
230*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R18, 0xFF);
231*4882a593Smuzhiyun /* AOM */
232*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R19, 0xFF);
233*4882a593Smuzhiyun /* soft mute */
234*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R04,
235*4882a593Smuzhiyun ASC_INT_MUTE_L | ASC_INT_MUTE_R |
236*4882a593Smuzhiyun ASC_SIDETONE_L_OFF | ASC_SIDETONE_R_OFF);
237*4882a593Smuzhiyun } else {
238*4882a593Smuzhiyun /* setup Vmid and Vref, other module power down */
239*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1D, 0x2a);
240*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0x40);
241*4882a593Smuzhiyun /* AOL */
242*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R17,
243*4882a593Smuzhiyun VOLUME_CODEC_PA | ASC_OUTPUT_ACTIVE |
244*4882a593Smuzhiyun ASC_CROSSZERO_EN);
245*4882a593Smuzhiyun /* AOR */
246*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R18,
247*4882a593Smuzhiyun VOLUME_CODEC_PA | ASC_OUTPUT_ACTIVE |
248*4882a593Smuzhiyun ASC_CROSSZERO_EN);
249*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R04,
250*4882a593Smuzhiyun ASC_INT_ACTIVE_L | ASC_INT_ACTIVE_R |
251*4882a593Smuzhiyun ASC_SIDETONE_L_OFF | ASC_SIDETONE_R_OFF);
252*4882a593Smuzhiyun /* AOM */
253*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R19, 0x7F);
254*4882a593Smuzhiyun #if OUT_CAPLESS
255*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F,
256*4882a593Smuzhiyun 0x09 | ASC_PDMIXM_ENABLE);
257*4882a593Smuzhiyun #else
258*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F,
259*4882a593Smuzhiyun 0x09 | ASC_PDMIXM_ENABLE | ASC_PDPAM_ENABLE);
260*4882a593Smuzhiyun #endif
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
pa_delayedwork(struct work_struct * work)266*4882a593Smuzhiyun static void pa_delayedwork(struct work_struct *work)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun struct rk1000_codec_priv *priv = container_of(work,
269*4882a593Smuzhiyun struct rk1000_codec_priv,
270*4882a593Smuzhiyun pa_delayed_work.work);
271*4882a593Smuzhiyun struct snd_soc_component *component = priv->component;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun spk_ctrl_fun(component, GPIO_HIGH);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun static struct snd_soc_dai_ops rk1000_codec_ops = {
277*4882a593Smuzhiyun .hw_params = rk1000_codec_pcm_hw_params,
278*4882a593Smuzhiyun .set_fmt = rk1000_codec_set_dai_fmt,
279*4882a593Smuzhiyun .mute_stream = rk1000_codec_mute,
280*4882a593Smuzhiyun .no_capture_mute = 1,
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun #define RK1000_CODEC_RATES SNDRV_PCM_RATE_8000_192000
284*4882a593Smuzhiyun #define RK1000_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
285*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_3LE | \
286*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE)
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static struct snd_soc_dai_driver rk1000_codec_dai[] = {
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun .name = "rk1000_codec",
291*4882a593Smuzhiyun .playback = {
292*4882a593Smuzhiyun .stream_name = "Playback",
293*4882a593Smuzhiyun .channels_min = 2,
294*4882a593Smuzhiyun .channels_max = 8,
295*4882a593Smuzhiyun .rates = RK1000_CODEC_RATES,
296*4882a593Smuzhiyun .formats = RK1000_CODEC_FORMATS,
297*4882a593Smuzhiyun },
298*4882a593Smuzhiyun .capture = {
299*4882a593Smuzhiyun .stream_name = "Capture",
300*4882a593Smuzhiyun .channels_min = 2,
301*4882a593Smuzhiyun .channels_max = 2,
302*4882a593Smuzhiyun .rates = RK1000_CODEC_RATES,
303*4882a593Smuzhiyun .formats = RK1000_CODEC_FORMATS,
304*4882a593Smuzhiyun },
305*4882a593Smuzhiyun .ops = &rk1000_codec_ops,
306*4882a593Smuzhiyun .symmetric_rates = 1,
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun };
309*4882a593Smuzhiyun
rk1000_codec_reg_init(struct snd_soc_component * component)310*4882a593Smuzhiyun static void rk1000_codec_reg_init(struct snd_soc_component *component)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000_codec;
313*4882a593Smuzhiyun unsigned int digital_gain;
314*4882a593Smuzhiyun unsigned int mic_vol;
315*4882a593Smuzhiyun int ret;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun mic_vol = VOLUME_INPUT;
318*4882a593Smuzhiyun rk1000_codec = snd_soc_component_get_drvdata(component);
319*4882a593Smuzhiyun ret = snd_soc_component_write(component, ACCELCODEC_R1D, 0x30);
320*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1E, 0x40);
321*4882a593Smuzhiyun /*Route R-LPF->R-Mixer, L-LPF->L-Mixer*/
322*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R15, 0xC1);
323*4882a593Smuzhiyun /*With Cap Output, VMID ramp up slow*/
324*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1A, 0x14);
325*4882a593Smuzhiyun mdelay(10);
326*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0C, 0x10 | ASC_INPUT_VOL_0DB);
327*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0D, 0x10 | ASC_INPUT_VOL_0DB);
328*4882a593Smuzhiyun if (mic_vol > 0x07) {
329*4882a593Smuzhiyun /*Select MIC input*/
330*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R12,
331*4882a593Smuzhiyun 0x4c | ASC_MIC_INPUT | ASC_MIC_BOOST_20DB);
332*4882a593Smuzhiyun mic_vol -= 0x07;
333*4882a593Smuzhiyun } else {
334*4882a593Smuzhiyun /*Select MIC input*/
335*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R12, 0x4c | ASC_MIC_INPUT);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun /*use default value*/
338*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1C, ASC_DEM_ENABLE);
339*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0E, 0x10 | mic_vol);
340*4882a593Smuzhiyun /* disable route PGA->R/L Mixer, PGA gain 0db. */
341*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R13, 0x05 | 0 << 3);
342*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R14, 0x05 | 0 << 3);
343*4882a593Smuzhiyun /*2soft mute*/
344*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R04,
345*4882a593Smuzhiyun ASC_INT_MUTE_L | ASC_INT_MUTE_R |
346*4882a593Smuzhiyun ASC_SIDETONE_L_OFF | ASC_SIDETONE_R_OFF);
347*4882a593Smuzhiyun /*2set default SR and clk*/
348*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0A, FREQ441KHZ | ASC_NORMAL_MODE |
349*4882a593Smuzhiyun (0x10 << 1) | ASC_CLKNODIV | ASC_CLK_ENABLE);
350*4882a593Smuzhiyun /*2Config audio interface*/
351*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R09, ASC_I2S_MODE |
352*4882a593Smuzhiyun ASC_16BIT_MODE | ASC_NORMAL_LRCLK |
353*4882a593Smuzhiyun ASC_LRSWAP_DISABLE | ASC_NORMAL_BCLK);
354*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R00, ASC_HPF_ENABLE |
355*4882a593Smuzhiyun ASC_DSM_MODE_ENABLE | ASC_SCRAMBLE_ENABLE |
356*4882a593Smuzhiyun ASC_DITHER_ENABLE | ASC_BCLKDIV_4);
357*4882a593Smuzhiyun /*2volume,input,output*/
358*4882a593Smuzhiyun digital_gain = VOLUME_OUTPUT;
359*4882a593Smuzhiyun if (snd_soc_component_read(component, ACCELCODEC_R05) != 0x0f) {
360*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R05,
361*4882a593Smuzhiyun (digital_gain >> 8) & 0xFF);
362*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R06, digital_gain & 0xFF);
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun if (snd_soc_component_read(component, ACCELCODEC_R07) != 0x0f) {
366*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R07,
367*4882a593Smuzhiyun (digital_gain >> 8) & 0xFF);
368*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R08, digital_gain & 0xFF);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R0B,
372*4882a593Smuzhiyun ASC_DEC_ENABLE | ASC_INT_ENABLE);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun #if OUT_CAPLESS
375*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F,
376*4882a593Smuzhiyun 0x09 | ASC_PDMIXM_ENABLE);
377*4882a593Smuzhiyun #else
378*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R1F, 0x09 |
379*4882a593Smuzhiyun ASC_PDMIXM_ENABLE | ASC_PDPAM_ENABLE);
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R17, VOLUME_CODEC_PA |
383*4882a593Smuzhiyun ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
384*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R18, VOLUME_CODEC_PA |
385*4882a593Smuzhiyun ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
386*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R04, ASC_INT_ACTIVE_L |
387*4882a593Smuzhiyun ASC_INT_ACTIVE_R | ASC_SIDETONE_L_OFF |
388*4882a593Smuzhiyun ASC_SIDETONE_R_OFF);
389*4882a593Smuzhiyun snd_soc_component_write(component, ACCELCODEC_R19, 0x7F);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
rk1000_codec_suspend(struct snd_soc_component * component)392*4882a593Smuzhiyun static int rk1000_codec_suspend(struct snd_soc_component *component)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun spk_ctrl_fun(component, GPIO_LOW);
395*4882a593Smuzhiyun rk1000_codec_set_bias_level(component, SND_SOC_BIAS_OFF);
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun return 0;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
rk1000_codec_resume(struct snd_soc_component * component)400*4882a593Smuzhiyun static int rk1000_codec_resume(struct snd_soc_component *component)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun rk1000_codec_set_bias_level(component, SND_SOC_BIAS_PREPARE);
403*4882a593Smuzhiyun spk_ctrl_fun(component, GPIO_HIGH);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun return 0;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
rk1000_codec_probe(struct snd_soc_component * component)408*4882a593Smuzhiyun static int rk1000_codec_probe(struct snd_soc_component *component)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000_codec;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun rk1000_codec = snd_soc_component_get_drvdata(component);
413*4882a593Smuzhiyun rk1000_codec->component = component;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk1000_codec->pa_delayed_work,
416*4882a593Smuzhiyun pa_delayedwork);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun rk1000_codec_set_bias_level(component, SND_SOC_BIAS_PREPARE);
419*4882a593Smuzhiyun schedule_delayed_work(&rk1000_codec->pa_delayed_work,
420*4882a593Smuzhiyun msecs_to_jiffies(rk1000_codec->pa_enable_time));
421*4882a593Smuzhiyun rk1000_codec_reg_init(component);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
rk1000_codec_remove(struct snd_soc_component * component)426*4882a593Smuzhiyun static void rk1000_codec_remove(struct snd_soc_component *component)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun rk1000_codec_set_bias_level(component, SND_SOC_BIAS_OFF);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rk1000_codec = {
432*4882a593Smuzhiyun .probe = rk1000_codec_probe,
433*4882a593Smuzhiyun .remove = rk1000_codec_remove,
434*4882a593Smuzhiyun .suspend = rk1000_codec_suspend,
435*4882a593Smuzhiyun .resume = rk1000_codec_resume,
436*4882a593Smuzhiyun .set_bias_level = rk1000_codec_set_bias_level,
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun
rk1000_reg_write(void * context,unsigned int reg,unsigned int value)439*4882a593Smuzhiyun static int rk1000_reg_write(void *context, unsigned int reg,
440*4882a593Smuzhiyun unsigned int value)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun struct i2c_client *i2c = context;
443*4882a593Smuzhiyun struct i2c_msg msg;
444*4882a593Smuzhiyun u8 buf;
445*4882a593Smuzhiyun int ret;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun buf = value;
448*4882a593Smuzhiyun msg.addr = i2c->addr | reg;
449*4882a593Smuzhiyun msg.flags = i2c->flags & I2C_M_TEN;
450*4882a593Smuzhiyun msg.len = 1;
451*4882a593Smuzhiyun msg.buf = &buf;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun ret = i2c_transfer(i2c->adapter, &msg, 1);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun return (ret == 1) ? 0 : ret;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
rk1000_reg_read(void * context,unsigned int reg,unsigned int * value)458*4882a593Smuzhiyun static int rk1000_reg_read(void *context, unsigned int reg,
459*4882a593Smuzhiyun unsigned int *value)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct i2c_client *i2c = context;
462*4882a593Smuzhiyun struct i2c_msg msg;
463*4882a593Smuzhiyun u8 buf;
464*4882a593Smuzhiyun int ret;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun msg.addr = i2c->addr | reg;
467*4882a593Smuzhiyun msg.flags = I2C_M_RD;
468*4882a593Smuzhiyun msg.len = 1;
469*4882a593Smuzhiyun msg.buf = &buf;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun ret = i2c_transfer(i2c->adapter, &msg, 1);
472*4882a593Smuzhiyun if (ret != 1)
473*4882a593Smuzhiyun return ret;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun *value = buf;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun return 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static const struct regmap_config rk1000_codec_regmap = {
481*4882a593Smuzhiyun .reg_bits = 8,
482*4882a593Smuzhiyun .val_bits = 8,
483*4882a593Smuzhiyun .reg_write = rk1000_reg_write,
484*4882a593Smuzhiyun .reg_read = rk1000_reg_read,
485*4882a593Smuzhiyun .max_register = ACCELCODEC_R1F,
486*4882a593Smuzhiyun .cache_type = REGCACHE_FLAT,
487*4882a593Smuzhiyun .reg_defaults = rk1000_codec_reg,
488*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(rk1000_codec_reg),
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun static const struct regmap_config rk1000_ctl_regmap = {
492*4882a593Smuzhiyun .reg_bits = 8,
493*4882a593Smuzhiyun .val_bits = 8,
494*4882a593Smuzhiyun .max_register = CODEC_CON,
495*4882a593Smuzhiyun .cache_type = REGCACHE_FLAT,
496*4882a593Smuzhiyun };
497*4882a593Smuzhiyun
rk1000_codec_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)498*4882a593Smuzhiyun static int rk1000_codec_i2c_probe(struct i2c_client *i2c,
499*4882a593Smuzhiyun const struct i2c_device_id *id)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000;
502*4882a593Smuzhiyun struct device_node *np = i2c->dev.of_node;
503*4882a593Smuzhiyun struct device_node *ctl;
504*4882a593Smuzhiyun struct i2c_client *ctl_client;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun rk1000 = devm_kzalloc(&i2c->dev, sizeof(*rk1000), GFP_KERNEL);
507*4882a593Smuzhiyun if (!rk1000)
508*4882a593Smuzhiyun return -ENOMEM;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun i2c_set_clientdata(i2c, rk1000);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun of_property_read_u32(np, "rockchip,pa-en-time-ms",
513*4882a593Smuzhiyun &rk1000->pa_enable_time);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun rk1000->spk_en_gpio = devm_gpiod_get_optional(&i2c->dev, "rockchip,spk-en",
516*4882a593Smuzhiyun GPIOD_OUT_LOW);
517*4882a593Smuzhiyun if (IS_ERR(rk1000->spk_en_gpio))
518*4882a593Smuzhiyun return PTR_ERR(rk1000->spk_en_gpio);
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun ctl = of_parse_phandle(np, "rockchip,ctl", 0);
521*4882a593Smuzhiyun if (!ctl)
522*4882a593Smuzhiyun return -EINVAL;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun ctl_client = of_find_i2c_device_by_node(ctl);
525*4882a593Smuzhiyun if (!ctl_client) {
526*4882a593Smuzhiyun dev_err(&i2c->dev, "can't find control client\n");
527*4882a593Smuzhiyun return -EPROBE_DEFER;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun rk1000->regmap = devm_regmap_init(&i2c->dev, NULL,
531*4882a593Smuzhiyun i2c, &rk1000_codec_regmap);
532*4882a593Smuzhiyun if (IS_ERR(rk1000->regmap))
533*4882a593Smuzhiyun return PTR_ERR(rk1000->regmap);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun rk1000->ctlmap = devm_regmap_init_i2c(ctl_client,
536*4882a593Smuzhiyun &rk1000_ctl_regmap);
537*4882a593Smuzhiyun if (IS_ERR(rk1000->ctlmap))
538*4882a593Smuzhiyun return PTR_ERR(rk1000->ctlmap);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun regmap_write(rk1000->ctlmap, CODEC_CON, CODEC_ON);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun return devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_rk1000_codec,
543*4882a593Smuzhiyun rk1000_codec_dai,
544*4882a593Smuzhiyun ARRAY_SIZE(rk1000_codec_dai));
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
rk1000_codec_i2c_remove(struct i2c_client * i2c)547*4882a593Smuzhiyun static int rk1000_codec_i2c_remove(struct i2c_client *i2c)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun struct rk1000_codec_priv *rk1000 = i2c_get_clientdata(i2c);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun regmap_write(rk1000->ctlmap, CODEC_CON, CODEC_OFF);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun return 0;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun static const struct i2c_device_id rk1000_codec_i2c_id[] = {
557*4882a593Smuzhiyun { "rk1000_codec", 0 },
558*4882a593Smuzhiyun { }
559*4882a593Smuzhiyun };
560*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, rk1000_codec_i2c_id);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun static const struct of_device_id rk1000_codec_of_match[] = {
563*4882a593Smuzhiyun { .compatible = "rockchip,rk1000-codec", },
564*4882a593Smuzhiyun {},
565*4882a593Smuzhiyun };
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun static struct i2c_driver rk1000_codec_i2c_driver = {
568*4882a593Smuzhiyun .driver = {
569*4882a593Smuzhiyun .name = "rk1000_codec",
570*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk1000_codec_of_match),
571*4882a593Smuzhiyun },
572*4882a593Smuzhiyun .probe = rk1000_codec_i2c_probe,
573*4882a593Smuzhiyun .remove = rk1000_codec_i2c_remove,
574*4882a593Smuzhiyun .id_table = rk1000_codec_i2c_id,
575*4882a593Smuzhiyun };
576*4882a593Smuzhiyun module_i2c_driver(rk1000_codec_i2c_driver);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip RK1000 CODEC driver");
579*4882a593Smuzhiyun MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
580*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
581