1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
5*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
6*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
7*4882a593Smuzhiyun * (at your option) any later version.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
10*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*4882a593Smuzhiyun * GNU General Public License for more details.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/clk.h>
16*4882a593Smuzhiyun #include <linux/device.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/mfd/rk808.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun #include <linux/of_gpio.h>
22*4882a593Smuzhiyun #include <linux/platform_device.h>
23*4882a593Smuzhiyun #include <linux/regmap.h>
24*4882a593Smuzhiyun #include <sound/core.h>
25*4882a593Smuzhiyun #include <sound/pcm_params.h>
26*4882a593Smuzhiyun #include <sound/soc.h>
27*4882a593Smuzhiyun #include "rk817_codec.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #ifdef CONFIG_SND_DEBUG
30*4882a593Smuzhiyun #define DBG(args...) pr_info(args)
31*4882a593Smuzhiyun #else
32*4882a593Smuzhiyun #define DBG(args...)
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* For route */
36*4882a593Smuzhiyun #define RK817_CODEC_PLAYBACK 1
37*4882a593Smuzhiyun #define RK817_CODEC_CAPTURE 2
38*4882a593Smuzhiyun #define RK817_CODEC_INCALL 4
39*4882a593Smuzhiyun #define RK817_CODEC_ALL (RK817_CODEC_PLAYBACK |\
40*4882a593Smuzhiyun RK817_CODEC_CAPTURE | RK817_CODEC_INCALL)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * DDAC L/R volume setting
44*4882a593Smuzhiyun * 0db~-95db,0.375db/step,for example:
45*4882a593Smuzhiyun * 0: 0dB
46*4882a593Smuzhiyun * 0x0a: -3.75dB
47*4882a593Smuzhiyun * 0x7d: -46dB
48*4882a593Smuzhiyun * 0xff: -95dB
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun #define OUT_VOLUME (0x03)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * DADC L/R volume setting
54*4882a593Smuzhiyun * 0db~-95db,0.375db/step,for example:
55*4882a593Smuzhiyun * 0: 0dB
56*4882a593Smuzhiyun * 0x0a: -3.75dB
57*4882a593Smuzhiyun * 0x7d: -46dB
58*4882a593Smuzhiyun * 0xff: -95dB
59*4882a593Smuzhiyun */
60*4882a593Smuzhiyun #define CAPTURE_VOLUME (0x0)
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define CODEC_SET_SPK 1
63*4882a593Smuzhiyun #define CODEC_SET_HP 2
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun struct rk817_codec_priv {
66*4882a593Smuzhiyun struct snd_soc_component *component;
67*4882a593Smuzhiyun struct regmap *regmap;
68*4882a593Smuzhiyun struct rk808 *rk817;
69*4882a593Smuzhiyun struct clk *mclk;
70*4882a593Smuzhiyun struct mutex clk_lock;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun unsigned int clk_capture;
73*4882a593Smuzhiyun unsigned int clk_playback;
74*4882a593Smuzhiyun unsigned int stereo_sysclk;
75*4882a593Smuzhiyun unsigned int rate;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun unsigned int spk_volume;
78*4882a593Smuzhiyun unsigned int hp_volume;
79*4882a593Smuzhiyun unsigned int capture_volume;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun bool mic_in_differential;
82*4882a593Smuzhiyun bool pdmdata_out_enable;
83*4882a593Smuzhiyun bool use_ext_amplifier;
84*4882a593Smuzhiyun bool adc_for_loopback;
85*4882a593Smuzhiyun bool resume_path;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun bool out_l2spk_r2hp;
88*4882a593Smuzhiyun long int playback_path;
89*4882a593Smuzhiyun long int capture_path;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun struct gpio_desc *spk_ctl_gpio;
92*4882a593Smuzhiyun struct gpio_desc *hp_ctl_gpio;
93*4882a593Smuzhiyun int spk_mute_delay;
94*4882a593Smuzhiyun int hp_mute_delay;
95*4882a593Smuzhiyun int chip_ver;
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun static const struct reg_default rk817_reg_defaults[] = {
99*4882a593Smuzhiyun { RK817_CODEC_DTOP_VUCTL, 0x003 },
100*4882a593Smuzhiyun { RK817_CODEC_DTOP_VUCTIME, 0x00 },
101*4882a593Smuzhiyun { RK817_CODEC_DTOP_LPT_SRST, 0x00 },
102*4882a593Smuzhiyun { RK817_CODEC_DTOP_DIGEN_CLKE, 0x00 },
103*4882a593Smuzhiyun { RK817_CODEC_AREF_RTCFG0, 0x00 },
104*4882a593Smuzhiyun { RK817_CODEC_AREF_RTCFG1, 0x06 },
105*4882a593Smuzhiyun { RK817_CODEC_AADC_CFG0, 0xc8 },
106*4882a593Smuzhiyun { RK817_CODEC_AADC_CFG1, 0x00 },
107*4882a593Smuzhiyun { RK817_CODEC_DADC_VOLL, 0x00 },
108*4882a593Smuzhiyun { RK817_CODEC_DADC_VOLR, 0x00 },
109*4882a593Smuzhiyun { RK817_CODEC_DADC_SR_ACL0, 0x00 },
110*4882a593Smuzhiyun { RK817_CODEC_DADC_ALC1, 0x00 },
111*4882a593Smuzhiyun { RK817_CODEC_DADC_ALC2, 0x00 },
112*4882a593Smuzhiyun { RK817_CODEC_DADC_NG, 0x00 },
113*4882a593Smuzhiyun { RK817_CODEC_DADC_HPF, 0x00 },
114*4882a593Smuzhiyun { RK817_CODEC_DADC_RVOLL, 0xff },
115*4882a593Smuzhiyun { RK817_CODEC_DADC_RVOLR, 0xff },
116*4882a593Smuzhiyun { RK817_CODEC_AMIC_CFG0, 0x70 },
117*4882a593Smuzhiyun { RK817_CODEC_AMIC_CFG1, 0x00 },
118*4882a593Smuzhiyun { RK817_CODEC_DMIC_PGA_GAIN, 0x66 },
119*4882a593Smuzhiyun { RK817_CODEC_DMIC_LMT1, 0x00 },
120*4882a593Smuzhiyun { RK817_CODEC_DMIC_LMT2, 0x00 },
121*4882a593Smuzhiyun { RK817_CODEC_DMIC_NG1, 0x00 },
122*4882a593Smuzhiyun { RK817_CODEC_DMIC_NG2, 0x00 },
123*4882a593Smuzhiyun { RK817_CODEC_ADAC_CFG0, 0x00 },
124*4882a593Smuzhiyun { RK817_CODEC_ADAC_CFG1, 0x07 },
125*4882a593Smuzhiyun { RK817_CODEC_DDAC_POPD_DACST, 0x82 },
126*4882a593Smuzhiyun { RK817_CODEC_DDAC_VOLL, 0x00 },
127*4882a593Smuzhiyun { RK817_CODEC_DDAC_VOLR, 0x00 },
128*4882a593Smuzhiyun { RK817_CODEC_DDAC_SR_LMT0, 0x00 },
129*4882a593Smuzhiyun { RK817_CODEC_DDAC_LMT1, 0x00 },
130*4882a593Smuzhiyun { RK817_CODEC_DDAC_LMT2, 0x00 },
131*4882a593Smuzhiyun { RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa0 },
132*4882a593Smuzhiyun { RK817_CODEC_DDAC_RVOLL, 0xff },
133*4882a593Smuzhiyun { RK817_CODEC_DDAC_RVOLR, 0xff },
134*4882a593Smuzhiyun { RK817_CODEC_AHP_ANTI0, 0x00 },
135*4882a593Smuzhiyun { RK817_CODEC_AHP_ANTI1, 0x00 },
136*4882a593Smuzhiyun { RK817_CODEC_AHP_CFG0, 0xe0 },
137*4882a593Smuzhiyun { RK817_CODEC_AHP_CFG1, 0x1f },
138*4882a593Smuzhiyun { RK817_CODEC_AHP_CP, 0x09 },
139*4882a593Smuzhiyun { RK817_CODEC_ACLASSD_CFG1, 0x69 },
140*4882a593Smuzhiyun { RK817_CODEC_ACLASSD_CFG2, 0x44 },
141*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG0, 0x04 },
142*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG1, 0x00 },
143*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG2, 0x30 },
144*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG3, 0x19 },
145*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG4, 0x65 },
146*4882a593Smuzhiyun { RK817_CODEC_APLL_CFG5, 0x01 },
147*4882a593Smuzhiyun { RK817_CODEC_DI2S_CKM, 0x01 },
148*4882a593Smuzhiyun { RK817_CODEC_DI2S_RSD, 0x00 },
149*4882a593Smuzhiyun { RK817_CODEC_DI2S_RXCR1, 0x00 },
150*4882a593Smuzhiyun { RK817_CODEC_DI2S_RXCR2, 0x17 },
151*4882a593Smuzhiyun { RK817_CODEC_DI2S_RXCMD_TSD, 0x00 },
152*4882a593Smuzhiyun { RK817_CODEC_DI2S_TXCR1, 0x00 },
153*4882a593Smuzhiyun { RK817_CODEC_DI2S_TXCR2, 0x17 },
154*4882a593Smuzhiyun { RK817_CODEC_DI2S_TXCR3_TXCMD, 0x00 },
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun
rk817_volatile_register(struct device * dev,unsigned int reg)157*4882a593Smuzhiyun static bool rk817_volatile_register(struct device *dev, unsigned int reg)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun switch (reg) {
160*4882a593Smuzhiyun case RK817_CODEC_DTOP_LPT_SRST:
161*4882a593Smuzhiyun case RK817_PMIC_CHIP_NAME:
162*4882a593Smuzhiyun case RK817_PMIC_CHIP_VER:
163*4882a593Smuzhiyun return true;
164*4882a593Smuzhiyun default:
165*4882a593Smuzhiyun return false;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
rk817_codec_register(struct device * dev,unsigned int reg)169*4882a593Smuzhiyun static bool rk817_codec_register(struct device *dev, unsigned int reg)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun switch (reg) {
172*4882a593Smuzhiyun case RK817_CODEC_DTOP_VUCTL:
173*4882a593Smuzhiyun case RK817_CODEC_DTOP_VUCTIME:
174*4882a593Smuzhiyun case RK817_CODEC_DTOP_LPT_SRST:
175*4882a593Smuzhiyun case RK817_CODEC_DTOP_DIGEN_CLKE:
176*4882a593Smuzhiyun case RK817_CODEC_AREF_RTCFG0:
177*4882a593Smuzhiyun case RK817_CODEC_AREF_RTCFG1:
178*4882a593Smuzhiyun case RK817_CODEC_AADC_CFG0:
179*4882a593Smuzhiyun case RK817_CODEC_AADC_CFG1:
180*4882a593Smuzhiyun case RK817_CODEC_DADC_VOLL:
181*4882a593Smuzhiyun case RK817_CODEC_DADC_VOLR:
182*4882a593Smuzhiyun case RK817_CODEC_DADC_SR_ACL0:
183*4882a593Smuzhiyun case RK817_CODEC_DADC_ALC1:
184*4882a593Smuzhiyun case RK817_CODEC_DADC_ALC2:
185*4882a593Smuzhiyun case RK817_CODEC_DADC_NG:
186*4882a593Smuzhiyun case RK817_CODEC_DADC_HPF:
187*4882a593Smuzhiyun case RK817_CODEC_DADC_RVOLL:
188*4882a593Smuzhiyun case RK817_CODEC_DADC_RVOLR:
189*4882a593Smuzhiyun case RK817_CODEC_AMIC_CFG0:
190*4882a593Smuzhiyun case RK817_CODEC_AMIC_CFG1:
191*4882a593Smuzhiyun case RK817_CODEC_DMIC_PGA_GAIN:
192*4882a593Smuzhiyun case RK817_CODEC_DMIC_LMT1:
193*4882a593Smuzhiyun case RK817_CODEC_DMIC_LMT2:
194*4882a593Smuzhiyun case RK817_CODEC_DMIC_NG1:
195*4882a593Smuzhiyun case RK817_CODEC_DMIC_NG2:
196*4882a593Smuzhiyun case RK817_CODEC_ADAC_CFG0:
197*4882a593Smuzhiyun case RK817_CODEC_ADAC_CFG1:
198*4882a593Smuzhiyun case RK817_CODEC_DDAC_POPD_DACST:
199*4882a593Smuzhiyun case RK817_CODEC_DDAC_VOLL:
200*4882a593Smuzhiyun case RK817_CODEC_DDAC_VOLR:
201*4882a593Smuzhiyun case RK817_CODEC_DDAC_SR_LMT0:
202*4882a593Smuzhiyun case RK817_CODEC_DDAC_LMT1:
203*4882a593Smuzhiyun case RK817_CODEC_DDAC_LMT2:
204*4882a593Smuzhiyun case RK817_CODEC_DDAC_MUTE_MIXCTL:
205*4882a593Smuzhiyun case RK817_CODEC_DDAC_RVOLL:
206*4882a593Smuzhiyun case RK817_CODEC_DDAC_RVOLR:
207*4882a593Smuzhiyun case RK817_CODEC_AHP_ANTI0:
208*4882a593Smuzhiyun case RK817_CODEC_AHP_ANTI1:
209*4882a593Smuzhiyun case RK817_CODEC_AHP_CFG0:
210*4882a593Smuzhiyun case RK817_CODEC_AHP_CFG1:
211*4882a593Smuzhiyun case RK817_CODEC_AHP_CP:
212*4882a593Smuzhiyun case RK817_CODEC_ACLASSD_CFG1:
213*4882a593Smuzhiyun case RK817_CODEC_ACLASSD_CFG2:
214*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG0:
215*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG1:
216*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG2:
217*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG3:
218*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG4:
219*4882a593Smuzhiyun case RK817_CODEC_APLL_CFG5:
220*4882a593Smuzhiyun case RK817_CODEC_DI2S_CKM:
221*4882a593Smuzhiyun case RK817_CODEC_DI2S_RSD:
222*4882a593Smuzhiyun case RK817_CODEC_DI2S_RXCR1:
223*4882a593Smuzhiyun case RK817_CODEC_DI2S_RXCR2:
224*4882a593Smuzhiyun case RK817_CODEC_DI2S_RXCMD_TSD:
225*4882a593Smuzhiyun case RK817_CODEC_DI2S_TXCR1:
226*4882a593Smuzhiyun case RK817_CODEC_DI2S_TXCR2:
227*4882a593Smuzhiyun case RK817_CODEC_DI2S_TXCR3_TXCMD:
228*4882a593Smuzhiyun case RK817_PMIC_CHIP_NAME:
229*4882a593Smuzhiyun case RK817_PMIC_CHIP_VER:
230*4882a593Smuzhiyun return true;
231*4882a593Smuzhiyun default:
232*4882a593Smuzhiyun return false;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
rk817_codec_ctl_gpio(struct rk817_codec_priv * rk817,int gpio,int level)236*4882a593Smuzhiyun static int rk817_codec_ctl_gpio(struct rk817_codec_priv *rk817,
237*4882a593Smuzhiyun int gpio, int level)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun if ((gpio & CODEC_SET_SPK) &&
240*4882a593Smuzhiyun rk817->spk_ctl_gpio) {
241*4882a593Smuzhiyun gpiod_set_value(rk817->spk_ctl_gpio, level);
242*4882a593Smuzhiyun DBG("%s set spk clt %d\n", __func__, level);
243*4882a593Smuzhiyun msleep(rk817->spk_mute_delay);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if ((gpio & CODEC_SET_HP) &&
247*4882a593Smuzhiyun rk817->hp_ctl_gpio) {
248*4882a593Smuzhiyun gpiod_set_value(rk817->hp_ctl_gpio, level);
249*4882a593Smuzhiyun DBG("%s set hp clt %d\n", __func__, level);
250*4882a593Smuzhiyun msleep(rk817->hp_mute_delay);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun return 0;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
rk817_reset(struct snd_soc_component * component)256*4882a593Smuzhiyun static int rk817_reset(struct snd_soc_component *component)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DTOP_LPT_SRST, 0x40);
261*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_POPD_DACST, 0x02);
262*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DI2S_CKM, 0x00);
263*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DTOP_DIGEN_CLKE, 0xff);
264*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG1, 0x58);
265*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG2, 0x2d);
266*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, 0x0c);
267*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG5, 0x00);
268*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00);
269*4882a593Smuzhiyun if (rk817->chip_ver <= 0x4) {
270*4882a593Smuzhiyun DBG("%s (%d): SMIC TudorAG and previous versions\n",
271*4882a593Smuzhiyun __func__, __LINE__);
272*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c);
273*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95);
274*4882a593Smuzhiyun } else {
275*4882a593Smuzhiyun DBG("%s (%d): SMIC TudorAG version later\n",
276*4882a593Smuzhiyun __func__, __LINE__);
277*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04);
278*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun return 0;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun static struct rk817_reg_val_typ playback_power_up_list[] = {
286*4882a593Smuzhiyun {RK817_CODEC_AREF_RTCFG1, 0x40},
287*4882a593Smuzhiyun {RK817_CODEC_DDAC_POPD_DACST, 0x02},
288*4882a593Smuzhiyun /* APLL */
289*4882a593Smuzhiyun /* {RK817_CODEC_APLL_CFG0, 0x04}, */
290*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG1, 0x58},
291*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG2, 0x2d},
292*4882a593Smuzhiyun /* {RK817_CODEC_APLL_CFG4, 0xa5}, */
293*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG5, 0x00},
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun {RK817_CODEC_DI2S_RXCMD_TSD, 0x00},
296*4882a593Smuzhiyun {RK817_CODEC_DI2S_RSD, 0x00},
297*4882a593Smuzhiyun /* {RK817_CODEC_DI2S_CKM, 0x00}, */
298*4882a593Smuzhiyun {RK817_CODEC_DI2S_RXCR1, 0x00},
299*4882a593Smuzhiyun {RK817_CODEC_DI2S_RXCMD_TSD, 0x20},
300*4882a593Smuzhiyun {RK817_CODEC_DTOP_VUCTIME, 0xf4},
301*4882a593Smuzhiyun {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00},
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun {RK817_CODEC_DDAC_VOLL, 0x0a},
304*4882a593Smuzhiyun {RK817_CODEC_DDAC_VOLR, 0x0a},
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun #define RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN \
308*4882a593Smuzhiyun ARRAY_SIZE(playback_power_up_list)
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun static struct rk817_reg_val_typ playback_power_down_list[] = {
311*4882a593Smuzhiyun {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x01},
312*4882a593Smuzhiyun {RK817_CODEC_ADAC_CFG1, 0x0f},
313*4882a593Smuzhiyun /* HP */
314*4882a593Smuzhiyun {RK817_CODEC_AHP_CFG0, 0xe0},
315*4882a593Smuzhiyun {RK817_CODEC_AHP_CP, 0x09},
316*4882a593Smuzhiyun /* SPK */
317*4882a593Smuzhiyun {RK817_CODEC_ACLASSD_CFG1, 0x69},
318*4882a593Smuzhiyun };
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun #define RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN \
321*4882a593Smuzhiyun ARRAY_SIZE(playback_power_down_list)
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun static struct rk817_reg_val_typ capture_power_up_list[] = {
324*4882a593Smuzhiyun {RK817_CODEC_AREF_RTCFG1, 0x40},
325*4882a593Smuzhiyun {RK817_CODEC_DADC_SR_ACL0, 0x02},
326*4882a593Smuzhiyun /* {RK817_CODEC_DTOP_DIGEN_CLKE, 0xff}, */
327*4882a593Smuzhiyun /* {RK817_CODEC_APLL_CFG0, 0x04}, */
328*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG1, 0x58},
329*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG2, 0x2d},
330*4882a593Smuzhiyun /* {RK817_CODEC_APLL_CFG4, 0xa5}, */
331*4882a593Smuzhiyun {RK817_CODEC_APLL_CFG5, 0x00},
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /*{RK817_CODEC_DI2S_RXCMD_TSD, 0x00},*/
334*4882a593Smuzhiyun {RK817_CODEC_DI2S_RSD, 0x00},
335*4882a593Smuzhiyun /* {RK817_CODEC_DI2S_CKM, 0x00}, */
336*4882a593Smuzhiyun {RK817_CODEC_DI2S_RXCR1, 0x00},
337*4882a593Smuzhiyun {RK817_CODEC_DI2S_RXCMD_TSD, 0x20},
338*4882a593Smuzhiyun {RK817_CODEC_DTOP_VUCTIME, 0xf4},
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00},
341*4882a593Smuzhiyun {RK817_CODEC_AADC_CFG0, 0x00},
342*4882a593Smuzhiyun {RK817_CODEC_AMIC_CFG0, 0x0a},
343*4882a593Smuzhiyun {RK817_CODEC_AMIC_CFG1, 0x30},
344*4882a593Smuzhiyun {RK817_CODEC_DI2S_TXCR3_TXCMD, 0x88},
345*4882a593Smuzhiyun {RK817_CODEC_DDAC_POPD_DACST, 0x02},
346*4882a593Smuzhiyun /* 0x29: -18db to 27db */
347*4882a593Smuzhiyun {RK817_CODEC_DMIC_PGA_GAIN, 0xaa},
348*4882a593Smuzhiyun };
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun #define RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN \
351*4882a593Smuzhiyun ARRAY_SIZE(capture_power_up_list)
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun static struct rk817_reg_val_typ capture_power_down_list[] = {
354*4882a593Smuzhiyun {RK817_CODEC_AADC_CFG0, 0xc8},
355*4882a593Smuzhiyun {RK817_CODEC_AMIC_CFG0, 0x70},
356*4882a593Smuzhiyun };
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun #define RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN \
359*4882a593Smuzhiyun ARRAY_SIZE(capture_power_down_list)
360*4882a593Smuzhiyun
rk817_codec_power_up(struct snd_soc_component * component,int type)361*4882a593Smuzhiyun static int rk817_codec_power_up(struct snd_soc_component *component, int type)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
364*4882a593Smuzhiyun int i;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun DBG("%s : power up %s %s %s\n", __func__,
367*4882a593Smuzhiyun type & RK817_CODEC_PLAYBACK ? "playback" : "",
368*4882a593Smuzhiyun type & RK817_CODEC_CAPTURE ? "capture" : "",
369*4882a593Smuzhiyun type & RK817_CODEC_INCALL ? "incall" : "");
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (type & RK817_CODEC_PLAYBACK) {
372*4882a593Smuzhiyun snd_soc_component_update_bits(component,
373*4882a593Smuzhiyun RK817_CODEC_DTOP_DIGEN_CLKE,
374*4882a593Smuzhiyun DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN);
375*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) {
376*4882a593Smuzhiyun snd_soc_component_write(component,
377*4882a593Smuzhiyun playback_power_up_list[i].reg,
378*4882a593Smuzhiyun playback_power_up_list[i].value);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* configure APLL CFG0/4 */
382*4882a593Smuzhiyun if (rk817->chip_ver <= 0x4) {
383*4882a593Smuzhiyun DBG("%s (%d): SMIC TudorAG and previous versions\n",
384*4882a593Smuzhiyun __func__, __LINE__);
385*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c);
386*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95);
387*4882a593Smuzhiyun } else {
388*4882a593Smuzhiyun DBG("%s: SMIC TudorAG version later\n", __func__);
389*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04);
390*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
394*4882a593Smuzhiyun DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS);
395*4882a593Smuzhiyun usleep_range(2000, 2500);
396*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
397*4882a593Smuzhiyun DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN);
398*4882a593Smuzhiyun DBG("%s: %d - Playback DIG CLK OPS\n", __func__, __LINE__);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun if (type & RK817_CODEC_CAPTURE) {
402*4882a593Smuzhiyun snd_soc_component_update_bits(component,
403*4882a593Smuzhiyun RK817_CODEC_DTOP_DIGEN_CLKE,
404*4882a593Smuzhiyun ADC_DIG_CLK_MASK,
405*4882a593Smuzhiyun ADC_DIG_CLK_EN);
406*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) {
407*4882a593Smuzhiyun snd_soc_component_write(component,
408*4882a593Smuzhiyun capture_power_up_list[i].reg,
409*4882a593Smuzhiyun capture_power_up_list[i].value);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* configure APLL CFG0/4 */
413*4882a593Smuzhiyun if (rk817->chip_ver <= 0x4) {
414*4882a593Smuzhiyun DBG("%s (%d): SMIC TudorAG and previous versions\n",
415*4882a593Smuzhiyun __func__, __LINE__);
416*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c);
417*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95);
418*4882a593Smuzhiyun } else {
419*4882a593Smuzhiyun DBG("%s: SMIC TudorAG version later\n", __func__);
420*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04);
421*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
425*4882a593Smuzhiyun ADC_DIG_CLK_MASK, DAC_DIG_CLK_DIS);
426*4882a593Smuzhiyun usleep_range(2000, 2500);
427*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
428*4882a593Smuzhiyun ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN);
429*4882a593Smuzhiyun DBG("%s: %d - Capture DIG CLK OPS\n", __func__, __LINE__);
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (rk817->mic_in_differential)
432*4882a593Smuzhiyun snd_soc_component_update_bits(component,
433*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
434*4882a593Smuzhiyun MIC_DIFF_MASK, MIC_DIFF_EN);
435*4882a593Smuzhiyun else
436*4882a593Smuzhiyun snd_soc_component_update_bits(component,
437*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
438*4882a593Smuzhiyun MIC_DIFF_MASK,
439*4882a593Smuzhiyun MIC_DIFF_DIS);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun if (rk817->pdmdata_out_enable)
442*4882a593Smuzhiyun snd_soc_component_update_bits(component,
443*4882a593Smuzhiyun RK817_CODEC_DI2S_CKM,
444*4882a593Smuzhiyun PDM_EN_MASK,
445*4882a593Smuzhiyun PDM_EN_ENABLE);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DADC_VOLL,
448*4882a593Smuzhiyun rk817->capture_volume);
449*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DADC_VOLR,
450*4882a593Smuzhiyun rk817->capture_volume);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun return 0;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
rk817_codec_power_down(struct snd_soc_component * component,int type)456*4882a593Smuzhiyun static int rk817_codec_power_down(struct snd_soc_component *component, int type)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun int i;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun DBG("%s : power down %s %s %s\n", __func__,
461*4882a593Smuzhiyun type & RK817_CODEC_PLAYBACK ? "playback" : "",
462*4882a593Smuzhiyun type & RK817_CODEC_CAPTURE ? "capture" : "",
463*4882a593Smuzhiyun type & RK817_CODEC_INCALL ? "incall" : "");
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /* mute output for pop noise */
466*4882a593Smuzhiyun if ((type & RK817_CODEC_PLAYBACK) ||
467*4882a593Smuzhiyun (type & RK817_CODEC_INCALL)) {
468*4882a593Smuzhiyun snd_soc_component_update_bits(component,
469*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
470*4882a593Smuzhiyun DACMT_ENABLE, DACMT_ENABLE);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (type & RK817_CODEC_CAPTURE) {
474*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) {
475*4882a593Smuzhiyun snd_soc_component_write(component,
476*4882a593Smuzhiyun capture_power_down_list[i].reg,
477*4882a593Smuzhiyun capture_power_down_list[i].value);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
480*4882a593Smuzhiyun ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS);
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun if (type & RK817_CODEC_PLAYBACK) {
484*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) {
485*4882a593Smuzhiyun snd_soc_component_write(component,
486*4882a593Smuzhiyun playback_power_down_list[i].reg,
487*4882a593Smuzhiyun playback_power_down_list[i].value);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun snd_soc_component_update_bits(component,
490*4882a593Smuzhiyun RK817_CODEC_DTOP_DIGEN_CLKE,
491*4882a593Smuzhiyun DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun if (type == RK817_CODEC_ALL) {
495*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) {
496*4882a593Smuzhiyun snd_soc_component_write(component,
497*4882a593Smuzhiyun playback_power_down_list[i].reg,
498*4882a593Smuzhiyun playback_power_down_list[i].value);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun for (i = 0; i < RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) {
501*4882a593Smuzhiyun snd_soc_component_write(component,
502*4882a593Smuzhiyun capture_power_down_list[i].reg,
503*4882a593Smuzhiyun capture_power_down_list[i].value);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00);
506*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG5, 0x01);
507*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AREF_RTCFG1, 0x06);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun return 0;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /* For tiny alsa playback/capture/voice call path */
514*4882a593Smuzhiyun static const char * const rk817_playback_path_mode[] = {
515*4882a593Smuzhiyun "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", /* 0-6 */
516*4882a593Smuzhiyun "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"}; /* 7-10 */
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun static const char * const rk817_capture_path_mode[] = {
519*4882a593Smuzhiyun "MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"};
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun static const char * const rk817_binary_mode[] = {"OFF", "ON"};
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk817_playback_path_type,
524*4882a593Smuzhiyun 0, 0, rk817_playback_path_mode);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk817_capture_path_type,
527*4882a593Smuzhiyun 0, 0, rk817_capture_path_mode);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk817_resume_path_type,
530*4882a593Smuzhiyun 0, 0, rk817_binary_mode);
531*4882a593Smuzhiyun
rk817_playback_path_config(struct snd_soc_component * component,long pre_path,long target_path)532*4882a593Smuzhiyun static int rk817_playback_path_config(struct snd_soc_component *component,
533*4882a593Smuzhiyun long pre_path, long target_path)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun rk817->playback_path = target_path;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun DBG("%s : set playback_path %ld, pre_path %ld\n",
540*4882a593Smuzhiyun __func__, rk817->playback_path, pre_path);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun mutex_lock(&rk817->clk_lock);
543*4882a593Smuzhiyun if (rk817->playback_path != OFF) {
544*4882a593Smuzhiyun if (rk817->clk_playback == 0) {
545*4882a593Smuzhiyun clk_prepare_enable(rk817->mclk);
546*4882a593Smuzhiyun rk817->clk_playback++;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun } else {
549*4882a593Smuzhiyun if (rk817->clk_playback > 0) {
550*4882a593Smuzhiyun clk_disable_unprepare(rk817->mclk);
551*4882a593Smuzhiyun rk817->clk_playback--;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun mutex_unlock(&rk817->clk_lock);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun switch (rk817->playback_path) {
557*4882a593Smuzhiyun case OFF:
558*4882a593Smuzhiyun if (pre_path != OFF && (pre_path != HP_PATH &&
559*4882a593Smuzhiyun pre_path != HP_NO_MIC && pre_path != RING_HP &&
560*4882a593Smuzhiyun pre_path != RING_HP_NO_MIC)) {
561*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_PLAYBACK);
562*4882a593Smuzhiyun if (rk817->capture_path == 0)
563*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_ALL);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun break;
566*4882a593Smuzhiyun case RCV:
567*4882a593Smuzhiyun case SPK_PATH:
568*4882a593Smuzhiyun case RING_SPK:
569*4882a593Smuzhiyun if (pre_path == OFF)
570*4882a593Smuzhiyun rk817_codec_power_up(component, RK817_CODEC_PLAYBACK);
571*4882a593Smuzhiyun if (rk817->out_l2spk_r2hp) {
572*4882a593Smuzhiyun /* for costdown: ldac -> ClassD rdac -> Hp */
573*4882a593Smuzhiyun /* HP_CP_EN , CP 2.3V */
574*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CP,
575*4882a593Smuzhiyun 0x11);
576*4882a593Smuzhiyun /* power on HP two stage opamp ,HP amplitude 0db */
577*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CFG0,
578*4882a593Smuzhiyun 0x80);
579*4882a593Smuzhiyun /* power on dac ibias/l/r */
580*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
581*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
582*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
583*4882a593Smuzhiyun /* CLASS D mode */
584*4882a593Smuzhiyun snd_soc_component_write(component,
585*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
586*4882a593Smuzhiyun 0x18);
587*4882a593Smuzhiyun /* CLASS D enable */
588*4882a593Smuzhiyun snd_soc_component_write(component,
589*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG1,
590*4882a593Smuzhiyun 0xa5);
591*4882a593Smuzhiyun /* restart CLASS D, OCPP/N */
592*4882a593Smuzhiyun snd_soc_component_write(component,
593*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG2,
594*4882a593Smuzhiyun 0xf7);
595*4882a593Smuzhiyun } else if (!rk817->use_ext_amplifier) {
596*4882a593Smuzhiyun /* power on dac ibias/l/r */
597*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
598*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
599*4882a593Smuzhiyun PWD_DACL_DOWN | PWD_DACR_DOWN);
600*4882a593Smuzhiyun /* CLASS D mode */
601*4882a593Smuzhiyun snd_soc_component_write(component,
602*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
603*4882a593Smuzhiyun 0x10);
604*4882a593Smuzhiyun /* CLASS D enable */
605*4882a593Smuzhiyun snd_soc_component_write(component,
606*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG1,
607*4882a593Smuzhiyun 0xa5);
608*4882a593Smuzhiyun /* restart CLASS D, OCPP/N */
609*4882a593Smuzhiyun snd_soc_component_write(component,
610*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG2,
611*4882a593Smuzhiyun 0xf7);
612*4882a593Smuzhiyun } else {
613*4882a593Smuzhiyun /* HP_CP_EN , CP 2.3V */
614*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CP,
615*4882a593Smuzhiyun 0x11);
616*4882a593Smuzhiyun /* power on HP two stage opamp ,HP amplitude 0db */
617*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CFG0,
618*4882a593Smuzhiyun 0x80);
619*4882a593Smuzhiyun /* power on dac ibias/l/r */
620*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
621*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_DOWN |
622*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
623*4882a593Smuzhiyun snd_soc_component_update_bits(component,
624*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
625*4882a593Smuzhiyun DACMT_ENABLE, DACMT_DISABLE);
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLL,
628*4882a593Smuzhiyun rk817->spk_volume);
629*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLR,
630*4882a593Smuzhiyun rk817->spk_volume);
631*4882a593Smuzhiyun break;
632*4882a593Smuzhiyun case HP_PATH:
633*4882a593Smuzhiyun case HP_NO_MIC:
634*4882a593Smuzhiyun case RING_HP:
635*4882a593Smuzhiyun case RING_HP_NO_MIC:
636*4882a593Smuzhiyun if (pre_path == OFF)
637*4882a593Smuzhiyun rk817_codec_power_up(component, RK817_CODEC_PLAYBACK);
638*4882a593Smuzhiyun /* HP_CP_EN , CP 2.3V */
639*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CP, 0x11);
640*4882a593Smuzhiyun /* power on HP two stage opamp ,HP amplitude 0db */
641*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CFG0, 0x80);
642*4882a593Smuzhiyun /* power on dac ibias/l/r */
643*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
644*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_DOWN |
645*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
646*4882a593Smuzhiyun snd_soc_component_update_bits(component,
647*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
648*4882a593Smuzhiyun DACMT_ENABLE, DACMT_DISABLE);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLL,
651*4882a593Smuzhiyun rk817->hp_volume);
652*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLR,
653*4882a593Smuzhiyun rk817->hp_volume);
654*4882a593Smuzhiyun break;
655*4882a593Smuzhiyun case BT:
656*4882a593Smuzhiyun break;
657*4882a593Smuzhiyun case SPK_HP:
658*4882a593Smuzhiyun case RING_SPK_HP:
659*4882a593Smuzhiyun if (pre_path == OFF)
660*4882a593Smuzhiyun rk817_codec_power_up(component, RK817_CODEC_PLAYBACK);
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun /* HP_CP_EN , CP 2.3V */
663*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CP, 0x11);
664*4882a593Smuzhiyun /* power on HP two stage opamp ,HP amplitude 0db */
665*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_AHP_CFG0, 0x80);
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /* power on dac ibias/l/r */
668*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
669*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
670*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (!rk817->use_ext_amplifier) {
673*4882a593Smuzhiyun /* CLASS D mode */
674*4882a593Smuzhiyun snd_soc_component_write(component,
675*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
676*4882a593Smuzhiyun 0x10);
677*4882a593Smuzhiyun /* CLASS D enable */
678*4882a593Smuzhiyun snd_soc_component_write(component,
679*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG1,
680*4882a593Smuzhiyun 0xa5);
681*4882a593Smuzhiyun /* restart CLASS D, OCPP/N */
682*4882a593Smuzhiyun snd_soc_component_write(component,
683*4882a593Smuzhiyun RK817_CODEC_ACLASSD_CFG2,
684*4882a593Smuzhiyun 0xf7);
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLL,
688*4882a593Smuzhiyun rk817->hp_volume);
689*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DDAC_VOLR,
690*4882a593Smuzhiyun rk817->hp_volume);
691*4882a593Smuzhiyun break;
692*4882a593Smuzhiyun default:
693*4882a593Smuzhiyun return -EINVAL;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun return 0;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
rk817_playback_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)699*4882a593Smuzhiyun static int rk817_playback_path_get(struct snd_kcontrol *kcontrol,
700*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
703*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun DBG("%s : playback_path %ld\n", __func__, rk817->playback_path);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk817->playback_path;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun return 0;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
rk817_playback_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)712*4882a593Smuzhiyun static int rk817_playback_path_put(struct snd_kcontrol *kcontrol,
713*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
716*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (rk817->playback_path == ucontrol->value.integer.value[0]) {
719*4882a593Smuzhiyun DBG("%s : playback_path is not changed!\n",
720*4882a593Smuzhiyun __func__);
721*4882a593Smuzhiyun return 0;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun return rk817_playback_path_config(component, rk817->playback_path,
725*4882a593Smuzhiyun ucontrol->value.integer.value[0]);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
rk817_capture_path_config(struct snd_soc_component * component,long pre_path,long target_path)728*4882a593Smuzhiyun static int rk817_capture_path_config(struct snd_soc_component *component,
729*4882a593Smuzhiyun long pre_path, long target_path)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun rk817->capture_path = target_path;
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun DBG("%s : set capture_path %ld, pre_path %ld\n", __func__,
736*4882a593Smuzhiyun rk817->capture_path, pre_path);
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun mutex_lock(&rk817->clk_lock);
739*4882a593Smuzhiyun if (rk817->capture_path != MIC_OFF) {
740*4882a593Smuzhiyun if (rk817->clk_capture == 0) {
741*4882a593Smuzhiyun clk_prepare_enable(rk817->mclk);
742*4882a593Smuzhiyun rk817->clk_capture++;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun } else {
745*4882a593Smuzhiyun if (rk817->clk_capture > 0) {
746*4882a593Smuzhiyun clk_disable_unprepare(rk817->mclk);
747*4882a593Smuzhiyun rk817->clk_capture--;
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun mutex_unlock(&rk817->clk_lock);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun switch (rk817->capture_path) {
753*4882a593Smuzhiyun case MIC_OFF:
754*4882a593Smuzhiyun if (pre_path != MIC_OFF) {
755*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_CAPTURE);
756*4882a593Smuzhiyun if (rk817->playback_path == OFF)
757*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_ALL);
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun break;
760*4882a593Smuzhiyun case MAIN_MIC:
761*4882a593Smuzhiyun if (pre_path == MIC_OFF)
762*4882a593Smuzhiyun rk817_codec_power_up(component, RK817_CODEC_CAPTURE);
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun if (rk817->adc_for_loopback) {
765*4882a593Smuzhiyun /* don't need to gain when adc use for loopback */
766*4882a593Smuzhiyun snd_soc_component_update_bits(component,
767*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
768*4882a593Smuzhiyun 0xf,
769*4882a593Smuzhiyun 0x0);
770*4882a593Smuzhiyun snd_soc_component_write(component,
771*4882a593Smuzhiyun RK817_CODEC_DMIC_PGA_GAIN,
772*4882a593Smuzhiyun 0x66);
773*4882a593Smuzhiyun snd_soc_component_write(component,
774*4882a593Smuzhiyun RK817_CODEC_DADC_VOLL,
775*4882a593Smuzhiyun 0x00);
776*4882a593Smuzhiyun snd_soc_component_write(component,
777*4882a593Smuzhiyun RK817_CODEC_DADC_VOLR,
778*4882a593Smuzhiyun 0x00);
779*4882a593Smuzhiyun break;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun if (!rk817->mic_in_differential) {
782*4882a593Smuzhiyun snd_soc_component_write(component,
783*4882a593Smuzhiyun RK817_CODEC_DADC_VOLR,
784*4882a593Smuzhiyun 0xff);
785*4882a593Smuzhiyun snd_soc_component_update_bits(component,
786*4882a593Smuzhiyun RK817_CODEC_AADC_CFG0,
787*4882a593Smuzhiyun ADC_R_PWD_MASK,
788*4882a593Smuzhiyun ADC_R_PWD_EN);
789*4882a593Smuzhiyun snd_soc_component_update_bits(component,
790*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
791*4882a593Smuzhiyun PWD_PGA_R_MASK,
792*4882a593Smuzhiyun PWD_PGA_R_EN);
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun break;
795*4882a593Smuzhiyun case HANDS_FREE_MIC:
796*4882a593Smuzhiyun if (pre_path == MIC_OFF)
797*4882a593Smuzhiyun rk817_codec_power_up(component, RK817_CODEC_CAPTURE);
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (rk817->adc_for_loopback) {
800*4882a593Smuzhiyun /* don't need to gain when adc use for loopback */
801*4882a593Smuzhiyun snd_soc_component_update_bits(component,
802*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
803*4882a593Smuzhiyun 0xf,
804*4882a593Smuzhiyun 0x0);
805*4882a593Smuzhiyun snd_soc_component_write(component,
806*4882a593Smuzhiyun RK817_CODEC_DMIC_PGA_GAIN,
807*4882a593Smuzhiyun 0x66);
808*4882a593Smuzhiyun snd_soc_component_write(component,
809*4882a593Smuzhiyun RK817_CODEC_DADC_VOLL,
810*4882a593Smuzhiyun 0x00);
811*4882a593Smuzhiyun snd_soc_component_write(component,
812*4882a593Smuzhiyun RK817_CODEC_DADC_VOLR,
813*4882a593Smuzhiyun 0x00);
814*4882a593Smuzhiyun break;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun if (!rk817->mic_in_differential) {
817*4882a593Smuzhiyun snd_soc_component_write(component,
818*4882a593Smuzhiyun RK817_CODEC_DADC_VOLL,
819*4882a593Smuzhiyun 0xff);
820*4882a593Smuzhiyun snd_soc_component_update_bits(component,
821*4882a593Smuzhiyun RK817_CODEC_AADC_CFG0,
822*4882a593Smuzhiyun ADC_L_PWD_MASK,
823*4882a593Smuzhiyun ADC_L_PWD_EN);
824*4882a593Smuzhiyun snd_soc_component_update_bits(component,
825*4882a593Smuzhiyun RK817_CODEC_AMIC_CFG0,
826*4882a593Smuzhiyun PWD_PGA_L_MASK,
827*4882a593Smuzhiyun PWD_PGA_L_EN);
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun break;
830*4882a593Smuzhiyun case BT_SCO_MIC:
831*4882a593Smuzhiyun break;
832*4882a593Smuzhiyun default:
833*4882a593Smuzhiyun return -EINVAL;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun return 0;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
rk817_capture_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)839*4882a593Smuzhiyun static int rk817_capture_path_get(struct snd_kcontrol *kcontrol,
840*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
843*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun DBG("%s : capture_path %ld\n", __func__,
846*4882a593Smuzhiyun rk817->capture_path);
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk817->capture_path;
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun return 0;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun
rk817_capture_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)853*4882a593Smuzhiyun static int rk817_capture_path_put(struct snd_kcontrol *kcontrol,
854*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
857*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun if (rk817->capture_path == ucontrol->value.integer.value[0]) {
860*4882a593Smuzhiyun DBG("%s : capture_path is not changed!\n",
861*4882a593Smuzhiyun __func__);
862*4882a593Smuzhiyun return 0;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun return rk817_capture_path_config(component, rk817->capture_path,
866*4882a593Smuzhiyun ucontrol->value.integer.value[0]);
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
rk817_resume_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)869*4882a593Smuzhiyun static int rk817_resume_path_get(struct snd_kcontrol *kcontrol,
870*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
871*4882a593Smuzhiyun {
872*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
873*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun DBG("%s : resume_path %ld\n", __func__, rk817->resume_path);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk817->resume_path;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun return 0;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
rk817_resume_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)882*4882a593Smuzhiyun static int rk817_resume_path_put(struct snd_kcontrol *kcontrol,
883*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
884*4882a593Smuzhiyun {
885*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
886*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun rk817->resume_path = ucontrol->value.integer.value[0];
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun return 0;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun static struct snd_kcontrol_new rk817_snd_path_controls[] = {
894*4882a593Smuzhiyun SOC_ENUM_EXT("Playback Path", rk817_playback_path_type,
895*4882a593Smuzhiyun rk817_playback_path_get, rk817_playback_path_put),
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type,
898*4882a593Smuzhiyun rk817_capture_path_get, rk817_capture_path_put),
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun SOC_ENUM_EXT("Resume Path", rk817_resume_path_type,
901*4882a593Smuzhiyun rk817_resume_path_get, rk817_resume_path_put),
902*4882a593Smuzhiyun };
903*4882a593Smuzhiyun
rk817_set_dai_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)904*4882a593Smuzhiyun static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai,
905*4882a593Smuzhiyun int clk_id, unsigned int freq, int dir)
906*4882a593Smuzhiyun {
907*4882a593Smuzhiyun struct snd_soc_component *component = codec_dai->component;
908*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun rk817->stereo_sysclk = freq;
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun DBG("%s : MCLK = %dHz\n", __func__, rk817->stereo_sysclk);
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun return 0;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
rk817_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)917*4882a593Smuzhiyun static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai,
918*4882a593Smuzhiyun unsigned int fmt)
919*4882a593Smuzhiyun {
920*4882a593Smuzhiyun struct snd_soc_component *component = codec_dai->component;
921*4882a593Smuzhiyun unsigned int i2s_mst = 0;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
924*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
925*4882a593Smuzhiyun i2s_mst |= RK817_I2S_MODE_SLV;
926*4882a593Smuzhiyun break;
927*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
928*4882a593Smuzhiyun i2s_mst |= RK817_I2S_MODE_MST;
929*4882a593Smuzhiyun break;
930*4882a593Smuzhiyun default:
931*4882a593Smuzhiyun dev_err(component->dev, "%s : set master mask failed!\n", __func__);
932*4882a593Smuzhiyun return -EINVAL;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun DBG("%s : i2s %s mode\n", __func__, i2s_mst ? "master" : "slave");
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DI2S_CKM,
937*4882a593Smuzhiyun RK817_I2S_MODE_MASK, i2s_mst);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun return 0;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
rk817_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)942*4882a593Smuzhiyun static int rk817_hw_params(struct snd_pcm_substream *substream,
943*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
944*4882a593Smuzhiyun struct snd_soc_dai *dai)
945*4882a593Smuzhiyun {
946*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
947*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
948*4882a593Smuzhiyun unsigned int rate = params_rate(params);
949*4882a593Smuzhiyun unsigned char apll_cfg3_val;
950*4882a593Smuzhiyun unsigned char dtop_digen_sr_lmt0;
951*4882a593Smuzhiyun unsigned char dtop_digen_clke;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun DBG("%s : sample rate = %dHz\n", __func__, rate);
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun if (rk817->chip_ver <= 0x4) {
956*4882a593Smuzhiyun DBG("%s: SMIC TudorAG and previous versions\n", __func__);
957*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c);
958*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95);
959*4882a593Smuzhiyun } else {
960*4882a593Smuzhiyun DBG("%s: SMIC TudorAG version later\n", __func__);
961*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04);
962*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
966*4882a593Smuzhiyun dtop_digen_clke = DAC_DIG_CLK_EN;
967*4882a593Smuzhiyun else
968*4882a593Smuzhiyun dtop_digen_clke = ADC_DIG_CLK_EN;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun switch (rate) {
971*4882a593Smuzhiyun case 8000:
972*4882a593Smuzhiyun apll_cfg3_val = 0x03;
973*4882a593Smuzhiyun dtop_digen_sr_lmt0 = 0x00;
974*4882a593Smuzhiyun break;
975*4882a593Smuzhiyun case 16000:
976*4882a593Smuzhiyun apll_cfg3_val = 0x06;
977*4882a593Smuzhiyun dtop_digen_sr_lmt0 = 0x01;
978*4882a593Smuzhiyun break;
979*4882a593Smuzhiyun case 96000:
980*4882a593Smuzhiyun apll_cfg3_val = 0x18;
981*4882a593Smuzhiyun dtop_digen_sr_lmt0 = 0x03;
982*4882a593Smuzhiyun break;
983*4882a593Smuzhiyun case 32000:
984*4882a593Smuzhiyun case 44100:
985*4882a593Smuzhiyun case 48000:
986*4882a593Smuzhiyun apll_cfg3_val = 0x0c;
987*4882a593Smuzhiyun dtop_digen_sr_lmt0 = 0x02;
988*4882a593Smuzhiyun break;
989*4882a593Smuzhiyun default:
990*4882a593Smuzhiyun pr_err("Unsupported rate: %d\n", rate);
991*4882a593Smuzhiyun return -EINVAL;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun /**
995*4882a593Smuzhiyun * Note that: If you use the ALSA hooks plugin, entering hw_params()
996*4882a593Smuzhiyun * is before playback/capture_path_put, therefore, we need to configure
997*4882a593Smuzhiyun * APLL_CFG3/DTOP_DIGEN_CLKE/DDAC_SR_LMT0 for different sample rates.
998*4882a593Smuzhiyun */
999*4882a593Smuzhiyun if (!((substream->stream == SNDRV_PCM_STREAM_CAPTURE) && rk817->pdmdata_out_enable)) {
1000*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, apll_cfg3_val);
1001*4882a593Smuzhiyun /* The 0x00 contains ADC_DIG_CLK_DIS and DAC_DIG_CLK_DIS */
1002*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1003*4882a593Smuzhiyun dtop_digen_clke, 0x00);
1004*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DDAC_SR_LMT0,
1005*4882a593Smuzhiyun DACSRT_MASK, dtop_digen_sr_lmt0);
1006*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1007*4882a593Smuzhiyun dtop_digen_clke, dtop_digen_clke);
1008*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5,
1009*4882a593Smuzhiyun PLL_PW_DOWN, PLL_PW_DOWN);
1010*4882a593Smuzhiyun usleep_range(50, 60);
1011*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5,
1012*4882a593Smuzhiyun PLL_PW_DOWN, PLL_PW_UP);
1013*4882a593Smuzhiyun usleep_range(500, 600);
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun switch (params_format(params)) {
1017*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
1018*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
1019*4882a593Smuzhiyun VDW_RX_16BITS);
1020*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
1021*4882a593Smuzhiyun VDW_TX_16BITS);
1022*4882a593Smuzhiyun break;
1023*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
1024*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
1025*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
1026*4882a593Smuzhiyun VDW_RX_24BITS);
1027*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
1028*4882a593Smuzhiyun VDW_TX_24BITS);
1029*4882a593Smuzhiyun break;
1030*4882a593Smuzhiyun default:
1031*4882a593Smuzhiyun return -EINVAL;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun return 0;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun
rk817_digital_mute(struct snd_soc_dai * dai,int mute,int stream)1037*4882a593Smuzhiyun static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1040*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
1041*4882a593Smuzhiyun
1042*4882a593Smuzhiyun DBG("%s %d\n", __func__, mute);
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun if (mute) {
1045*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0);
1046*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun snd_soc_component_update_bits(component,
1049*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
1050*4882a593Smuzhiyun DACMT_ENABLE, DACMT_ENABLE);
1051*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1052*4882a593Smuzhiyun PWD_DACBIAS_DOWN | PWD_DACD_DOWN |
1053*4882a593Smuzhiyun PWD_DACL_DOWN | PWD_DACR_DOWN);
1054*4882a593Smuzhiyun /* Reset DAC DTOP_DIGEN_CLKE for playback stopped */
1055*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1056*4882a593Smuzhiyun DAC_DIG_CLK_EN, DAC_DIG_CLK_DIS);
1057*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1058*4882a593Smuzhiyun DAC_DIG_CLK_EN, DAC_DIG_CLK_EN);
1059*4882a593Smuzhiyun } else {
1060*4882a593Smuzhiyun snd_soc_component_update_bits(component,
1061*4882a593Smuzhiyun RK817_CODEC_DDAC_MUTE_MIXCTL,
1062*4882a593Smuzhiyun DACMT_ENABLE, DACMT_DISABLE);
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun switch (rk817->playback_path) {
1065*4882a593Smuzhiyun case SPK_PATH:
1066*4882a593Smuzhiyun case RING_SPK:
1067*4882a593Smuzhiyun if (rk817->out_l2spk_r2hp) {
1068*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1069*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
1070*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
1071*4882a593Smuzhiyun } else if (!rk817->use_ext_amplifier) {
1072*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1073*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
1074*4882a593Smuzhiyun PWD_DACL_DOWN | PWD_DACR_DOWN);
1075*4882a593Smuzhiyun } else {
1076*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1077*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_DOWN |
1078*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 1);
1081*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0);
1082*4882a593Smuzhiyun break;
1083*4882a593Smuzhiyun case HP_PATH:
1084*4882a593Smuzhiyun case HP_NO_MIC:
1085*4882a593Smuzhiyun case RING_HP:
1086*4882a593Smuzhiyun case RING_HP_NO_MIC:
1087*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1088*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_DOWN |
1089*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
1090*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0);
1091*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 1);
1092*4882a593Smuzhiyun break;
1093*4882a593Smuzhiyun case SPK_HP:
1094*4882a593Smuzhiyun case RING_SPK_HP:
1095*4882a593Smuzhiyun snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1,
1096*4882a593Smuzhiyun PWD_DACBIAS_ON | PWD_DACD_ON |
1097*4882a593Smuzhiyun PWD_DACL_ON | PWD_DACR_ON);
1098*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 1);
1099*4882a593Smuzhiyun rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 1);
1100*4882a593Smuzhiyun break;
1101*4882a593Smuzhiyun default:
1102*4882a593Smuzhiyun break;
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun return 0;
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun #define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
1110*4882a593Smuzhiyun SNDRV_PCM_RATE_16000 | \
1111*4882a593Smuzhiyun SNDRV_PCM_RATE_32000 | \
1112*4882a593Smuzhiyun SNDRV_PCM_RATE_44100 | \
1113*4882a593Smuzhiyun SNDRV_PCM_RATE_48000 | \
1114*4882a593Smuzhiyun SNDRV_PCM_RATE_96000)
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun #define RK817_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
1117*4882a593Smuzhiyun SNDRV_PCM_RATE_16000 | \
1118*4882a593Smuzhiyun SNDRV_PCM_RATE_32000 | \
1119*4882a593Smuzhiyun SNDRV_PCM_RATE_44100 | \
1120*4882a593Smuzhiyun SNDRV_PCM_RATE_48000 | \
1121*4882a593Smuzhiyun SNDRV_PCM_RATE_96000)
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun #define RK817_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1124*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_3LE |\
1125*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |\
1126*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE)
1127*4882a593Smuzhiyun
rk817_codec_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1128*4882a593Smuzhiyun static void rk817_codec_shutdown(struct snd_pcm_substream *substream,
1129*4882a593Smuzhiyun struct snd_soc_dai *dai)
1130*4882a593Smuzhiyun {
1131*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun /**
1134*4882a593Smuzhiyun * Note: The following configurations will take effect when i2s bclk
1135*4882a593Smuzhiyun * is working, and we just need to handle the part of ADC that is
1136*4882a593Smuzhiyun * output to SoC.
1137*4882a593Smuzhiyun */
1138*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1139*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1140*4882a593Smuzhiyun I2STX_CKE_EN, I2STX_CKE_EN);
1141*4882a593Smuzhiyun usleep_range(1000, 1100);
1142*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE,
1143*4882a593Smuzhiyun I2STX_CKE_EN, I2STX_CKE_DIS);
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun
1147*4882a593Smuzhiyun static struct snd_soc_dai_ops rk817_dai_ops = {
1148*4882a593Smuzhiyun .hw_params = rk817_hw_params,
1149*4882a593Smuzhiyun .set_fmt = rk817_set_dai_fmt,
1150*4882a593Smuzhiyun .set_sysclk = rk817_set_dai_sysclk,
1151*4882a593Smuzhiyun .mute_stream = rk817_digital_mute,
1152*4882a593Smuzhiyun .shutdown = rk817_codec_shutdown,
1153*4882a593Smuzhiyun .no_capture_mute = 1,
1154*4882a593Smuzhiyun };
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun static struct snd_soc_dai_driver rk817_dai[] = {
1157*4882a593Smuzhiyun {
1158*4882a593Smuzhiyun .name = "rk817-hifi",
1159*4882a593Smuzhiyun .id = RK817_HIFI,
1160*4882a593Smuzhiyun .playback = {
1161*4882a593Smuzhiyun .stream_name = "HiFi Playback",
1162*4882a593Smuzhiyun .channels_min = 2,
1163*4882a593Smuzhiyun .channels_max = 8,
1164*4882a593Smuzhiyun .rates = RK817_PLAYBACK_RATES,
1165*4882a593Smuzhiyun .formats = RK817_FORMATS,
1166*4882a593Smuzhiyun },
1167*4882a593Smuzhiyun .capture = {
1168*4882a593Smuzhiyun .stream_name = "HiFi Capture",
1169*4882a593Smuzhiyun .channels_min = 2,
1170*4882a593Smuzhiyun .channels_max = 8,
1171*4882a593Smuzhiyun .rates = RK817_CAPTURE_RATES,
1172*4882a593Smuzhiyun .formats = RK817_FORMATS,
1173*4882a593Smuzhiyun },
1174*4882a593Smuzhiyun .ops = &rk817_dai_ops,
1175*4882a593Smuzhiyun },
1176*4882a593Smuzhiyun {
1177*4882a593Smuzhiyun .name = "rk817-voice",
1178*4882a593Smuzhiyun .id = RK817_VOICE,
1179*4882a593Smuzhiyun .playback = {
1180*4882a593Smuzhiyun .stream_name = "Voice Playback",
1181*4882a593Smuzhiyun .channels_min = 1,
1182*4882a593Smuzhiyun .channels_max = 2,
1183*4882a593Smuzhiyun .rates = RK817_PLAYBACK_RATES,
1184*4882a593Smuzhiyun .formats = RK817_FORMATS,
1185*4882a593Smuzhiyun },
1186*4882a593Smuzhiyun .capture = {
1187*4882a593Smuzhiyun .stream_name = "Voice Capture",
1188*4882a593Smuzhiyun .channels_min = 2,
1189*4882a593Smuzhiyun .channels_max = 8,
1190*4882a593Smuzhiyun .rates = RK817_CAPTURE_RATES,
1191*4882a593Smuzhiyun .formats = RK817_FORMATS,
1192*4882a593Smuzhiyun },
1193*4882a593Smuzhiyun .ops = &rk817_dai_ops,
1194*4882a593Smuzhiyun },
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun };
1197*4882a593Smuzhiyun
rk817_suspend(struct snd_soc_component * component)1198*4882a593Smuzhiyun static int rk817_suspend(struct snd_soc_component *component)
1199*4882a593Smuzhiyun {
1200*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_ALL);
1201*4882a593Smuzhiyun return 0;
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun
rk817_resume(struct snd_soc_component * component)1204*4882a593Smuzhiyun static int rk817_resume(struct snd_soc_component *component)
1205*4882a593Smuzhiyun {
1206*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun if (rk817->resume_path) {
1209*4882a593Smuzhiyun if (rk817->capture_path != MIC_OFF)
1210*4882a593Smuzhiyun rk817_capture_path_config(component, OFF, rk817->capture_path);
1211*4882a593Smuzhiyun if (rk817->playback_path != OFF)
1212*4882a593Smuzhiyun rk817_playback_path_config(component, OFF, rk817->playback_path);
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun return 0;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun
rk817_probe(struct snd_soc_component * component)1218*4882a593Smuzhiyun static int rk817_probe(struct snd_soc_component *component)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
1221*4882a593Smuzhiyun int chip_name = 0;
1222*4882a593Smuzhiyun int chip_ver = 0;
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun DBG("%s\n", __func__);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun if (!rk817) {
1227*4882a593Smuzhiyun dev_err(component->dev, "%s : rk817 priv is NULL!\n",
1228*4882a593Smuzhiyun __func__);
1229*4882a593Smuzhiyun return -EINVAL;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun snd_soc_component_init_regmap(component, rk817->regmap);
1232*4882a593Smuzhiyun rk817->component = component;
1233*4882a593Smuzhiyun rk817->playback_path = OFF;
1234*4882a593Smuzhiyun rk817->capture_path = MIC_OFF;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun chip_name = snd_soc_component_read(component, RK817_PMIC_CHIP_NAME);
1237*4882a593Smuzhiyun chip_ver = snd_soc_component_read(component, RK817_PMIC_CHIP_VER);
1238*4882a593Smuzhiyun rk817->chip_ver = (chip_ver & 0x0f);
1239*4882a593Smuzhiyun dev_info(component->dev, "%s: chip_name:0x%x, chip_ver:0x%x\n", __func__, chip_name, chip_ver);
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun clk_prepare_enable(rk817->mclk);
1242*4882a593Smuzhiyun rk817_reset(component);
1243*4882a593Smuzhiyun clk_disable_unprepare(rk817->mclk);
1244*4882a593Smuzhiyun mutex_init(&rk817->clk_lock);
1245*4882a593Smuzhiyun rk817->clk_capture = 0;
1246*4882a593Smuzhiyun rk817->clk_playback = 0;
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun snd_soc_add_component_controls(component, rk817_snd_path_controls,
1249*4882a593Smuzhiyun ARRAY_SIZE(rk817_snd_path_controls));
1250*4882a593Smuzhiyun return 0;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun /* power down chip */
rk817_remove(struct snd_soc_component * component)1254*4882a593Smuzhiyun static void rk817_remove(struct snd_soc_component *component)
1255*4882a593Smuzhiyun {
1256*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun DBG("%s\n", __func__);
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun if (!rk817) {
1261*4882a593Smuzhiyun dev_err(component->dev, "%s : rk817 is NULL\n", __func__);
1262*4882a593Smuzhiyun return;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun rk817_codec_power_down(component, RK817_CODEC_ALL);
1266*4882a593Smuzhiyun snd_soc_component_exit_regmap(component);
1267*4882a593Smuzhiyun mutex_destroy(&rk817->clk_lock);
1268*4882a593Smuzhiyun mdelay(10);
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun }
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rk817 = {
1273*4882a593Smuzhiyun .probe = rk817_probe,
1274*4882a593Smuzhiyun .remove = rk817_remove,
1275*4882a593Smuzhiyun .suspend = rk817_suspend,
1276*4882a593Smuzhiyun .resume = rk817_resume,
1277*4882a593Smuzhiyun .idle_bias_on = 1,
1278*4882a593Smuzhiyun .use_pmdown_time = 1,
1279*4882a593Smuzhiyun .endianness = 1,
1280*4882a593Smuzhiyun .non_legacy_dai_naming = 1
1281*4882a593Smuzhiyun };
1282*4882a593Smuzhiyun
rk817_codec_parse_dt_property(struct device * dev,struct rk817_codec_priv * rk817)1283*4882a593Smuzhiyun static int rk817_codec_parse_dt_property(struct device *dev,
1284*4882a593Smuzhiyun struct rk817_codec_priv *rk817)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun struct device_node *node = dev->parent->of_node;
1287*4882a593Smuzhiyun int ret;
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun DBG("%s()\n", __func__);
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun if (!node) {
1292*4882a593Smuzhiyun dev_err(dev, "%s() dev->parent->of_node is NULL\n",
1293*4882a593Smuzhiyun __func__);
1294*4882a593Smuzhiyun return -ENODEV;
1295*4882a593Smuzhiyun }
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun node = of_get_child_by_name(dev->parent->of_node, "codec");
1298*4882a593Smuzhiyun if (!node) {
1299*4882a593Smuzhiyun dev_err(dev, "%s() Can not get child: codec\n",
1300*4882a593Smuzhiyun __func__);
1301*4882a593Smuzhiyun return -ENODEV;
1302*4882a593Smuzhiyun }
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun rk817->hp_ctl_gpio = devm_gpiod_get_optional(dev, "hp-ctl",
1305*4882a593Smuzhiyun GPIOD_OUT_LOW);
1306*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(rk817->hp_ctl_gpio)) {
1307*4882a593Smuzhiyun DBG("%s : hp-ctl-gpio %d\n", __func__,
1308*4882a593Smuzhiyun desc_to_gpio(rk817->hp_ctl_gpio));
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun rk817->spk_ctl_gpio = devm_gpiod_get_optional(dev, "spk-ctl",
1312*4882a593Smuzhiyun GPIOD_OUT_LOW);
1313*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(rk817->spk_ctl_gpio)) {
1314*4882a593Smuzhiyun DBG("%s : spk-ctl-gpio %d\n", __func__,
1315*4882a593Smuzhiyun desc_to_gpio(rk817->spk_ctl_gpio));
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun ret = of_property_read_u32(node, "spk-mute-delay-ms",
1319*4882a593Smuzhiyun &rk817->spk_mute_delay);
1320*4882a593Smuzhiyun if (ret < 0) {
1321*4882a593Smuzhiyun DBG("%s() Can not read property spk-mute-delay-ms\n",
1322*4882a593Smuzhiyun __func__);
1323*4882a593Smuzhiyun rk817->spk_mute_delay = 0;
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun ret = of_property_read_u32(node, "hp-mute-delay-ms",
1327*4882a593Smuzhiyun &rk817->hp_mute_delay);
1328*4882a593Smuzhiyun if (ret < 0) {
1329*4882a593Smuzhiyun DBG("%s() Can not read property hp-mute-delay-ms\n",
1330*4882a593Smuzhiyun __func__);
1331*4882a593Smuzhiyun rk817->hp_mute_delay = 0;
1332*4882a593Smuzhiyun }
1333*4882a593Smuzhiyun DBG("spk mute delay %dms --- hp mute delay %dms\n",
1334*4882a593Smuzhiyun rk817->spk_mute_delay, rk817->hp_mute_delay);
1335*4882a593Smuzhiyun
1336*4882a593Smuzhiyun ret = of_property_read_u32(node, "spk-volume", &rk817->spk_volume);
1337*4882a593Smuzhiyun if (ret < 0) {
1338*4882a593Smuzhiyun DBG("%s() Can not read property spk-volume\n", __func__);
1339*4882a593Smuzhiyun rk817->spk_volume = OUT_VOLUME;
1340*4882a593Smuzhiyun }
1341*4882a593Smuzhiyun if (rk817->spk_volume < 3)
1342*4882a593Smuzhiyun rk817->spk_volume = 3;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun ret = of_property_read_u32(node, "hp-volume",
1345*4882a593Smuzhiyun &rk817->hp_volume);
1346*4882a593Smuzhiyun if (ret < 0) {
1347*4882a593Smuzhiyun DBG("%s() Can not read property hp-volume\n",
1348*4882a593Smuzhiyun __func__);
1349*4882a593Smuzhiyun rk817->hp_volume = OUT_VOLUME;
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun if (rk817->hp_volume < 3)
1352*4882a593Smuzhiyun rk817->hp_volume = 3;
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun ret = of_property_read_u32(node, "capture-volume",
1355*4882a593Smuzhiyun &rk817->capture_volume);
1356*4882a593Smuzhiyun if (ret < 0) {
1357*4882a593Smuzhiyun DBG("%s() Can not read property capture-volume\n",
1358*4882a593Smuzhiyun __func__);
1359*4882a593Smuzhiyun rk817->capture_volume = CAPTURE_VOLUME;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun rk817->mic_in_differential =
1363*4882a593Smuzhiyun of_property_read_bool(node, "mic-in-differential");
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun rk817->pdmdata_out_enable =
1366*4882a593Smuzhiyun of_property_read_bool(node, "pdmdata-out-enable");
1367*4882a593Smuzhiyun
1368*4882a593Smuzhiyun rk817->use_ext_amplifier =
1369*4882a593Smuzhiyun of_property_read_bool(node, "use-ext-amplifier");
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun rk817->out_l2spk_r2hp = of_property_read_bool(node, "out-l2spk-r2hp");
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun rk817->adc_for_loopback =
1374*4882a593Smuzhiyun of_property_read_bool(node, "adc-for-loopback");
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun return 0;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun static const struct regmap_config rk817_codec_regmap_config = {
1380*4882a593Smuzhiyun .name = "rk817-codec",
1381*4882a593Smuzhiyun .reg_bits = 8,
1382*4882a593Smuzhiyun .val_bits = 8,
1383*4882a593Smuzhiyun .reg_stride = 1,
1384*4882a593Smuzhiyun .max_register = 0xfe,
1385*4882a593Smuzhiyun .cache_type = REGCACHE_FLAT,
1386*4882a593Smuzhiyun .volatile_reg = rk817_volatile_register,
1387*4882a593Smuzhiyun .writeable_reg = rk817_codec_register,
1388*4882a593Smuzhiyun .readable_reg = rk817_codec_register,
1389*4882a593Smuzhiyun .reg_defaults = rk817_reg_defaults,
1390*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(rk817_reg_defaults),
1391*4882a593Smuzhiyun };
1392*4882a593Smuzhiyun
rk817_platform_probe(struct platform_device * pdev)1393*4882a593Smuzhiyun static int rk817_platform_probe(struct platform_device *pdev)
1394*4882a593Smuzhiyun {
1395*4882a593Smuzhiyun struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent);
1396*4882a593Smuzhiyun struct rk817_codec_priv *rk817_codec_data;
1397*4882a593Smuzhiyun int ret;
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun DBG("%s\n", __func__);
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun if (!rk817) {
1402*4882a593Smuzhiyun dev_err(&pdev->dev, "%s : rk817 is NULL\n", __func__);
1403*4882a593Smuzhiyun return -EINVAL;
1404*4882a593Smuzhiyun }
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun rk817_codec_data = devm_kzalloc(&pdev->dev,
1407*4882a593Smuzhiyun sizeof(struct rk817_codec_priv),
1408*4882a593Smuzhiyun GFP_KERNEL);
1409*4882a593Smuzhiyun if (!rk817_codec_data)
1410*4882a593Smuzhiyun return -ENOMEM;
1411*4882a593Smuzhiyun
1412*4882a593Smuzhiyun platform_set_drvdata(pdev, rk817_codec_data);
1413*4882a593Smuzhiyun
1414*4882a593Smuzhiyun ret = rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data);
1415*4882a593Smuzhiyun if (ret < 0) {
1416*4882a593Smuzhiyun dev_err(&pdev->dev, "%s() parse device tree property error %d\n",
1417*4882a593Smuzhiyun __func__, ret);
1418*4882a593Smuzhiyun goto err_;
1419*4882a593Smuzhiyun }
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun rk817_codec_data->regmap = devm_regmap_init_i2c(rk817->i2c,
1422*4882a593Smuzhiyun &rk817_codec_regmap_config);
1423*4882a593Smuzhiyun if (IS_ERR(rk817_codec_data->regmap)) {
1424*4882a593Smuzhiyun ret = PTR_ERR(rk817_codec_data->regmap);
1425*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate register map: %d\n",
1426*4882a593Smuzhiyun ret);
1427*4882a593Smuzhiyun goto err_;
1428*4882a593Smuzhiyun }
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun rk817_codec_data->mclk = devm_clk_get(&pdev->dev, "mclk");
1431*4882a593Smuzhiyun if (IS_ERR(rk817_codec_data->mclk)) {
1432*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to get mclk\n");
1433*4882a593Smuzhiyun ret = -ENXIO;
1434*4882a593Smuzhiyun goto err_;
1435*4882a593Smuzhiyun }
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk817,
1438*4882a593Smuzhiyun rk817_dai, ARRAY_SIZE(rk817_dai));
1439*4882a593Smuzhiyun if (ret < 0) {
1440*4882a593Smuzhiyun dev_err(&pdev->dev, "%s() register codec error %d\n",
1441*4882a593Smuzhiyun __func__, ret);
1442*4882a593Smuzhiyun goto err_;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun return 0;
1446*4882a593Smuzhiyun err_:
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun return ret;
1449*4882a593Smuzhiyun }
1450*4882a593Smuzhiyun
rk817_platform_remove(struct platform_device * pdev)1451*4882a593Smuzhiyun static int rk817_platform_remove(struct platform_device *pdev)
1452*4882a593Smuzhiyun {
1453*4882a593Smuzhiyun snd_soc_unregister_component(&pdev->dev);
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun return 0;
1456*4882a593Smuzhiyun }
1457*4882a593Smuzhiyun
rk817_platform_shutdown(struct platform_device * pdev)1458*4882a593Smuzhiyun static void rk817_platform_shutdown(struct platform_device *pdev)
1459*4882a593Smuzhiyun {
1460*4882a593Smuzhiyun struct rk817_codec_priv *rk817 = dev_get_drvdata(&pdev->dev);
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun DBG("%s\n", __func__);
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun if (rk817 && rk817->component)
1465*4882a593Smuzhiyun rk817_codec_power_down(rk817->component, RK817_CODEC_ALL);
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun static const struct of_device_id rk817_codec_dt_ids[] = {
1469*4882a593Smuzhiyun { .compatible = "rockchip,rk817-codec" },
1470*4882a593Smuzhiyun {},
1471*4882a593Smuzhiyun };
1472*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk817_codec_dt_ids);
1473*4882a593Smuzhiyun
1474*4882a593Smuzhiyun static struct platform_driver rk817_codec_driver = {
1475*4882a593Smuzhiyun .driver = {
1476*4882a593Smuzhiyun .name = "rk817-codec",
1477*4882a593Smuzhiyun .of_match_table = rk817_codec_dt_ids,
1478*4882a593Smuzhiyun },
1479*4882a593Smuzhiyun .probe = rk817_platform_probe,
1480*4882a593Smuzhiyun .remove = rk817_platform_remove,
1481*4882a593Smuzhiyun .shutdown = rk817_platform_shutdown,
1482*4882a593Smuzhiyun };
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun module_platform_driver(rk817_codec_driver);
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC RK817 codec driver");
1487*4882a593Smuzhiyun MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
1488*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1489