1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * rk3308_codec.c -- RK3308 ALSA Soc Audio Driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
7*4882a593Smuzhiyun * under the terms and conditions of the GNU General Public License,
8*4882a593Smuzhiyun * version 2, as published by the Free Software Foundation.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This program is distributed in the hope it will be useful, but WITHOUT
11*4882a593Smuzhiyun * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13*4882a593Smuzhiyun * more details.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * You should have received a copy of the GNU General Public License
16*4882a593Smuzhiyun * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <linux/clk.h>
21*4882a593Smuzhiyun #include <linux/device.h>
22*4882a593Smuzhiyun #include <linux/delay.h>
23*4882a593Smuzhiyun #include <linux/init.h>
24*4882a593Smuzhiyun #include <linux/io.h>
25*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <linux/of.h>
28*4882a593Smuzhiyun #include <linux/of_gpio.h>
29*4882a593Smuzhiyun #include <linux/platform_device.h>
30*4882a593Smuzhiyun #include <linux/pm_runtime.h>
31*4882a593Smuzhiyun #include <linux/regmap.h>
32*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
33*4882a593Smuzhiyun #include <linux/reset.h>
34*4882a593Smuzhiyun #include <linux/rockchip/grf.h>
35*4882a593Smuzhiyun #include <linux/version.h>
36*4882a593Smuzhiyun #include <sound/core.h>
37*4882a593Smuzhiyun #include <sound/dmaengine_pcm.h>
38*4882a593Smuzhiyun #include <sound/initval.h>
39*4882a593Smuzhiyun #include <sound/jack.h>
40*4882a593Smuzhiyun #include <sound/pcm.h>
41*4882a593Smuzhiyun #include <sound/pcm_params.h>
42*4882a593Smuzhiyun #include <sound/simple_card.h>
43*4882a593Smuzhiyun #include <sound/soc.h>
44*4882a593Smuzhiyun #include <sound/tlv.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #include "rk3308_codec.h"
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
49*4882a593Smuzhiyun #include <linux/fs.h>
50*4882a593Smuzhiyun #include <linux/debugfs.h>
51*4882a593Smuzhiyun #include <linux/seq_file.h>
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define CODEC_DRV_NAME "rk3308-acodec"
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define ADC_GRP_SKIP_MAGIC 0x1001
57*4882a593Smuzhiyun #define ADC_LR_GROUP_MAX 4
58*4882a593Smuzhiyun #define ADC_STABLE_MS 200
59*4882a593Smuzhiyun #define DEBUG_POP_ALWAYS 0
60*4882a593Smuzhiyun #define HPDET_POLL_MS 2000
61*4882a593Smuzhiyun #define NOT_USED 255
62*4882a593Smuzhiyun #define LOOPBACK_HANDLE_MS 100
63*4882a593Smuzhiyun #define PA_DRV_MS 5
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define GRF_SOC_CON1 0x304
66*4882a593Smuzhiyun #define GRF_CHIP_ID 0x800
67*4882a593Smuzhiyun #define GRF_I2S2_8CH_SDI_SFT 0
68*4882a593Smuzhiyun #define GRF_I2S3_4CH_SDI_SFT 8
69*4882a593Smuzhiyun #define GRF_I2S1_2CH_SDI_SFT 12
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define GRF_I2S2_8CH_SDI_R_MSK(i, v) ((v >> (i * 2 + GRF_I2S2_8CH_SDI_SFT)) & 0x3)
72*4882a593Smuzhiyun #define GRF_I2S2_8CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S2_8CH_SDI_SFT + 16))
73*4882a593Smuzhiyun #define GRF_I2S2_8CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S2_8CH_SDI_SFT)) |\
74*4882a593Smuzhiyun GRF_I2S2_8CH_SDI_W_MSK(i))
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define GRF_I2S3_4CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S3_4CH_SDI_SFT + 16))
77*4882a593Smuzhiyun #define GRF_I2S3_4CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S3_4CH_SDI_SFT)) |\
78*4882a593Smuzhiyun GRF_I2S3_4CH_SDI_W_MSK(i))
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define GRF_I2S1_2CH_SDI_W_MSK (0x3 << (GRF_I2S1_2CH_SDI_SFT + 16))
81*4882a593Smuzhiyun #define GRF_I2S1_2CH_SDI(v) (((v & 0x3) << GRF_I2S1_2CH_SDI_SFT) |\
82*4882a593Smuzhiyun GRF_I2S1_2CH_SDI_W_MSK)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define DETECT_GRF_ACODEC_HPDET_COUNTER 0x0030
85*4882a593Smuzhiyun #define DETECT_GRF_ACODEC_HPDET_CON 0x0034
86*4882a593Smuzhiyun #define DETECT_GRF_ACODEC_HPDET_STATUS 0x0038
87*4882a593Smuzhiyun #define DETECT_GRF_ACODEC_HPDET_STATUS_CLR 0x003c
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* 200ms based on pclk is 100MHz */
90*4882a593Smuzhiyun #define DEFAULT_HPDET_COUNT 20000000
91*4882a593Smuzhiyun #define HPDET_NEG_IRQ_SFT 1
92*4882a593Smuzhiyun #define HPDET_POS_IRQ_SFT 0
93*4882a593Smuzhiyun #define HPDET_BOTH_NEG_POS ((1 << HPDET_NEG_IRQ_SFT) |\
94*4882a593Smuzhiyun (1 << HPDET_POS_IRQ_SFT))
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun #define ACODEC_VERSION_A 0xa
97*4882a593Smuzhiyun #define ACODEC_VERSION_B 0xb
98*4882a593Smuzhiyun #define ACODEC_VERSION_C 0xc
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun enum {
101*4882a593Smuzhiyun ACODEC_TO_I2S2_8CH = 0,
102*4882a593Smuzhiyun ACODEC_TO_I2S3_4CH,
103*4882a593Smuzhiyun ACODEC_TO_I2S1_2CH,
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun enum {
107*4882a593Smuzhiyun ADC_GRP0_MICIN = 0,
108*4882a593Smuzhiyun ADC_GRP0_LINEIN
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun enum {
112*4882a593Smuzhiyun ADC_TYPE_NORMAL = 0,
113*4882a593Smuzhiyun ADC_TYPE_LOOPBACK,
114*4882a593Smuzhiyun ADC_TYPE_DBG,
115*4882a593Smuzhiyun ADC_TYPE_ALL,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun enum {
119*4882a593Smuzhiyun DAC_LINEOUT = 0,
120*4882a593Smuzhiyun DAC_HPOUT = 1,
121*4882a593Smuzhiyun DAC_LINEOUT_HPOUT = 11,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun enum {
125*4882a593Smuzhiyun EXT_MICBIAS_NONE = 0,
126*4882a593Smuzhiyun EXT_MICBIAS_FUNC1, /* enable external micbias via GPIO */
127*4882a593Smuzhiyun EXT_MICBIAS_FUNC2, /* enable external micbias via regulator */
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun enum {
131*4882a593Smuzhiyun PATH_IDLE = 0,
132*4882a593Smuzhiyun PATH_BUSY,
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun enum {
136*4882a593Smuzhiyun PM_NORMAL = 0,
137*4882a593Smuzhiyun PM_LLP_DOWN, /* light low power down */
138*4882a593Smuzhiyun PM_LLP_UP,
139*4882a593Smuzhiyun PM_DLP_DOWN, /* deep low power down */
140*4882a593Smuzhiyun PM_DLP_UP,
141*4882a593Smuzhiyun PM_DLP_DOWN2,
142*4882a593Smuzhiyun PM_DLP_UP2,
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun struct rk3308_codec_priv {
146*4882a593Smuzhiyun const struct device *plat_dev;
147*4882a593Smuzhiyun struct device dev;
148*4882a593Smuzhiyun struct reset_control *reset;
149*4882a593Smuzhiyun struct regmap *regmap;
150*4882a593Smuzhiyun struct regmap *grf;
151*4882a593Smuzhiyun struct regmap *detect_grf;
152*4882a593Smuzhiyun struct clk *pclk;
153*4882a593Smuzhiyun struct clk *mclk_rx;
154*4882a593Smuzhiyun struct clk *mclk_tx;
155*4882a593Smuzhiyun struct gpio_desc *micbias_en_gpio;
156*4882a593Smuzhiyun struct gpio_desc *hp_ctl_gpio;
157*4882a593Smuzhiyun struct gpio_desc *spk_ctl_gpio;
158*4882a593Smuzhiyun struct gpio_desc *pa_drv_gpio;
159*4882a593Smuzhiyun struct snd_soc_component *component;
160*4882a593Smuzhiyun struct snd_soc_jack *hpdet_jack;
161*4882a593Smuzhiyun struct regulator *vcc_micbias;
162*4882a593Smuzhiyun u32 codec_ver;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun * To select ADCs for groups:
166*4882a593Smuzhiyun *
167*4882a593Smuzhiyun * grp 0 -- select ADC1 / ADC2
168*4882a593Smuzhiyun * grp 1 -- select ADC3 / ADC4
169*4882a593Smuzhiyun * grp 2 -- select ADC5 / ADC6
170*4882a593Smuzhiyun * grp 3 -- select ADC7 / ADC8
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun u32 used_adc_grps;
173*4882a593Smuzhiyun /* The ADC group which is used for loop back */
174*4882a593Smuzhiyun u32 loopback_grp;
175*4882a593Smuzhiyun u32 cur_dbg_grp;
176*4882a593Smuzhiyun u32 en_always_grps[ADC_LR_GROUP_MAX];
177*4882a593Smuzhiyun u32 en_always_grps_num;
178*4882a593Smuzhiyun u32 skip_grps[ADC_LR_GROUP_MAX];
179*4882a593Smuzhiyun u32 i2s_sdis[ADC_LR_GROUP_MAX];
180*4882a593Smuzhiyun u32 to_i2s_grps;
181*4882a593Smuzhiyun u32 delay_loopback_handle_ms;
182*4882a593Smuzhiyun u32 delay_start_play_ms;
183*4882a593Smuzhiyun u32 delay_pa_drv_ms;
184*4882a593Smuzhiyun u32 micbias_num;
185*4882a593Smuzhiyun u32 micbias_volt;
186*4882a593Smuzhiyun int which_i2s;
187*4882a593Smuzhiyun int irq;
188*4882a593Smuzhiyun int adc_grp0_using_linein;
189*4882a593Smuzhiyun int adc_zerocross;
190*4882a593Smuzhiyun /* 0: line out, 1: hp out, 11: lineout and hpout */
191*4882a593Smuzhiyun int dac_output;
192*4882a593Smuzhiyun int dac_path_state;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun int ext_micbias;
195*4882a593Smuzhiyun int pm_state;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* ADC MIC Mute/Work */
198*4882a593Smuzhiyun unsigned int mic_mute_l[ADC_LR_GROUP_MAX];
199*4882a593Smuzhiyun unsigned int mic_mute_r[ADC_LR_GROUP_MAX];
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* For the high pass filter */
202*4882a593Smuzhiyun unsigned int hpf_cutoff[ADC_LR_GROUP_MAX];
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* Only hpout do fade-in and fade-out */
205*4882a593Smuzhiyun unsigned int hpout_l_dgain;
206*4882a593Smuzhiyun unsigned int hpout_r_dgain;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun bool adc_grps_endisable[ADC_LR_GROUP_MAX];
209*4882a593Smuzhiyun bool dac_endisable;
210*4882a593Smuzhiyun bool enable_all_adcs;
211*4882a593Smuzhiyun bool enable_micbias;
212*4882a593Smuzhiyun bool micbias1;
213*4882a593Smuzhiyun bool micbias2;
214*4882a593Smuzhiyun bool hp_jack_reversed;
215*4882a593Smuzhiyun bool hp_plugged;
216*4882a593Smuzhiyun bool loopback_dacs_enabled;
217*4882a593Smuzhiyun bool no_deep_low_power;
218*4882a593Smuzhiyun bool no_hp_det;
219*4882a593Smuzhiyun struct delayed_work hpdet_work;
220*4882a593Smuzhiyun struct delayed_work loopback_work;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
223*4882a593Smuzhiyun struct dentry *dbg_codec;
224*4882a593Smuzhiyun #endif
225*4882a593Smuzhiyun };
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv,
228*4882a593Smuzhiyun -1800, 150, 2850);
229*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_lineout_gain_tlv,
230*4882a593Smuzhiyun -600, 150, 0);
231*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv,
232*4882a593Smuzhiyun -3900, 150, 600);
233*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv,
234*4882a593Smuzhiyun -600, 600, 0);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_a,
237*4882a593Smuzhiyun 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
238*4882a593Smuzhiyun 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
239*4882a593Smuzhiyun );
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_b,
242*4882a593Smuzhiyun 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
243*4882a593Smuzhiyun 1, 1, TLV_DB_SCALE_ITEM(660, 0, 0),
244*4882a593Smuzhiyun 2, 2, TLV_DB_SCALE_ITEM(1300, 0, 0),
245*4882a593Smuzhiyun 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
246*4882a593Smuzhiyun );
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun static bool handle_loopback(struct rk3308_codec_priv *rk3308);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun static int check_micbias(int micbias);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun static void rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv *rk3308);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308,
255*4882a593Smuzhiyun int micbias);
256*4882a593Smuzhiyun static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol,
259*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
260*4882a593Smuzhiyun static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol,
261*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
262*4882a593Smuzhiyun static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol,
263*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
264*4882a593Smuzhiyun static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol,
265*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
266*4882a593Smuzhiyun static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol,
267*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
268*4882a593Smuzhiyun static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol,
269*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
270*4882a593Smuzhiyun static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol,
271*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
272*4882a593Smuzhiyun static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
273*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
274*4882a593Smuzhiyun static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol,
275*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
276*4882a593Smuzhiyun static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol,
277*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
278*4882a593Smuzhiyun static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol,
279*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
280*4882a593Smuzhiyun static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol,
281*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
282*4882a593Smuzhiyun static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol,
283*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
284*4882a593Smuzhiyun static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol,
285*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun static const char *offon_text[2] = {
288*4882a593Smuzhiyun [0] = "Off",
289*4882a593Smuzhiyun [1] = "On",
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static const char *mute_text[2] = {
293*4882a593Smuzhiyun [0] = "Work",
294*4882a593Smuzhiyun [1] = "Mute",
295*4882a593Smuzhiyun };
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun /* ADC MICBIAS Volt */
298*4882a593Smuzhiyun #define MICBIAS_VOLT_NUM 8
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun #define MICBIAS_VREFx0_5 0
301*4882a593Smuzhiyun #define MICBIAS_VREFx0_55 1
302*4882a593Smuzhiyun #define MICBIAS_VREFx0_6 2
303*4882a593Smuzhiyun #define MICBIAS_VREFx0_65 3
304*4882a593Smuzhiyun #define MICBIAS_VREFx0_7 4
305*4882a593Smuzhiyun #define MICBIAS_VREFx0_75 5
306*4882a593Smuzhiyun #define MICBIAS_VREFx0_8 6
307*4882a593Smuzhiyun #define MICBIAS_VREFx0_85 7
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = {
310*4882a593Smuzhiyun [MICBIAS_VREFx0_5] = "VREFx0_5",
311*4882a593Smuzhiyun [MICBIAS_VREFx0_55] = "VREFx0_55",
312*4882a593Smuzhiyun [MICBIAS_VREFx0_6] = "VREFx0_6",
313*4882a593Smuzhiyun [MICBIAS_VREFx0_65] = "VREFx0_65",
314*4882a593Smuzhiyun [MICBIAS_VREFx0_7] = "VREFx0_7",
315*4882a593Smuzhiyun [MICBIAS_VREFx0_75] = "VREFx0_75",
316*4882a593Smuzhiyun [MICBIAS_VREFx0_8] = "VREFx0_8",
317*4882a593Smuzhiyun [MICBIAS_VREFx0_85] = "VREFx0_85",
318*4882a593Smuzhiyun };
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun static const struct soc_enum rk3308_micbias_volts_enum_array[] = {
321*4882a593Smuzhiyun SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array),
322*4882a593Smuzhiyun };
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* ADC MICBIAS1 and MICBIAS2 Main Switch */
325*4882a593Smuzhiyun static const struct soc_enum rk3308_main_micbias_enum_array[] = {
326*4882a593Smuzhiyun SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text),
327*4882a593Smuzhiyun };
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun static const struct soc_enum rk3308_hpf_enum_array[] = {
330*4882a593Smuzhiyun SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text),
331*4882a593Smuzhiyun SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text),
332*4882a593Smuzhiyun SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text),
333*4882a593Smuzhiyun SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text),
334*4882a593Smuzhiyun };
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* ADC MIC Mute/Work Switch */
337*4882a593Smuzhiyun static const struct soc_enum rk3308_mic_mute_enum_array[] = {
338*4882a593Smuzhiyun SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(mute_text), mute_text),
339*4882a593Smuzhiyun SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(mute_text), mute_text),
340*4882a593Smuzhiyun SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(mute_text), mute_text),
341*4882a593Smuzhiyun SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(mute_text), mute_text),
342*4882a593Smuzhiyun SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(mute_text), mute_text),
343*4882a593Smuzhiyun SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(mute_text), mute_text),
344*4882a593Smuzhiyun SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(mute_text), mute_text),
345*4882a593Smuzhiyun SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(mute_text), mute_text),
346*4882a593Smuzhiyun };
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun static const struct snd_kcontrol_new mic_gains_a[] = {
349*4882a593Smuzhiyun /* ADC MIC */
350*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Gain",
351*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(0),
352*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
353*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
354*4882a593Smuzhiyun 0,
355*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
356*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
357*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
358*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Gain",
359*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(0),
360*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
361*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
362*4882a593Smuzhiyun 0,
363*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
364*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
365*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
366*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Gain",
367*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(1),
368*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
369*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
370*4882a593Smuzhiyun 0,
371*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
372*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
373*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
374*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Gain",
375*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(1),
376*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
377*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
378*4882a593Smuzhiyun 0,
379*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
380*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
381*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
382*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Gain",
383*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(2),
384*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
385*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
386*4882a593Smuzhiyun 0,
387*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
388*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
389*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
390*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Gain",
391*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(2),
392*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
393*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
394*4882a593Smuzhiyun 0,
395*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
396*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
397*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
398*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Gain",
399*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(3),
400*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
401*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
402*4882a593Smuzhiyun 0,
403*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
404*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
405*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
406*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Gain",
407*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(3),
408*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
409*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
410*4882a593Smuzhiyun 0,
411*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
412*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
413*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_a),
414*4882a593Smuzhiyun };
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun static const struct snd_kcontrol_new mic_gains_b[] = {
417*4882a593Smuzhiyun /* ADC MIC */
418*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Gain",
419*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(0),
420*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
421*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
422*4882a593Smuzhiyun 0,
423*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
424*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
425*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
426*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Gain",
427*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(0),
428*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
429*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
430*4882a593Smuzhiyun 0,
431*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
432*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
433*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
434*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Gain",
435*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(1),
436*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
437*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
438*4882a593Smuzhiyun 0,
439*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
440*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
441*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
442*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Gain",
443*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(1),
444*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
445*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
446*4882a593Smuzhiyun 0,
447*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
448*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
449*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
450*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Gain",
451*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(2),
452*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
453*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
454*4882a593Smuzhiyun 0,
455*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
456*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
457*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
458*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Gain",
459*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(2),
460*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
461*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
462*4882a593Smuzhiyun 0,
463*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
464*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
465*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
466*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Gain",
467*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(3),
468*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_SFT,
469*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MAX,
470*4882a593Smuzhiyun 0,
471*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
472*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
473*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
474*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Gain",
475*4882a593Smuzhiyun RK3308_ADC_ANA_CON01(3),
476*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_SFT,
477*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MAX,
478*4882a593Smuzhiyun 0,
479*4882a593Smuzhiyun rk3308_codec_mic_gain_get,
480*4882a593Smuzhiyun rk3308_codec_mic_gain_put,
481*4882a593Smuzhiyun rk3308_codec_adc_mic_gain_tlv_b),
482*4882a593Smuzhiyun };
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = {
485*4882a593Smuzhiyun /* ADC MICBIAS Voltage */
486*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MICBIAS Voltage", rk3308_micbias_volts_enum_array[0],
487*4882a593Smuzhiyun rk3308_codec_micbias_volts_get, rk3308_codec_micbias_volts_put),
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /* ADC Main MICBIAS Switch */
490*4882a593Smuzhiyun SOC_ENUM_EXT("ADC Main MICBIAS", rk3308_main_micbias_enum_array[0],
491*4882a593Smuzhiyun rk3308_codec_main_micbias_get, rk3308_codec_main_micbias_put),
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /* ADC MICBIAS1 and MICBIAS2 Switch */
494*4882a593Smuzhiyun SOC_SINGLE("ADC MICBIAS1", RK3308_ADC_ANA_CON07(1),
495*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0),
496*4882a593Smuzhiyun SOC_SINGLE("ADC MICBIAS2", RK3308_ADC_ANA_CON07(2),
497*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0),
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* ADC MIC Mute/Work Switch */
500*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 0 Left Switch", rk3308_mic_mute_enum_array[0],
501*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
502*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 0 Right Switch", rk3308_mic_mute_enum_array[1],
503*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
504*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 1 Left Switch", rk3308_mic_mute_enum_array[2],
505*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
506*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 1 Right Switch", rk3308_mic_mute_enum_array[3],
507*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
508*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 2 Left Switch", rk3308_mic_mute_enum_array[4],
509*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
510*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 2 Right Switch", rk3308_mic_mute_enum_array[5],
511*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
512*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 3 Left Switch", rk3308_mic_mute_enum_array[6],
513*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
514*4882a593Smuzhiyun SOC_ENUM_EXT("ADC MIC Group 3 Right Switch", rk3308_mic_mute_enum_array[7],
515*4882a593Smuzhiyun rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /* ADC ALC */
518*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Left Volume",
519*4882a593Smuzhiyun RK3308_ADC_ANA_CON03(0),
520*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_SFT,
521*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MIN,
522*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MAX,
523*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
524*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Right Volume",
525*4882a593Smuzhiyun RK3308_ADC_ANA_CON04(0),
526*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_SFT,
527*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MIN,
528*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MAX,
529*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
530*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Left Volume",
531*4882a593Smuzhiyun RK3308_ADC_ANA_CON03(1),
532*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_SFT,
533*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MIN,
534*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MAX,
535*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
536*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Right Volume",
537*4882a593Smuzhiyun RK3308_ADC_ANA_CON04(1),
538*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_SFT,
539*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MIN,
540*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MAX,
541*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
542*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Left Volume",
543*4882a593Smuzhiyun RK3308_ADC_ANA_CON03(2),
544*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_SFT,
545*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MIN,
546*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MAX,
547*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
548*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Right Volume",
549*4882a593Smuzhiyun RK3308_ADC_ANA_CON04(2),
550*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_SFT,
551*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MIN,
552*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MAX,
553*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
554*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Left Volume",
555*4882a593Smuzhiyun RK3308_ADC_ANA_CON03(3),
556*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_SFT,
557*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MIN,
558*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MAX,
559*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
560*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Right Volume",
561*4882a593Smuzhiyun RK3308_ADC_ANA_CON04(3),
562*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_SFT,
563*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MIN,
564*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MAX,
565*4882a593Smuzhiyun 0, rk3308_codec_adc_alc_gain_tlv),
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* ADC High Pass Filter */
568*4882a593Smuzhiyun SOC_ENUM_EXT("ADC Group 0 HPF Cut-off", rk3308_hpf_enum_array[0],
569*4882a593Smuzhiyun rk3308_codec_hpf_get, rk3308_codec_hpf_put),
570*4882a593Smuzhiyun SOC_ENUM_EXT("ADC Group 1 HPF Cut-off", rk3308_hpf_enum_array[1],
571*4882a593Smuzhiyun rk3308_codec_hpf_get, rk3308_codec_hpf_put),
572*4882a593Smuzhiyun SOC_ENUM_EXT("ADC Group 2 HPF Cut-off", rk3308_hpf_enum_array[2],
573*4882a593Smuzhiyun rk3308_codec_hpf_get, rk3308_codec_hpf_put),
574*4882a593Smuzhiyun SOC_ENUM_EXT("ADC Group 3 HPF Cut-off", rk3308_hpf_enum_array[3],
575*4882a593Smuzhiyun rk3308_codec_hpf_get, rk3308_codec_hpf_put),
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun /* DAC LINEOUT */
578*4882a593Smuzhiyun SOC_SINGLE_TLV("DAC LINEOUT Left Volume",
579*4882a593Smuzhiyun RK3308_DAC_ANA_CON04,
580*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_GAIN_SFT,
581*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_GAIN_MAX,
582*4882a593Smuzhiyun 0, rk3308_codec_dac_lineout_gain_tlv),
583*4882a593Smuzhiyun SOC_SINGLE_TLV("DAC LINEOUT Right Volume",
584*4882a593Smuzhiyun RK3308_DAC_ANA_CON04,
585*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_GAIN_SFT,
586*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_GAIN_MAX,
587*4882a593Smuzhiyun 0, rk3308_codec_dac_lineout_gain_tlv),
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun /* DAC HPOUT */
590*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("DAC HPOUT Left Volume",
591*4882a593Smuzhiyun RK3308_DAC_ANA_CON05,
592*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_SFT,
593*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_MAX,
594*4882a593Smuzhiyun 0,
595*4882a593Smuzhiyun rk3308_codec_hpout_l_get_tlv,
596*4882a593Smuzhiyun rk3308_codec_hpout_l_put_tlv,
597*4882a593Smuzhiyun rk3308_codec_dac_hpout_gain_tlv),
598*4882a593Smuzhiyun SOC_SINGLE_EXT_TLV("DAC HPOUT Right Volume",
599*4882a593Smuzhiyun RK3308_DAC_ANA_CON06,
600*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_SFT,
601*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_MAX,
602*4882a593Smuzhiyun 0,
603*4882a593Smuzhiyun rk3308_codec_hpout_r_get_tlv,
604*4882a593Smuzhiyun rk3308_codec_hpout_r_put_tlv,
605*4882a593Smuzhiyun rk3308_codec_dac_hpout_gain_tlv),
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun /* DAC HPMIX */
608*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume",
609*4882a593Smuzhiyun RK3308_DAC_ANA_CON12,
610*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_GAIN_SFT,
611*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_GAIN_MIN,
612*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_GAIN_MAX,
613*4882a593Smuzhiyun 0, rk3308_codec_dac_hpmix_gain_tlv),
614*4882a593Smuzhiyun SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume",
615*4882a593Smuzhiyun RK3308_DAC_ANA_CON12,
616*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_GAIN_SFT,
617*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_GAIN_MIN,
618*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_GAIN_MAX,
619*4882a593Smuzhiyun 0, rk3308_codec_dac_hpmix_gain_tlv),
620*4882a593Smuzhiyun };
621*4882a593Smuzhiyun
rk3308_codec_mic_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)622*4882a593Smuzhiyun static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol,
623*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
626*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
627*4882a593Smuzhiyun struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
628*4882a593Smuzhiyun unsigned int value;
629*4882a593Smuzhiyun int grp = e->reg;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
632*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
633*4882a593Smuzhiyun "%s: Invalid ADC grp: %d\n", __func__, e->reg);
634*4882a593Smuzhiyun return -EINVAL;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun if (e->shift_l) {
638*4882a593Smuzhiyun /* ADC MIC Right Mute/Work Infos */
639*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value);
640*4882a593Smuzhiyun rk3308->mic_mute_r[e->reg] = (value & RK3308_ADC_R_CH_BIST_SINE) >>
641*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_SFT;
642*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk3308->mic_mute_r[e->reg];
643*4882a593Smuzhiyun } else {
644*4882a593Smuzhiyun /* ADC MIC Left Mute/Work Infos */
645*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value);
646*4882a593Smuzhiyun rk3308->mic_mute_l[e->reg] = (value & RK3308_ADC_L_CH_BIST_SINE) >>
647*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_SFT;
648*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk3308->mic_mute_l[e->reg];
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun return 0;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
rk3308_codec_mic_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)654*4882a593Smuzhiyun static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
655*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
656*4882a593Smuzhiyun {
657*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
658*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
659*4882a593Smuzhiyun struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
660*4882a593Smuzhiyun unsigned int value;
661*4882a593Smuzhiyun int grp = e->reg;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
664*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
665*4882a593Smuzhiyun "%s: Invalid ADC grp: %d\n", __func__, e->reg);
666*4882a593Smuzhiyun return -EINVAL;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun if (e->shift_l) {
670*4882a593Smuzhiyun /* ADC MIC Right Mute/Work Configuration */
671*4882a593Smuzhiyun value = ucontrol->value.integer.value[0] << RK3308_ADC_R_CH_BIST_SFT;
672*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp),
673*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_SINE,
674*4882a593Smuzhiyun value);
675*4882a593Smuzhiyun rk3308->mic_mute_r[e->reg] = ucontrol->value.integer.value[0];
676*4882a593Smuzhiyun } else {
677*4882a593Smuzhiyun /* ADC MIC Left Mute/Work Configuration */
678*4882a593Smuzhiyun value = ucontrol->value.integer.value[0] << RK3308_ADC_L_CH_BIST_SFT;
679*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp),
680*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_SINE,
681*4882a593Smuzhiyun value);
682*4882a593Smuzhiyun rk3308->mic_mute_l[e->reg] = ucontrol->value.integer.value[0];
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun return 0;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
rk3308_codec_micbias_volts_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)688*4882a593Smuzhiyun static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol,
689*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
692*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk3308->micbias_volt;
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun return 0;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
rk3308_codec_micbias_volts_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)699*4882a593Smuzhiyun static int rk3308_codec_micbias_volts_put(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 rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
704*4882a593Smuzhiyun unsigned int volt = ucontrol->value.integer.value[0];
705*4882a593Smuzhiyun int ret;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun ret = check_micbias(volt);
708*4882a593Smuzhiyun if (ret < 0) {
709*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "The invalid micbias volt: %d\n",
710*4882a593Smuzhiyun volt);
711*4882a593Smuzhiyun return ret;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0),
715*4882a593Smuzhiyun RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK,
716*4882a593Smuzhiyun volt);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun rk3308->micbias_volt = volt;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun return 0;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
rk3308_codec_main_micbias_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)723*4882a593Smuzhiyun static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol,
724*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
727*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk3308->enable_micbias;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun return 0;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
rk3308_codec_main_micbias_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)734*4882a593Smuzhiyun static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol,
735*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
738*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
739*4882a593Smuzhiyun unsigned int on = ucontrol->value.integer.value[0];
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun if (on) {
742*4882a593Smuzhiyun if (!rk3308->enable_micbias)
743*4882a593Smuzhiyun rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt);
744*4882a593Smuzhiyun } else {
745*4882a593Smuzhiyun if (rk3308->enable_micbias)
746*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun return 0;
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun
rk3308_codec_mic_gain_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)752*4882a593Smuzhiyun static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol,
753*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
754*4882a593Smuzhiyun {
755*4882a593Smuzhiyun return snd_soc_get_volsw_range(kcontrol, ucontrol);
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
rk3308_codec_mic_gain_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)758*4882a593Smuzhiyun static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol,
759*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
762*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
763*4882a593Smuzhiyun unsigned int gain = ucontrol->value.integer.value[0];
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) {
766*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s: invalid mic gain: %d\n",
767*4882a593Smuzhiyun __func__, gain);
768*4882a593Smuzhiyun return -EINVAL;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_A) {
772*4882a593Smuzhiyun /*
773*4882a593Smuzhiyun * From the TRM, there are only suupport 0dB(gain==0) and
774*4882a593Smuzhiyun * 20dB(gain==3) on the codec version A.
775*4882a593Smuzhiyun */
776*4882a593Smuzhiyun if (!(gain == 0 || gain == RK3308_ADC_CH1_MIC_GAIN_MAX)) {
777*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
778*4882a593Smuzhiyun "version A doesn't supported: %d, expect: 0,%d\n",
779*4882a593Smuzhiyun gain, RK3308_ADC_CH1_MIC_GAIN_MAX);
780*4882a593Smuzhiyun return 0;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun return snd_soc_put_volsw_range(kcontrol, ucontrol);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
rk3308_codec_hpf_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)787*4882a593Smuzhiyun static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol,
788*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
791*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
792*4882a593Smuzhiyun struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
793*4882a593Smuzhiyun unsigned int value;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
796*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
797*4882a593Smuzhiyun "%s: Invalid ADC grp: %d\n", __func__, e->reg);
798*4882a593Smuzhiyun return -EINVAL;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), &value);
802*4882a593Smuzhiyun if (value & RK3308_ADC_HPF_PATH_MSK)
803*4882a593Smuzhiyun rk3308->hpf_cutoff[e->reg] = 0;
804*4882a593Smuzhiyun else
805*4882a593Smuzhiyun rk3308->hpf_cutoff[e->reg] = 1;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk3308->hpf_cutoff[e->reg];
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun return 0;
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun
rk3308_codec_hpf_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)812*4882a593Smuzhiyun static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol,
813*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
816*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
817*4882a593Smuzhiyun struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
818*4882a593Smuzhiyun unsigned int value = ucontrol->value.integer.value[0];
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
821*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
822*4882a593Smuzhiyun "%s: Invalid ADC grp: %d\n", __func__, e->reg);
823*4882a593Smuzhiyun return -EINVAL;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun if (value) {
827*4882a593Smuzhiyun /* Enable high pass filter for ADCs */
828*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg),
829*4882a593Smuzhiyun RK3308_ADC_HPF_PATH_MSK,
830*4882a593Smuzhiyun RK3308_ADC_HPF_PATH_EN);
831*4882a593Smuzhiyun } else {
832*4882a593Smuzhiyun /* Disable high pass filter for ADCs. */
833*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg),
834*4882a593Smuzhiyun RK3308_ADC_HPF_PATH_MSK,
835*4882a593Smuzhiyun RK3308_ADC_HPF_PATH_DIS);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun rk3308->hpf_cutoff[e->reg] = value;
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun return 0;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun
rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)843*4882a593Smuzhiyun static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol,
844*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun return snd_soc_get_volsw_range(kcontrol, ucontrol);
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)849*4882a593Smuzhiyun static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol,
850*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
853*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
854*4882a593Smuzhiyun unsigned int dgain = ucontrol->value.integer.value[0];
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) {
857*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s: invalid l_dgain: %d\n",
858*4882a593Smuzhiyun __func__, dgain);
859*4882a593Smuzhiyun return -EINVAL;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun rk3308->hpout_l_dgain = dgain;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun return snd_soc_put_volsw_range(kcontrol, ucontrol);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)867*4882a593Smuzhiyun static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol,
868*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun return snd_soc_get_volsw_range(kcontrol, ucontrol);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)873*4882a593Smuzhiyun static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol,
874*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
877*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
878*4882a593Smuzhiyun unsigned int dgain = ucontrol->value.integer.value[0];
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) {
881*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s: invalid r_dgain: %d\n",
882*4882a593Smuzhiyun __func__, dgain);
883*4882a593Smuzhiyun return -EINVAL;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun rk3308->hpout_r_dgain = dgain;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun return snd_soc_put_volsw_range(kcontrol, ucontrol);
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
to_mapped_grp(struct rk3308_codec_priv * rk3308,int idx)891*4882a593Smuzhiyun static u32 to_mapped_grp(struct rk3308_codec_priv *rk3308, int idx)
892*4882a593Smuzhiyun {
893*4882a593Smuzhiyun return rk3308->i2s_sdis[idx];
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
adc_for_each_grp(struct rk3308_codec_priv * rk3308,int type,int idx,u32 * grp)896*4882a593Smuzhiyun static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308,
897*4882a593Smuzhiyun int type, int idx, u32 *grp)
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun if (type == ADC_TYPE_NORMAL) {
900*4882a593Smuzhiyun u32 mapped_grp = to_mapped_grp(rk3308, idx);
901*4882a593Smuzhiyun int max_grps;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (rk3308->enable_all_adcs)
904*4882a593Smuzhiyun max_grps = ADC_LR_GROUP_MAX;
905*4882a593Smuzhiyun else
906*4882a593Smuzhiyun max_grps = rk3308->used_adc_grps;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun if (idx >= max_grps)
909*4882a593Smuzhiyun return false;
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun if ((!rk3308->loopback_dacs_enabled) &&
912*4882a593Smuzhiyun handle_loopback(rk3308) &&
913*4882a593Smuzhiyun rk3308->loopback_grp == mapped_grp) {
914*4882a593Smuzhiyun /*
915*4882a593Smuzhiyun * Ths loopback DACs are closed, and specify the
916*4882a593Smuzhiyun * loopback ADCs.
917*4882a593Smuzhiyun */
918*4882a593Smuzhiyun *grp = ADC_GRP_SKIP_MAGIC;
919*4882a593Smuzhiyun } else if (rk3308->en_always_grps_num &&
920*4882a593Smuzhiyun rk3308->skip_grps[mapped_grp]) {
921*4882a593Smuzhiyun /* To set the skip flag if the ADC GRP is enabled. */
922*4882a593Smuzhiyun *grp = ADC_GRP_SKIP_MAGIC;
923*4882a593Smuzhiyun } else {
924*4882a593Smuzhiyun *grp = mapped_grp;
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun dev_dbg(rk3308->plat_dev,
928*4882a593Smuzhiyun "ADC_TYPE_NORMAL, idx: %d, mapped_grp: %d, get grp: %d,\n",
929*4882a593Smuzhiyun idx, mapped_grp, *grp);
930*4882a593Smuzhiyun } else if (type == ADC_TYPE_ALL) {
931*4882a593Smuzhiyun if (idx >= ADC_LR_GROUP_MAX)
932*4882a593Smuzhiyun return false;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun *grp = idx;
935*4882a593Smuzhiyun dev_dbg(rk3308->plat_dev,
936*4882a593Smuzhiyun "ADC_TYPE_ALL, idx: %d, get grp: %d\n",
937*4882a593Smuzhiyun idx, *grp);
938*4882a593Smuzhiyun } else if (type == ADC_TYPE_DBG) {
939*4882a593Smuzhiyun if (idx >= ADC_LR_GROUP_MAX)
940*4882a593Smuzhiyun return false;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (idx == (int)rk3308->cur_dbg_grp)
943*4882a593Smuzhiyun *grp = idx;
944*4882a593Smuzhiyun else
945*4882a593Smuzhiyun *grp = ADC_GRP_SKIP_MAGIC;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun dev_dbg(rk3308->plat_dev,
948*4882a593Smuzhiyun "ADC_TYPE_DBG, idx: %d, get grp: %d\n",
949*4882a593Smuzhiyun idx, *grp);
950*4882a593Smuzhiyun } else {
951*4882a593Smuzhiyun if (idx >= 1)
952*4882a593Smuzhiyun return false;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun *grp = rk3308->loopback_grp;
955*4882a593Smuzhiyun dev_dbg(rk3308->plat_dev,
956*4882a593Smuzhiyun "ADC_TYPE_LOOPBACK, idx: %d, get grp: %d\n",
957*4882a593Smuzhiyun idx, *grp);
958*4882a593Smuzhiyun }
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun return true;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
rk3308_codec_get_dac_path_state(struct rk3308_codec_priv * rk3308)963*4882a593Smuzhiyun static int rk3308_codec_get_dac_path_state(struct rk3308_codec_priv *rk3308)
964*4882a593Smuzhiyun {
965*4882a593Smuzhiyun return rk3308->dac_path_state;
966*4882a593Smuzhiyun }
967*4882a593Smuzhiyun
rk3308_codec_set_dac_path_state(struct rk3308_codec_priv * rk3308,int state)968*4882a593Smuzhiyun static void rk3308_codec_set_dac_path_state(struct rk3308_codec_priv *rk3308,
969*4882a593Smuzhiyun int state)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun rk3308->dac_path_state = state;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
rk3308_headphone_ctl(struct rk3308_codec_priv * rk3308,int on)974*4882a593Smuzhiyun static void rk3308_headphone_ctl(struct rk3308_codec_priv *rk3308, int on)
975*4882a593Smuzhiyun {
976*4882a593Smuzhiyun if (rk3308->hp_ctl_gpio)
977*4882a593Smuzhiyun gpiod_direction_output(rk3308->hp_ctl_gpio, on);
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun
rk3308_speaker_ctl(struct rk3308_codec_priv * rk3308,int on)980*4882a593Smuzhiyun static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun if (on) {
983*4882a593Smuzhiyun if (rk3308->pa_drv_gpio) {
984*4882a593Smuzhiyun gpiod_direction_output(rk3308->pa_drv_gpio, on);
985*4882a593Smuzhiyun msleep(rk3308->delay_pa_drv_ms);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (rk3308->spk_ctl_gpio)
989*4882a593Smuzhiyun gpiod_direction_output(rk3308->spk_ctl_gpio, on);
990*4882a593Smuzhiyun } else {
991*4882a593Smuzhiyun if (rk3308->spk_ctl_gpio)
992*4882a593Smuzhiyun gpiod_direction_output(rk3308->spk_ctl_gpio, on);
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun if (rk3308->pa_drv_gpio) {
995*4882a593Smuzhiyun msleep(rk3308->delay_pa_drv_ms);
996*4882a593Smuzhiyun gpiod_direction_output(rk3308->pa_drv_gpio, on);
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
rk3308_codec_reset(struct snd_soc_component * component)1001*4882a593Smuzhiyun static int rk3308_codec_reset(struct snd_soc_component *component)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun reset_control_assert(rk3308->reset);
1006*4882a593Smuzhiyun usleep_range(10000, 11000); /* estimated value */
1007*4882a593Smuzhiyun reset_control_deassert(rk3308->reset);
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00);
1010*4882a593Smuzhiyun usleep_range(10000, 11000); /* estimated value */
1011*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308_GLB_CON,
1012*4882a593Smuzhiyun RK3308_SYS_WORK |
1013*4882a593Smuzhiyun RK3308_DAC_DIG_WORK |
1014*4882a593Smuzhiyun RK3308_ADC_DIG_WORK);
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun return 0;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
rk3308_codec_adc_dig_reset(struct rk3308_codec_priv * rk3308)1019*4882a593Smuzhiyun static int rk3308_codec_adc_dig_reset(struct rk3308_codec_priv *rk3308)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1022*4882a593Smuzhiyun RK3308_ADC_DIG_WORK,
1023*4882a593Smuzhiyun RK3308_ADC_DIG_RESET);
1024*4882a593Smuzhiyun udelay(50);
1025*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1026*4882a593Smuzhiyun RK3308_ADC_DIG_WORK,
1027*4882a593Smuzhiyun RK3308_ADC_DIG_WORK);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun return 0;
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
rk3308_codec_dac_dig_reset(struct rk3308_codec_priv * rk3308)1032*4882a593Smuzhiyun static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308)
1033*4882a593Smuzhiyun {
1034*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1035*4882a593Smuzhiyun RK3308_DAC_DIG_WORK,
1036*4882a593Smuzhiyun RK3308_DAC_DIG_RESET);
1037*4882a593Smuzhiyun usleep_range(10000, 11000);
1038*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1039*4882a593Smuzhiyun RK3308_DAC_DIG_WORK,
1040*4882a593Smuzhiyun RK3308_DAC_DIG_WORK);
1041*4882a593Smuzhiyun
1042*4882a593Smuzhiyun return 0;
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun
rk3308_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)1045*4882a593Smuzhiyun static int rk3308_set_bias_level(struct snd_soc_component *component,
1046*4882a593Smuzhiyun enum snd_soc_bias_level level)
1047*4882a593Smuzhiyun {
1048*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun switch (level) {
1051*4882a593Smuzhiyun case SND_SOC_BIAS_ON:
1052*4882a593Smuzhiyun break;
1053*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
1054*4882a593Smuzhiyun break;
1055*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
1056*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
1057*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
1058*4882a593Smuzhiyun break;
1059*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
1060*4882a593Smuzhiyun break;
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun return 0;
1064*4882a593Smuzhiyun }
1065*4882a593Smuzhiyun
rk3308_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)1066*4882a593Smuzhiyun static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai,
1067*4882a593Smuzhiyun unsigned int fmt)
1068*4882a593Smuzhiyun {
1069*4882a593Smuzhiyun struct snd_soc_component *component = codec_dai->component;
1070*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
1071*4882a593Smuzhiyun unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0;
1072*4882a593Smuzhiyun int idx, grp, is_master;
1073*4882a593Smuzhiyun int type = ADC_TYPE_ALL;
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1076*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
1077*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE;
1078*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_MODE_SLAVE;
1079*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
1080*4882a593Smuzhiyun dac_aif2 |= RK3308BS_DAC_IO_MODE_SLAVE;
1081*4882a593Smuzhiyun dac_aif2 |= RK3308BS_DAC_MODE_SLAVE;
1082*4882a593Smuzhiyun } else {
1083*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE;
1084*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_MODE_SLAVE;
1085*4882a593Smuzhiyun }
1086*4882a593Smuzhiyun is_master = 0;
1087*4882a593Smuzhiyun break;
1088*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
1089*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_IO_MODE_MASTER;
1090*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_MODE_MASTER;
1091*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
1092*4882a593Smuzhiyun dac_aif2 |= RK3308BS_DAC_IO_MODE_MASTER;
1093*4882a593Smuzhiyun dac_aif2 |= RK3308BS_DAC_MODE_MASTER;
1094*4882a593Smuzhiyun } else {
1095*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_IO_MODE_MASTER;
1096*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_MODE_MASTER;
1097*4882a593Smuzhiyun }
1098*4882a593Smuzhiyun is_master = 1;
1099*4882a593Smuzhiyun break;
1100*4882a593Smuzhiyun default:
1101*4882a593Smuzhiyun return -EINVAL;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1105*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_A:
1106*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_MODE_PCM;
1107*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_MODE_PCM;
1108*4882a593Smuzhiyun break;
1109*4882a593Smuzhiyun case SND_SOC_DAIFMT_I2S:
1110*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_MODE_I2S;
1111*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_MODE_I2S;
1112*4882a593Smuzhiyun break;
1113*4882a593Smuzhiyun case SND_SOC_DAIFMT_RIGHT_J:
1114*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_MODE_RJ;
1115*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_MODE_RJ;
1116*4882a593Smuzhiyun break;
1117*4882a593Smuzhiyun case SND_SOC_DAIFMT_LEFT_J:
1118*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_MODE_LJ;
1119*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_MODE_LJ;
1120*4882a593Smuzhiyun break;
1121*4882a593Smuzhiyun default:
1122*4882a593Smuzhiyun return -EINVAL;
1123*4882a593Smuzhiyun }
1124*4882a593Smuzhiyun
1125*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1126*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_NF:
1127*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL;
1128*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL;
1129*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL;
1130*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL;
1131*4882a593Smuzhiyun break;
1132*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_IF:
1133*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL;
1134*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL;
1135*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL;
1136*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL;
1137*4882a593Smuzhiyun break;
1138*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_NF:
1139*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL;
1140*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL;
1141*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL;
1142*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL;
1143*4882a593Smuzhiyun break;
1144*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_IF:
1145*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL;
1146*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL;
1147*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL;
1148*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL;
1149*4882a593Smuzhiyun break;
1150*4882a593Smuzhiyun default:
1151*4882a593Smuzhiyun return -EINVAL;
1152*4882a593Smuzhiyun }
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun /*
1155*4882a593Smuzhiyun * Hold ADC Digital registers start at master mode
1156*4882a593Smuzhiyun *
1157*4882a593Smuzhiyun * There are 8 ADCs and use the same SCLK and LRCK internal for master
1158*4882a593Smuzhiyun * mode, We need to make sure that they are in effect at the same time,
1159*4882a593Smuzhiyun * otherwise they will cause the abnormal clocks.
1160*4882a593Smuzhiyun */
1161*4882a593Smuzhiyun if (is_master)
1162*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1163*4882a593Smuzhiyun RK3308_ADC_DIG_WORK,
1164*4882a593Smuzhiyun RK3308_ADC_DIG_RESET);
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
1167*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
1168*4882a593Smuzhiyun continue;
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp),
1171*4882a593Smuzhiyun RK3308_ADC_I2S_LRC_POL_MSK |
1172*4882a593Smuzhiyun RK3308_ADC_I2S_MODE_MSK,
1173*4882a593Smuzhiyun adc_aif1);
1174*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp),
1175*4882a593Smuzhiyun RK3308_ADC_IO_MODE_MSK |
1176*4882a593Smuzhiyun RK3308_ADC_MODE_MSK |
1177*4882a593Smuzhiyun RK3308_ADC_I2S_BIT_CLK_POL_MSK,
1178*4882a593Smuzhiyun adc_aif2);
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun /* Hold ADC Digital registers end at master mode */
1182*4882a593Smuzhiyun if (is_master)
1183*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
1184*4882a593Smuzhiyun RK3308_ADC_DIG_WORK,
1185*4882a593Smuzhiyun RK3308_ADC_DIG_WORK);
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01,
1188*4882a593Smuzhiyun RK3308_DAC_I2S_LRC_POL_MSK |
1189*4882a593Smuzhiyun RK3308_DAC_I2S_MODE_MSK,
1190*4882a593Smuzhiyun dac_aif1);
1191*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
1192*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02,
1193*4882a593Smuzhiyun RK3308BS_DAC_IO_MODE_MSK |
1194*4882a593Smuzhiyun RK3308BS_DAC_MODE_MSK |
1195*4882a593Smuzhiyun RK3308_DAC_I2S_BIT_CLK_POL_MSK,
1196*4882a593Smuzhiyun dac_aif2);
1197*4882a593Smuzhiyun } else {
1198*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02,
1199*4882a593Smuzhiyun RK3308_DAC_IO_MODE_MSK |
1200*4882a593Smuzhiyun RK3308_DAC_MODE_MSK |
1201*4882a593Smuzhiyun RK3308_DAC_I2S_BIT_CLK_POL_MSK,
1202*4882a593Smuzhiyun dac_aif2);
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun return 0;
1206*4882a593Smuzhiyun }
1207*4882a593Smuzhiyun
rk3308_codec_dac_dig_config(struct rk3308_codec_priv * rk3308,struct snd_pcm_hw_params * params)1208*4882a593Smuzhiyun static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308,
1209*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
1210*4882a593Smuzhiyun {
1211*4882a593Smuzhiyun unsigned int dac_aif1 = 0, dac_aif2 = 0;
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun /* Clear the status of DAC DIG Digital reigisters */
1214*4882a593Smuzhiyun rk3308_codec_dac_dig_reset(rk3308);
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun switch (params_format(params)) {
1217*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
1218*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS;
1219*4882a593Smuzhiyun break;
1220*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S20_3LE:
1221*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS;
1222*4882a593Smuzhiyun break;
1223*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
1224*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS;
1225*4882a593Smuzhiyun break;
1226*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
1227*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS;
1228*4882a593Smuzhiyun break;
1229*4882a593Smuzhiyun default:
1230*4882a593Smuzhiyun return -EINVAL;
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL;
1234*4882a593Smuzhiyun dac_aif2 |= RK3308_DAC_I2S_WORK;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01,
1237*4882a593Smuzhiyun RK3308_DAC_I2S_VALID_LEN_MSK |
1238*4882a593Smuzhiyun RK3308_DAC_I2S_LR_MSK,
1239*4882a593Smuzhiyun dac_aif1);
1240*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02,
1241*4882a593Smuzhiyun RK3308_DAC_I2S_MSK,
1242*4882a593Smuzhiyun dac_aif2);
1243*4882a593Smuzhiyun
1244*4882a593Smuzhiyun return 0;
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun
rk3308_codec_adc_dig_config(struct rk3308_codec_priv * rk3308,struct snd_pcm_hw_params * params)1247*4882a593Smuzhiyun static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308,
1248*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun unsigned int adc_aif1 = 0, adc_aif2 = 0;
1251*4882a593Smuzhiyun int type = ADC_TYPE_NORMAL;
1252*4882a593Smuzhiyun int idx, grp;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun /* Clear the status of ADC DIG Digital reigisters */
1255*4882a593Smuzhiyun rk3308_codec_adc_dig_reset(rk3308);
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun switch (params_format(params)) {
1258*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
1259*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS;
1260*4882a593Smuzhiyun break;
1261*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S20_3LE:
1262*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS;
1263*4882a593Smuzhiyun break;
1264*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
1265*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS;
1266*4882a593Smuzhiyun break;
1267*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
1268*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS;
1269*4882a593Smuzhiyun break;
1270*4882a593Smuzhiyun default:
1271*4882a593Smuzhiyun return -EINVAL;
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun
1274*4882a593Smuzhiyun switch (params_channels(params)) {
1275*4882a593Smuzhiyun case 1:
1276*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_MONO;
1277*4882a593Smuzhiyun break;
1278*4882a593Smuzhiyun case 2:
1279*4882a593Smuzhiyun case 4:
1280*4882a593Smuzhiyun case 6:
1281*4882a593Smuzhiyun case 8:
1282*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_STEREO;
1283*4882a593Smuzhiyun break;
1284*4882a593Smuzhiyun default:
1285*4882a593Smuzhiyun return -EINVAL;
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL;
1289*4882a593Smuzhiyun adc_aif2 |= RK3308_ADC_I2S_WORK;
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
1292*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
1293*4882a593Smuzhiyun continue;
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp),
1296*4882a593Smuzhiyun RK3308_ADC_I2S_VALID_LEN_MSK |
1297*4882a593Smuzhiyun RK3308_ADC_I2S_LR_MSK |
1298*4882a593Smuzhiyun RK3308_ADC_I2S_TYPE_MSK,
1299*4882a593Smuzhiyun adc_aif1);
1300*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp),
1301*4882a593Smuzhiyun RK3308_ADC_I2S_MSK,
1302*4882a593Smuzhiyun adc_aif2);
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun
1305*4882a593Smuzhiyun return 0;
1306*4882a593Smuzhiyun }
1307*4882a593Smuzhiyun
rk3308_codec_update_adc_grps(struct rk3308_codec_priv * rk3308,struct snd_pcm_hw_params * params)1308*4882a593Smuzhiyun static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308,
1309*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun switch (params_channels(params)) {
1312*4882a593Smuzhiyun case 1:
1313*4882a593Smuzhiyun rk3308->used_adc_grps = 1;
1314*4882a593Smuzhiyun break;
1315*4882a593Smuzhiyun case 2:
1316*4882a593Smuzhiyun case 4:
1317*4882a593Smuzhiyun case 6:
1318*4882a593Smuzhiyun case 8:
1319*4882a593Smuzhiyun rk3308->used_adc_grps = params_channels(params) / 2;
1320*4882a593Smuzhiyun break;
1321*4882a593Smuzhiyun default:
1322*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "Invalid channels: %d\n",
1323*4882a593Smuzhiyun params_channels(params));
1324*4882a593Smuzhiyun return -EINVAL;
1325*4882a593Smuzhiyun }
1326*4882a593Smuzhiyun
1327*4882a593Smuzhiyun return 0;
1328*4882a593Smuzhiyun }
1329*4882a593Smuzhiyun
rk3308_mute_stream(struct snd_soc_dai * dai,int mute,int stream)1330*4882a593Smuzhiyun static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
1331*4882a593Smuzhiyun {
1332*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1333*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1336*4882a593Smuzhiyun int dgain;
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun if (mute) {
1339*4882a593Smuzhiyun if (rk3308->codec_ver <= ACODEC_VERSION_B) {
1340*4882a593Smuzhiyun for (dgain = 0x2; dgain <= 0x7; dgain++) {
1341*4882a593Smuzhiyun /*
1342*4882a593Smuzhiyun * Keep the max -> min digital CIC interpolation
1343*4882a593Smuzhiyun * filter gain step by step.
1344*4882a593Smuzhiyun *
1345*4882a593Smuzhiyun * loud: 0x2; whisper: 0x7
1346*4882a593Smuzhiyun */
1347*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
1348*4882a593Smuzhiyun RK3308_DAC_DIG_CON04,
1349*4882a593Smuzhiyun RK3308_DAC_CIC_IF_GAIN_MSK,
1350*4882a593Smuzhiyun dgain);
1351*4882a593Smuzhiyun usleep_range(200, 300); /* estimated value */
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun #if !DEBUG_POP_ALWAYS
1356*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 0);
1357*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 0);
1358*4882a593Smuzhiyun #endif
1359*4882a593Smuzhiyun } else {
1360*4882a593Smuzhiyun #if !DEBUG_POP_ALWAYS
1361*4882a593Smuzhiyun if (rk3308->dac_output == DAC_LINEOUT)
1362*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 1);
1363*4882a593Smuzhiyun else if (rk3308->dac_output == DAC_HPOUT)
1364*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 1);
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun if (rk3308->delay_start_play_ms)
1367*4882a593Smuzhiyun msleep(rk3308->delay_start_play_ms);
1368*4882a593Smuzhiyun #endif
1369*4882a593Smuzhiyun if (rk3308->codec_ver <= ACODEC_VERSION_B) {
1370*4882a593Smuzhiyun for (dgain = 0x7; dgain >= 0x2; dgain--) {
1371*4882a593Smuzhiyun /*
1372*4882a593Smuzhiyun * Keep the min -> max digital CIC interpolation
1373*4882a593Smuzhiyun * filter gain step by step
1374*4882a593Smuzhiyun *
1375*4882a593Smuzhiyun * loud: 0x2; whisper: 0x7
1376*4882a593Smuzhiyun */
1377*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
1378*4882a593Smuzhiyun RK3308_DAC_DIG_CON04,
1379*4882a593Smuzhiyun RK3308_DAC_CIC_IF_GAIN_MSK,
1380*4882a593Smuzhiyun dgain);
1381*4882a593Smuzhiyun usleep_range(200, 300); /* estimated value */
1382*4882a593Smuzhiyun }
1383*4882a593Smuzhiyun }
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun }
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun return 0;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun
rk3308_codec_digital_fadein(struct rk3308_codec_priv * rk3308)1390*4882a593Smuzhiyun static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308)
1391*4882a593Smuzhiyun {
1392*4882a593Smuzhiyun unsigned int dgain, dgain_ref;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) {
1395*4882a593Smuzhiyun pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
1396*4882a593Smuzhiyun rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
1397*4882a593Smuzhiyun dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
1398*4882a593Smuzhiyun } else {
1399*4882a593Smuzhiyun dgain_ref = rk3308->hpout_l_dgain;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun
1402*4882a593Smuzhiyun /*
1403*4882a593Smuzhiyun * We'd better change the gain of the left and right channels
1404*4882a593Smuzhiyun * at the same time to avoid different listening
1405*4882a593Smuzhiyun */
1406*4882a593Smuzhiyun for (dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39;
1407*4882a593Smuzhiyun dgain <= dgain_ref; dgain++) {
1408*4882a593Smuzhiyun /* Step 02 decrease dgains for de-pop */
1409*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
1410*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_MSK,
1411*4882a593Smuzhiyun dgain);
1412*4882a593Smuzhiyun
1413*4882a593Smuzhiyun /* Step 02 decrease dgains for de-pop */
1414*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
1415*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_MSK,
1416*4882a593Smuzhiyun dgain);
1417*4882a593Smuzhiyun }
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun return 0;
1420*4882a593Smuzhiyun }
1421*4882a593Smuzhiyun
rk3308_codec_digital_fadeout(struct rk3308_codec_priv * rk3308)1422*4882a593Smuzhiyun static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308)
1423*4882a593Smuzhiyun {
1424*4882a593Smuzhiyun unsigned int l_dgain, r_dgain;
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun /*
1427*4882a593Smuzhiyun * Note. In the step2, adjusting the register step by step to
1428*4882a593Smuzhiyun * the appropriate value and taking 20ms as time step
1429*4882a593Smuzhiyun */
1430*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain);
1431*4882a593Smuzhiyun l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain);
1434*4882a593Smuzhiyun r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK;
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun if (l_dgain != r_dgain) {
1437*4882a593Smuzhiyun pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
1438*4882a593Smuzhiyun l_dgain, r_dgain);
1439*4882a593Smuzhiyun l_dgain = min(l_dgain, r_dgain);
1440*4882a593Smuzhiyun }
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun /*
1443*4882a593Smuzhiyun * We'd better change the gain of the left and right channels
1444*4882a593Smuzhiyun * at the same time to avoid different listening
1445*4882a593Smuzhiyun */
1446*4882a593Smuzhiyun while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) {
1447*4882a593Smuzhiyun /* Step 02 decrease dgains for de-pop */
1448*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
1449*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_MSK,
1450*4882a593Smuzhiyun l_dgain);
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun /* Step 02 decrease dgains for de-pop */
1453*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
1454*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_MSK,
1455*4882a593Smuzhiyun l_dgain);
1456*4882a593Smuzhiyun
1457*4882a593Smuzhiyun usleep_range(200, 300); /* estimated value */
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39)
1460*4882a593Smuzhiyun break;
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun l_dgain--;
1463*4882a593Smuzhiyun }
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun return 0;
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun
rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv * rk3308)1468*4882a593Smuzhiyun static int rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv *rk3308)
1469*4882a593Smuzhiyun {
1470*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
1471*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
1472*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
1473*4882a593Smuzhiyun RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL |
1474*4882a593Smuzhiyun RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun udelay(20);
1477*4882a593Smuzhiyun
1478*4882a593Smuzhiyun /* Step 07 */
1479*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1480*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1481*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN,
1482*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1483*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN);
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun udelay(20);
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun /* Step 19 */
1488*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1489*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1490*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE,
1491*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1492*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE);
1493*4882a593Smuzhiyun udelay(20);
1494*4882a593Smuzhiyun
1495*4882a593Smuzhiyun return 0;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun
rk3308_codec_dac_lineout_disable(struct rk3308_codec_priv * rk3308)1498*4882a593Smuzhiyun static int rk3308_codec_dac_lineout_disable(struct rk3308_codec_priv *rk3308)
1499*4882a593Smuzhiyun {
1500*4882a593Smuzhiyun /* Step 08 */
1501*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1502*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1503*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE,
1504*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_MUTE |
1505*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_MUTE);
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun /* Step 09 */
1508*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1509*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1510*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN,
1511*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_DIS |
1512*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_DIS);
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
1515*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
1516*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
1517*4882a593Smuzhiyun RK3308_DAC_L_SEL_DC_FROM_INTERNAL |
1518*4882a593Smuzhiyun RK3308_DAC_R_SEL_DC_FROM_INTERNAL);
1519*4882a593Smuzhiyun
1520*4882a593Smuzhiyun return 0;
1521*4882a593Smuzhiyun }
1522*4882a593Smuzhiyun
rk3308_codec_dac_hpout_enable(struct rk3308_codec_priv * rk3308)1523*4882a593Smuzhiyun static int rk3308_codec_dac_hpout_enable(struct rk3308_codec_priv *rk3308)
1524*4882a593Smuzhiyun {
1525*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
1526*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_MSK |
1527*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
1528*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_WORK |
1529*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_WORK);
1530*4882a593Smuzhiyun udelay(20);
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun /* Step 07 */
1533*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1534*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1535*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN,
1536*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1537*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN);
1538*4882a593Smuzhiyun
1539*4882a593Smuzhiyun udelay(20);
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun /* Step 08 */
1542*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1543*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
1544*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK,
1545*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
1546*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK);
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun udelay(20);
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun /* Step 16 */
1551*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1552*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1553*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE,
1554*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1555*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE);
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun udelay(20);
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun return 0;
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun
rk3308_codec_dac_hpout_disable(struct rk3308_codec_priv * rk3308)1562*4882a593Smuzhiyun static int rk3308_codec_dac_hpout_disable(struct rk3308_codec_priv *rk3308)
1563*4882a593Smuzhiyun {
1564*4882a593Smuzhiyun /* Step 07 */
1565*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1566*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1567*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN,
1568*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_DIS |
1569*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_DIS);
1570*4882a593Smuzhiyun
1571*4882a593Smuzhiyun /* Step 08 */
1572*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1573*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
1574*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK,
1575*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_INIT |
1576*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_INIT);
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun /* Step 16 */
1579*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1580*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1581*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE,
1582*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_MUTE |
1583*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_MUTE);
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun udelay(20);
1586*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
1587*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_MSK |
1588*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
1589*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_DIS |
1590*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_DIS);
1591*4882a593Smuzhiyun return 0;
1592*4882a593Smuzhiyun }
1593*4882a593Smuzhiyun
rk3308_codec_dac_switch(struct rk3308_codec_priv * rk3308,int dac_output)1594*4882a593Smuzhiyun static int rk3308_codec_dac_switch(struct rk3308_codec_priv *rk3308,
1595*4882a593Smuzhiyun int dac_output)
1596*4882a593Smuzhiyun { int ret = 0;
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun if (rk3308->dac_output == dac_output) {
1599*4882a593Smuzhiyun dev_info(rk3308->plat_dev,
1600*4882a593Smuzhiyun "Don't need to change dac_output: %d\n", dac_output);
1601*4882a593Smuzhiyun goto out;
1602*4882a593Smuzhiyun }
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun switch (dac_output) {
1605*4882a593Smuzhiyun case DAC_LINEOUT:
1606*4882a593Smuzhiyun case DAC_HPOUT:
1607*4882a593Smuzhiyun case DAC_LINEOUT_HPOUT:
1608*4882a593Smuzhiyun break;
1609*4882a593Smuzhiyun default:
1610*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "Unknown value: %d\n", dac_output);
1611*4882a593Smuzhiyun ret = -EINVAL;
1612*4882a593Smuzhiyun goto out;
1613*4882a593Smuzhiyun }
1614*4882a593Smuzhiyun
1615*4882a593Smuzhiyun if (rk3308_codec_get_dac_path_state(rk3308) == PATH_BUSY) {
1616*4882a593Smuzhiyun /*
1617*4882a593Smuzhiyun * We can only switch the audio path to LINEOUT or HPOUT on
1618*4882a593Smuzhiyun * codec during playbacking, otherwise, just update the
1619*4882a593Smuzhiyun * dac_output flag.
1620*4882a593Smuzhiyun */
1621*4882a593Smuzhiyun switch (dac_output) {
1622*4882a593Smuzhiyun case DAC_LINEOUT:
1623*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 0);
1624*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 1);
1625*4882a593Smuzhiyun rk3308_codec_dac_hpout_disable(rk3308);
1626*4882a593Smuzhiyun rk3308_codec_dac_lineout_enable(rk3308);
1627*4882a593Smuzhiyun break;
1628*4882a593Smuzhiyun case DAC_HPOUT:
1629*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 0);
1630*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 1);
1631*4882a593Smuzhiyun rk3308_codec_dac_lineout_disable(rk3308);
1632*4882a593Smuzhiyun rk3308_codec_dac_hpout_enable(rk3308);
1633*4882a593Smuzhiyun break;
1634*4882a593Smuzhiyun case DAC_LINEOUT_HPOUT:
1635*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 1);
1636*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 1);
1637*4882a593Smuzhiyun rk3308_codec_dac_lineout_enable(rk3308);
1638*4882a593Smuzhiyun rk3308_codec_dac_hpout_enable(rk3308);
1639*4882a593Smuzhiyun break;
1640*4882a593Smuzhiyun default:
1641*4882a593Smuzhiyun break;
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun }
1644*4882a593Smuzhiyun
1645*4882a593Smuzhiyun rk3308->dac_output = dac_output;
1646*4882a593Smuzhiyun out:
1647*4882a593Smuzhiyun dev_dbg(rk3308->plat_dev, "switch dac_output to: %d\n",
1648*4882a593Smuzhiyun rk3308->dac_output);
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun return ret;
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun
rk3308_codec_dac_enable(struct rk3308_codec_priv * rk3308)1653*4882a593Smuzhiyun static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308)
1654*4882a593Smuzhiyun {
1655*4882a593Smuzhiyun /*
1656*4882a593Smuzhiyun * Note1. If the ACODEC_DAC_ANA_CON12[6] or ACODEC_DAC_ANA_CON12[2]
1657*4882a593Smuzhiyun * is set to 0x1, ignoring the step9~12.
1658*4882a593Smuzhiyun */
1659*4882a593Smuzhiyun
1660*4882a593Smuzhiyun /*
1661*4882a593Smuzhiyun * Note2. If the ACODEC_ DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3]
1662*4882a593Smuzhiyun * is set to 0x1, the ADC0 or ADC1 should be enabled firstly, and
1663*4882a593Smuzhiyun * please refer to Enable ADC Configuration Standard Usage Flow(expect
1664*4882a593Smuzhiyun * step7~step9,step14).
1665*4882a593Smuzhiyun */
1666*4882a593Smuzhiyun
1667*4882a593Smuzhiyun /*
1668*4882a593Smuzhiyun * Note3. If no opening the line out, ignoring the step6, step17 and
1669*4882a593Smuzhiyun * step19.
1670*4882a593Smuzhiyun */
1671*4882a593Smuzhiyun
1672*4882a593Smuzhiyun /*
1673*4882a593Smuzhiyun * Note4. If no opening the headphone out, ignoring the step3,step7~8,
1674*4882a593Smuzhiyun * step16 and step18.
1675*4882a593Smuzhiyun */
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun /*
1678*4882a593Smuzhiyun * Note5. In the step18, adjust the register step by step to the
1679*4882a593Smuzhiyun * appropriate value and taking 10ms as one time step
1680*4882a593Smuzhiyun */
1681*4882a593Smuzhiyun
1682*4882a593Smuzhiyun /*
1683*4882a593Smuzhiyun * 1. Set the ACODEC_DAC_ANA_CON0[0] to 0x1, to enable the current
1684*4882a593Smuzhiyun * source of DAC
1685*4882a593Smuzhiyun */
1686*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00,
1687*4882a593Smuzhiyun RK3308_DAC_CURRENT_MSK,
1688*4882a593Smuzhiyun RK3308_DAC_CURRENT_EN);
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun udelay(20);
1691*4882a593Smuzhiyun
1692*4882a593Smuzhiyun /*
1693*4882a593Smuzhiyun * 2. Set the ACODEC_DAC_ANA_CON1[6] and ACODEC_DAC_ANA_CON1[2] to 0x1,
1694*4882a593Smuzhiyun * to enable the reference voltage buffer
1695*4882a593Smuzhiyun */
1696*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
1697*4882a593Smuzhiyun RK3308_DAC_BUF_REF_L_MSK |
1698*4882a593Smuzhiyun RK3308_DAC_BUF_REF_R_MSK,
1699*4882a593Smuzhiyun RK3308_DAC_BUF_REF_L_EN |
1700*4882a593Smuzhiyun RK3308_DAC_BUF_REF_R_EN);
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun /* Waiting the stable reference voltage */
1703*4882a593Smuzhiyun mdelay(1);
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun /* Step 03 */
1706*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
1707*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_MSK |
1708*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
1709*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_WORK |
1710*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_WORK);
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun udelay(20);
1713*4882a593Smuzhiyun
1714*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B &&
1715*4882a593Smuzhiyun (rk3308->dac_output == DAC_LINEOUT ||
1716*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT)) {
1717*4882a593Smuzhiyun /* Step 04 */
1718*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
1719*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
1720*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
1721*4882a593Smuzhiyun RK3308_DAC_L_SEL_DC_FROM_INTERNAL |
1722*4882a593Smuzhiyun RK3308_DAC_R_SEL_DC_FROM_INTERNAL);
1723*4882a593Smuzhiyun
1724*4882a593Smuzhiyun udelay(20);
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun /* Step 05 */
1728*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1729*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_EN |
1730*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_EN,
1731*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_EN |
1732*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_EN);
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun /* Waiting the stable HPMIX */
1735*4882a593Smuzhiyun mdelay(1);
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun /* Step 06. Reset HPMIX and recover HPMIX gains */
1738*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1739*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_WORK |
1740*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_WORK,
1741*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_INIT |
1742*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_INIT);
1743*4882a593Smuzhiyun udelay(50);
1744*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1745*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_WORK |
1746*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_WORK,
1747*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_WORK |
1748*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_WORK);
1749*4882a593Smuzhiyun
1750*4882a593Smuzhiyun udelay(20);
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun if (rk3308->dac_output == DAC_LINEOUT ||
1753*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1754*4882a593Smuzhiyun /* Step 07 */
1755*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1756*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1757*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN,
1758*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1759*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN);
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun udelay(20);
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun
1764*4882a593Smuzhiyun if (rk3308->dac_output == DAC_HPOUT ||
1765*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1766*4882a593Smuzhiyun /* Step 08 */
1767*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1768*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1769*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN,
1770*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1771*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN);
1772*4882a593Smuzhiyun
1773*4882a593Smuzhiyun udelay(20);
1774*4882a593Smuzhiyun
1775*4882a593Smuzhiyun /* Step 09 */
1776*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1777*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
1778*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK,
1779*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
1780*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK);
1781*4882a593Smuzhiyun
1782*4882a593Smuzhiyun udelay(20);
1783*4882a593Smuzhiyun }
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
1786*4882a593Smuzhiyun /* Step 10 */
1787*4882a593Smuzhiyun if (rk3308->dac_output == DAC_HPOUT) {
1788*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
1789*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
1790*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
1791*4882a593Smuzhiyun RK3308_DAC_L_SEL_DC_FROM_INTERNAL |
1792*4882a593Smuzhiyun RK3308_DAC_R_SEL_DC_FROM_INTERNAL);
1793*4882a593Smuzhiyun } else {
1794*4882a593Smuzhiyun /* LINEOUT and LINEOUT + HPOUT */
1795*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
1796*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
1797*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
1798*4882a593Smuzhiyun RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL |
1799*4882a593Smuzhiyun RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL);
1800*4882a593Smuzhiyun }
1801*4882a593Smuzhiyun
1802*4882a593Smuzhiyun udelay(20);
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun /* Step 11 */
1806*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1807*4882a593Smuzhiyun RK3308_DAC_L_REF_EN |
1808*4882a593Smuzhiyun RK3308_DAC_R_REF_EN,
1809*4882a593Smuzhiyun RK3308_DAC_L_REF_EN |
1810*4882a593Smuzhiyun RK3308_DAC_R_REF_EN);
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun udelay(20);
1813*4882a593Smuzhiyun
1814*4882a593Smuzhiyun /* Step 12 */
1815*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1816*4882a593Smuzhiyun RK3308_DAC_L_CLK_EN |
1817*4882a593Smuzhiyun RK3308_DAC_R_CLK_EN,
1818*4882a593Smuzhiyun RK3308_DAC_L_CLK_EN |
1819*4882a593Smuzhiyun RK3308_DAC_R_CLK_EN);
1820*4882a593Smuzhiyun
1821*4882a593Smuzhiyun udelay(20);
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun /* Step 13 */
1824*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1825*4882a593Smuzhiyun RK3308_DAC_L_DAC_EN |
1826*4882a593Smuzhiyun RK3308_DAC_R_DAC_EN,
1827*4882a593Smuzhiyun RK3308_DAC_L_DAC_EN |
1828*4882a593Smuzhiyun RK3308_DAC_R_DAC_EN);
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun udelay(20);
1831*4882a593Smuzhiyun
1832*4882a593Smuzhiyun /* Step 14 */
1833*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1834*4882a593Smuzhiyun RK3308_DAC_L_DAC_WORK |
1835*4882a593Smuzhiyun RK3308_DAC_R_DAC_WORK,
1836*4882a593Smuzhiyun RK3308_DAC_L_DAC_WORK |
1837*4882a593Smuzhiyun RK3308_DAC_R_DAC_WORK);
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun udelay(20);
1840*4882a593Smuzhiyun
1841*4882a593Smuzhiyun /* Step 15 */
1842*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
1843*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_SEL_MSK |
1844*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_SEL_MSK,
1845*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_I2S |
1846*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_I2S);
1847*4882a593Smuzhiyun
1848*4882a593Smuzhiyun udelay(20);
1849*4882a593Smuzhiyun
1850*4882a593Smuzhiyun /* Step 16 */
1851*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1852*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_UNMUTE |
1853*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_UNMUTE,
1854*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_UNMUTE |
1855*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_UNMUTE);
1856*4882a593Smuzhiyun
1857*4882a593Smuzhiyun udelay(20);
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun /* Step 17: Put configuration HPMIX Gain to DAPM */
1860*4882a593Smuzhiyun
1861*4882a593Smuzhiyun if (rk3308->dac_output == DAC_HPOUT ||
1862*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1863*4882a593Smuzhiyun /* Step 18 */
1864*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1865*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1866*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE,
1867*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1868*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE);
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun udelay(20);
1871*4882a593Smuzhiyun }
1872*4882a593Smuzhiyun
1873*4882a593Smuzhiyun if (rk3308->dac_output == DAC_LINEOUT ||
1874*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1875*4882a593Smuzhiyun /* Step 19 */
1876*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1877*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1878*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE,
1879*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1880*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE);
1881*4882a593Smuzhiyun udelay(20);
1882*4882a593Smuzhiyun }
1883*4882a593Smuzhiyun
1884*4882a593Smuzhiyun /* Step 20, put configuration HPOUT gain to DAPM control */
1885*4882a593Smuzhiyun /* Step 21, put configuration LINEOUT gain to DAPM control */
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun if (rk3308->dac_output == DAC_HPOUT ||
1888*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1889*4882a593Smuzhiyun /* Just for HPOUT */
1890*4882a593Smuzhiyun rk3308_codec_digital_fadein(rk3308);
1891*4882a593Smuzhiyun }
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun rk3308->dac_endisable = true;
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun /* TODO: TRY TO TEST DRIVE STRENGTH */
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun return 0;
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun
rk3308_codec_dac_disable(struct rk3308_codec_priv * rk3308)1900*4882a593Smuzhiyun static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308)
1901*4882a593Smuzhiyun {
1902*4882a593Smuzhiyun /*
1903*4882a593Smuzhiyun * Step 00 skipped. Keep the DAC channel work and input the mute signal.
1904*4882a593Smuzhiyun */
1905*4882a593Smuzhiyun
1906*4882a593Smuzhiyun /* Step 01 skipped. May set the min gain for LINEOUT. */
1907*4882a593Smuzhiyun
1908*4882a593Smuzhiyun /* Step 02 skipped. May set the min gain for HPOUT. */
1909*4882a593Smuzhiyun
1910*4882a593Smuzhiyun if (rk3308->dac_output == DAC_HPOUT ||
1911*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT) {
1912*4882a593Smuzhiyun /* Just for HPOUT */
1913*4882a593Smuzhiyun rk3308_codec_digital_fadeout(rk3308);
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun /* Step 03 */
1917*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1918*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_UNMUTE |
1919*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_UNMUTE,
1920*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_UNMUTE |
1921*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_UNMUTE);
1922*4882a593Smuzhiyun
1923*4882a593Smuzhiyun /* Step 04 */
1924*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
1925*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_SEL_MSK |
1926*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_SEL_MSK,
1927*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_NONE |
1928*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_NONE);
1929*4882a593Smuzhiyun /* Step 05 */
1930*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1931*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_UNMUTE |
1932*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_UNMUTE,
1933*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_MUTE |
1934*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_MUTE);
1935*4882a593Smuzhiyun
1936*4882a593Smuzhiyun /* Step 06 */
1937*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1938*4882a593Smuzhiyun RK3308_DAC_L_DAC_WORK |
1939*4882a593Smuzhiyun RK3308_DAC_R_DAC_WORK,
1940*4882a593Smuzhiyun RK3308_DAC_L_DAC_INIT |
1941*4882a593Smuzhiyun RK3308_DAC_R_DAC_INIT);
1942*4882a593Smuzhiyun
1943*4882a593Smuzhiyun /* Step 07 */
1944*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
1945*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_EN |
1946*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_EN,
1947*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_DIS |
1948*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_DIS);
1949*4882a593Smuzhiyun
1950*4882a593Smuzhiyun /* Step 08 */
1951*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1952*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_UNMUTE |
1953*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_UNMUTE,
1954*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_MUTE |
1955*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_MUTE);
1956*4882a593Smuzhiyun
1957*4882a593Smuzhiyun /* Step 09 */
1958*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
1959*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_EN |
1960*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_EN,
1961*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_DIS |
1962*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_DIS);
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun /* Step 10 */
1965*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
1966*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_EN |
1967*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_EN,
1968*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_DIS |
1969*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_DIS);
1970*4882a593Smuzhiyun
1971*4882a593Smuzhiyun /* Step 11 */
1972*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1973*4882a593Smuzhiyun RK3308_DAC_L_DAC_EN |
1974*4882a593Smuzhiyun RK3308_DAC_R_DAC_EN,
1975*4882a593Smuzhiyun RK3308_DAC_L_DAC_DIS |
1976*4882a593Smuzhiyun RK3308_DAC_R_DAC_DIS);
1977*4882a593Smuzhiyun
1978*4882a593Smuzhiyun /* Step 12 */
1979*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1980*4882a593Smuzhiyun RK3308_DAC_L_CLK_EN |
1981*4882a593Smuzhiyun RK3308_DAC_R_CLK_EN,
1982*4882a593Smuzhiyun RK3308_DAC_L_CLK_DIS |
1983*4882a593Smuzhiyun RK3308_DAC_R_CLK_DIS);
1984*4882a593Smuzhiyun
1985*4882a593Smuzhiyun /* Step 13 */
1986*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
1987*4882a593Smuzhiyun RK3308_DAC_L_REF_EN |
1988*4882a593Smuzhiyun RK3308_DAC_R_REF_EN,
1989*4882a593Smuzhiyun RK3308_DAC_L_REF_DIS |
1990*4882a593Smuzhiyun RK3308_DAC_R_REF_DIS);
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun /* Step 14 */
1993*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
1994*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_MSK |
1995*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
1996*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_INIT |
1997*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_INIT);
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun /* Step 15 */
2000*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B &&
2001*4882a593Smuzhiyun (rk3308->dac_output == DAC_LINEOUT ||
2002*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT_HPOUT)) {
2003*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
2004*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
2005*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
2006*4882a593Smuzhiyun RK3308_DAC_L_SEL_DC_FROM_VCM |
2007*4882a593Smuzhiyun RK3308_DAC_R_SEL_DC_FROM_VCM);
2008*4882a593Smuzhiyun }
2009*4882a593Smuzhiyun
2010*4882a593Smuzhiyun /* Step 16 */
2011*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
2012*4882a593Smuzhiyun RK3308_DAC_BUF_REF_L_EN |
2013*4882a593Smuzhiyun RK3308_DAC_BUF_REF_R_EN,
2014*4882a593Smuzhiyun RK3308_DAC_BUF_REF_L_DIS |
2015*4882a593Smuzhiyun RK3308_DAC_BUF_REF_R_DIS);
2016*4882a593Smuzhiyun
2017*4882a593Smuzhiyun /* Step 17 */
2018*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00,
2019*4882a593Smuzhiyun RK3308_DAC_CURRENT_EN,
2020*4882a593Smuzhiyun RK3308_DAC_CURRENT_DIS);
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun /* Step 18 */
2023*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
2024*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_WORK |
2025*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_WORK,
2026*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_INIT |
2027*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_INIT);
2028*4882a593Smuzhiyun
2029*4882a593Smuzhiyun /* Step 19 */
2030*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
2031*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_WORK |
2032*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_WORK,
2033*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_WORK |
2034*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_WORK);
2035*4882a593Smuzhiyun
2036*4882a593Smuzhiyun /* Step 20 skipped, may set the min gain for HPOUT. */
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun /*
2039*4882a593Smuzhiyun * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3]
2040*4882a593Smuzhiyun * is set to 0x1, add the steps from the section Disable ADC
2041*4882a593Smuzhiyun * Configuration Standard Usage Flow after complete the step 19
2042*4882a593Smuzhiyun *
2043*4882a593Smuzhiyun * IF USING LINE-IN
2044*4882a593Smuzhiyun * rk3308_codec_adc_ana_disable(rk3308, type);
2045*4882a593Smuzhiyun */
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun rk3308->dac_endisable = false;
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun return 0;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
rk3308_codec_power_on(struct rk3308_codec_priv * rk3308)2052*4882a593Smuzhiyun static int rk3308_codec_power_on(struct rk3308_codec_priv *rk3308)
2053*4882a593Smuzhiyun {
2054*4882a593Smuzhiyun unsigned int v;
2055*4882a593Smuzhiyun
2056*4882a593Smuzhiyun /* 0. Supply the power of digital part and reset the Audio Codec */
2057*4882a593Smuzhiyun /* Do nothing */
2058*4882a593Smuzhiyun
2059*4882a593Smuzhiyun /*
2060*4882a593Smuzhiyun * 1. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4]
2061*4882a593Smuzhiyun * to 0x1, to setup dc voltage of the DAC channel output.
2062*4882a593Smuzhiyun */
2063*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
2064*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_MSK,
2065*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_L_INIT);
2066*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
2067*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
2068*4882a593Smuzhiyun RK3308_DAC_HPOUT_POP_SOUND_R_INIT);
2069*4882a593Smuzhiyun
2070*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2071*4882a593Smuzhiyun /*
2072*4882a593Smuzhiyun * 2. Configure ACODEC_DAC_ANA_CON15[1:0] and
2073*4882a593Smuzhiyun * ACODEC_DAC_ANA_CON15[5:4] to 0x1, to setup dc voltage of
2074*4882a593Smuzhiyun * the DAC channel output.
2075*4882a593Smuzhiyun */
2076*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
2077*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_L_MSK,
2078*4882a593Smuzhiyun RK3308_DAC_L_SEL_DC_FROM_VCM);
2079*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
2080*4882a593Smuzhiyun RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
2081*4882a593Smuzhiyun RK3308_DAC_R_SEL_DC_FROM_VCM);
2082*4882a593Smuzhiyun }
2083*4882a593Smuzhiyun
2084*4882a593Smuzhiyun /*
2085*4882a593Smuzhiyun * 3. Configure the register ACODEC_ADC_ANA_CON10[3:0] to 7’b000_0001.
2086*4882a593Smuzhiyun */
2087*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2088*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK,
2089*4882a593Smuzhiyun RK3308_ADC_SEL_I(0x1));
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2092*4882a593Smuzhiyun /*
2093*4882a593Smuzhiyun * 4. Configure the register ACODEC_ADC_ANA_CON14[3:0] to
2094*4882a593Smuzhiyun * 4’b0001.
2095*4882a593Smuzhiyun */
2096*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2097*4882a593Smuzhiyun RK3308_DAC_CURRENT_CHARGE_MSK,
2098*4882a593Smuzhiyun RK3308_DAC_SEL_I(0x1));
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun
2101*4882a593Smuzhiyun /* 5. Supply the power of the analog part(AVDD,AVDDRV) */
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun /*
2104*4882a593Smuzhiyun * 6. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup
2105*4882a593Smuzhiyun * reference voltage
2106*4882a593Smuzhiyun */
2107*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2108*4882a593Smuzhiyun RK3308_ADC_REF_EN, RK3308_ADC_REF_EN);
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2111*4882a593Smuzhiyun /*
2112*4882a593Smuzhiyun * 7. Configure the register ACODEC_ADC_ANA_CON14[4] to 0x1 to
2113*4882a593Smuzhiyun * setup reference voltage
2114*4882a593Smuzhiyun */
2115*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2116*4882a593Smuzhiyun RK3308_DAC_VCM_LINEOUT_EN,
2117*4882a593Smuzhiyun RK3308_DAC_VCM_LINEOUT_EN);
2118*4882a593Smuzhiyun }
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun /*
2121*4882a593Smuzhiyun * 8. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to
2122*4882a593Smuzhiyun * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to
2123*4882a593Smuzhiyun * 0x7f directly. Here the slot time of the step is 200us.
2124*4882a593Smuzhiyun */
2125*4882a593Smuzhiyun for (v = 0x1; v <= 0x7f; v++) {
2126*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2127*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK,
2128*4882a593Smuzhiyun v);
2129*4882a593Smuzhiyun udelay(200);
2130*4882a593Smuzhiyun }
2131*4882a593Smuzhiyun
2132*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2133*4882a593Smuzhiyun /*
2134*4882a593Smuzhiyun * 9. Change the register ACODEC_ADC_ANA_CON14[3:0] from the 0x1
2135*4882a593Smuzhiyun * to 0xf step by step or configure the
2136*4882a593Smuzhiyun * ACODEC_ADC_ANA_CON14[3:0] to 0xf directly. Here the slot
2137*4882a593Smuzhiyun * time of the step is 200us.
2138*4882a593Smuzhiyun */
2139*4882a593Smuzhiyun for (v = 0x1; v <= 0xf; v++) {
2140*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2141*4882a593Smuzhiyun RK3308_DAC_CURRENT_CHARGE_MSK,
2142*4882a593Smuzhiyun v);
2143*4882a593Smuzhiyun udelay(200);
2144*4882a593Smuzhiyun }
2145*4882a593Smuzhiyun }
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun /* 10. Wait until the voltage of VCM keeps stable at the AVDD/2 */
2148*4882a593Smuzhiyun msleep(20); /* estimated value */
2149*4882a593Smuzhiyun
2150*4882a593Smuzhiyun /*
2151*4882a593Smuzhiyun * 11. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the
2152*4882a593Smuzhiyun * appropriate value(expect 0x0) for reducing power.
2153*4882a593Smuzhiyun */
2154*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2155*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK, 0x7c);
2156*4882a593Smuzhiyun
2157*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2158*4882a593Smuzhiyun /*
2159*4882a593Smuzhiyun * 12. Configure the register ACODEC_DAC_ANA_CON14[6:0] to the
2160*4882a593Smuzhiyun * appropriate value(expect 0x0) for reducing power.
2161*4882a593Smuzhiyun */
2162*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2163*4882a593Smuzhiyun RK3308_DAC_CURRENT_CHARGE_MSK, 0xf);
2164*4882a593Smuzhiyun }
2165*4882a593Smuzhiyun
2166*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
2167*4882a593Smuzhiyun /* Using large driver strength for HPOUT and LINEOUT */
2168*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308_DAC_ANA_CON07, 0x11);
2169*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308_DAC_ANA_CON08, 0x11);
2170*4882a593Smuzhiyun }
2171*4882a593Smuzhiyun
2172*4882a593Smuzhiyun return 0;
2173*4882a593Smuzhiyun }
2174*4882a593Smuzhiyun
rk3308_codec_power_off(struct rk3308_codec_priv * rk3308)2175*4882a593Smuzhiyun static int rk3308_codec_power_off(struct rk3308_codec_priv *rk3308)
2176*4882a593Smuzhiyun {
2177*4882a593Smuzhiyun unsigned int v;
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun /*
2180*4882a593Smuzhiyun * 0. Keep the power on and disable the DAC and ADC path according to
2181*4882a593Smuzhiyun * the section power on configuration standard usage flow.
2182*4882a593Smuzhiyun */
2183*4882a593Smuzhiyun
2184*4882a593Smuzhiyun /*
2185*4882a593Smuzhiyun * 1. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 7’b000_0001.
2186*4882a593Smuzhiyun */
2187*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2188*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK,
2189*4882a593Smuzhiyun RK3308_ADC_SEL_I(0x1));
2190*4882a593Smuzhiyun
2191*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2192*4882a593Smuzhiyun /*
2193*4882a593Smuzhiyun * 2. Configure the register ACODEC_DAC_ANA_CON14[3:0] to
2194*4882a593Smuzhiyun * 4’b0001.
2195*4882a593Smuzhiyun */
2196*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2197*4882a593Smuzhiyun RK3308_DAC_CURRENT_CHARGE_MSK,
2198*4882a593Smuzhiyun RK3308_DAC_SEL_I(0x1));
2199*4882a593Smuzhiyun }
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */
2202*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2203*4882a593Smuzhiyun RK3308_ADC_REF_EN,
2204*4882a593Smuzhiyun RK3308_ADC_REF_DIS);
2205*4882a593Smuzhiyun
2206*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2207*4882a593Smuzhiyun /* 4. Configure the register ACODEC_DAC_ANA_CON14[7] to 0x0 */
2208*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
2209*4882a593Smuzhiyun RK3308_DAC_VCM_LINEOUT_EN,
2210*4882a593Smuzhiyun RK3308_DAC_VCM_LINEOUT_DIS);
2211*4882a593Smuzhiyun }
2212*4882a593Smuzhiyun
2213*4882a593Smuzhiyun /*
2214*4882a593Smuzhiyun * 5. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f
2215*4882a593Smuzhiyun * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f
2216*4882a593Smuzhiyun * directly. Here the slot time of the step is 200us.
2217*4882a593Smuzhiyun */
2218*4882a593Smuzhiyun for (v = 0x1; v <= 0x7f; v++) {
2219*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0),
2220*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK,
2221*4882a593Smuzhiyun v);
2222*4882a593Smuzhiyun udelay(200);
2223*4882a593Smuzhiyun }
2224*4882a593Smuzhiyun
2225*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
2226*4882a593Smuzhiyun /*
2227*4882a593Smuzhiyun * 6. Change the register ACODEC_DAC_ANA_CON14[3:0] from the 0x1
2228*4882a593Smuzhiyun * to 0xf step by step or configure the
2229*4882a593Smuzhiyun * ACODEC_DAC_ANA_CON14[3:0] to 0xf directly. Here the slot
2230*4882a593Smuzhiyun * time of the step is 200us.
2231*4882a593Smuzhiyun */
2232*4882a593Smuzhiyun for (v = 0x1; v <= 0x7f; v++) {
2233*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
2234*4882a593Smuzhiyun RK3308_ADC_ANA_CON10(0),
2235*4882a593Smuzhiyun RK3308_ADC_CURRENT_CHARGE_MSK,
2236*4882a593Smuzhiyun v);
2237*4882a593Smuzhiyun udelay(200);
2238*4882a593Smuzhiyun }
2239*4882a593Smuzhiyun }
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun /* 7. Wait until the voltage of VCM keeps stable at the AGND */
2242*4882a593Smuzhiyun msleep(20); /* estimated value */
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun /* 8. Power off the analog power supply */
2245*4882a593Smuzhiyun /* 9. Power off the digital power supply */
2246*4882a593Smuzhiyun
2247*4882a593Smuzhiyun /* Do something via hardware */
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun return 0;
2250*4882a593Smuzhiyun }
2251*4882a593Smuzhiyun
rk3308_codec_headset_detect_enable(struct rk3308_codec_priv * rk3308)2252*4882a593Smuzhiyun static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308)
2253*4882a593Smuzhiyun {
2254*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C)
2255*4882a593Smuzhiyun rk3308_codec_dac_mclk_enable(rk3308);
2256*4882a593Smuzhiyun
2257*4882a593Smuzhiyun /*
2258*4882a593Smuzhiyun * Set ACODEC_DAC_ANA_CON0[1] to 0x1, to enable the headset insert
2259*4882a593Smuzhiyun * detection
2260*4882a593Smuzhiyun *
2261*4882a593Smuzhiyun * Note. When the voltage of PAD HPDET> 8*AVDD/9, the output value of
2262*4882a593Smuzhiyun * the pin_hpdet will be set to 0x1 and assert a interrupt
2263*4882a593Smuzhiyun */
2264*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00,
2265*4882a593Smuzhiyun RK3308_DAC_HEADPHONE_DET_MSK,
2266*4882a593Smuzhiyun RK3308_DAC_HEADPHONE_DET_EN);
2267*4882a593Smuzhiyun
2268*4882a593Smuzhiyun return 0;
2269*4882a593Smuzhiyun }
2270*4882a593Smuzhiyun
rk3308_codec_headset_detect_disable(struct rk3308_codec_priv * rk3308)2271*4882a593Smuzhiyun static int rk3308_codec_headset_detect_disable(struct rk3308_codec_priv *rk3308)
2272*4882a593Smuzhiyun {
2273*4882a593Smuzhiyun /*
2274*4882a593Smuzhiyun * Set ACODEC_DAC_ANA_CON0[1] to 0x0, to disable the headset insert
2275*4882a593Smuzhiyun * detection
2276*4882a593Smuzhiyun */
2277*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00,
2278*4882a593Smuzhiyun RK3308_DAC_HEADPHONE_DET_MSK,
2279*4882a593Smuzhiyun RK3308_DAC_HEADPHONE_DET_DIS);
2280*4882a593Smuzhiyun
2281*4882a593Smuzhiyun return 0;
2282*4882a593Smuzhiyun }
2283*4882a593Smuzhiyun
rk3308_codec_check_i2s_sdis(struct rk3308_codec_priv * rk3308,int num)2284*4882a593Smuzhiyun static int rk3308_codec_check_i2s_sdis(struct rk3308_codec_priv *rk3308,
2285*4882a593Smuzhiyun int num)
2286*4882a593Smuzhiyun {
2287*4882a593Smuzhiyun int i, j, ret = 0;
2288*4882a593Smuzhiyun
2289*4882a593Smuzhiyun switch (num) {
2290*4882a593Smuzhiyun case 1:
2291*4882a593Smuzhiyun rk3308->which_i2s = ACODEC_TO_I2S1_2CH;
2292*4882a593Smuzhiyun break;
2293*4882a593Smuzhiyun case 2:
2294*4882a593Smuzhiyun rk3308->which_i2s = ACODEC_TO_I2S3_4CH;
2295*4882a593Smuzhiyun break;
2296*4882a593Smuzhiyun case 4:
2297*4882a593Smuzhiyun rk3308->which_i2s = ACODEC_TO_I2S2_8CH;
2298*4882a593Smuzhiyun break;
2299*4882a593Smuzhiyun default:
2300*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "Invalid i2s sdis num: %d\n", num);
2301*4882a593Smuzhiyun ret = -EINVAL;
2302*4882a593Smuzhiyun goto err;
2303*4882a593Smuzhiyun }
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyun for (i = 0; i < num; i++) {
2306*4882a593Smuzhiyun if (rk3308->i2s_sdis[i] > ADC_LR_GROUP_MAX - 1) {
2307*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
2308*4882a593Smuzhiyun "i2s_sdis[%d]: %d is overflow\n",
2309*4882a593Smuzhiyun i, rk3308->i2s_sdis[i]);
2310*4882a593Smuzhiyun ret = -EINVAL;
2311*4882a593Smuzhiyun goto err;
2312*4882a593Smuzhiyun }
2313*4882a593Smuzhiyun
2314*4882a593Smuzhiyun for (j = 0; j < num; j++) {
2315*4882a593Smuzhiyun if (i == j)
2316*4882a593Smuzhiyun continue;
2317*4882a593Smuzhiyun
2318*4882a593Smuzhiyun if (rk3308->i2s_sdis[i] == rk3308->i2s_sdis[j]) {
2319*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
2320*4882a593Smuzhiyun "Invalid i2s_sdis: [%d]%d == [%d]%d\n",
2321*4882a593Smuzhiyun i, rk3308->i2s_sdis[i],
2322*4882a593Smuzhiyun j, rk3308->i2s_sdis[j]);
2323*4882a593Smuzhiyun ret = -EINVAL;
2324*4882a593Smuzhiyun goto err;
2325*4882a593Smuzhiyun }
2326*4882a593Smuzhiyun }
2327*4882a593Smuzhiyun }
2328*4882a593Smuzhiyun
2329*4882a593Smuzhiyun err:
2330*4882a593Smuzhiyun return ret;
2331*4882a593Smuzhiyun }
2332*4882a593Smuzhiyun
rk3308_codec_adc_grps_route_config(struct rk3308_codec_priv * rk3308)2333*4882a593Smuzhiyun static int rk3308_codec_adc_grps_route_config(struct rk3308_codec_priv *rk3308)
2334*4882a593Smuzhiyun {
2335*4882a593Smuzhiyun int idx = 0;
2336*4882a593Smuzhiyun
2337*4882a593Smuzhiyun if (rk3308->which_i2s == ACODEC_TO_I2S2_8CH) {
2338*4882a593Smuzhiyun for (idx = 0; idx < rk3308->to_i2s_grps; idx++) {
2339*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2340*4882a593Smuzhiyun GRF_I2S2_8CH_SDI(idx, rk3308->i2s_sdis[idx]));
2341*4882a593Smuzhiyun }
2342*4882a593Smuzhiyun } else if (rk3308->which_i2s == ACODEC_TO_I2S3_4CH) {
2343*4882a593Smuzhiyun for (idx = 0; idx < rk3308->to_i2s_grps; idx++) {
2344*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2345*4882a593Smuzhiyun GRF_I2S3_4CH_SDI(idx, rk3308->i2s_sdis[idx]));
2346*4882a593Smuzhiyun }
2347*4882a593Smuzhiyun } else if (rk3308->which_i2s == ACODEC_TO_I2S1_2CH) {
2348*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2349*4882a593Smuzhiyun GRF_I2S1_2CH_SDI(rk3308->i2s_sdis[idx]));
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun return 0;
2353*4882a593Smuzhiyun }
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun /* Put default one-to-one mapping */
rk3308_codec_adc_grps_route_default(struct rk3308_codec_priv * rk3308)2356*4882a593Smuzhiyun static int rk3308_codec_adc_grps_route_default(struct rk3308_codec_priv *rk3308)
2357*4882a593Smuzhiyun {
2358*4882a593Smuzhiyun unsigned int idx;
2359*4882a593Smuzhiyun
2360*4882a593Smuzhiyun /*
2361*4882a593Smuzhiyun * The GRF values may be kept the previous status after hot reboot,
2362*4882a593Smuzhiyun * if the property 'rockchip,adc-grps-route' is not set, we need to
2363*4882a593Smuzhiyun * recover default the order of sdi/sdo for i2s2_8ch/i2s3_8ch/i2s1_2ch.
2364*4882a593Smuzhiyun */
2365*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2366*4882a593Smuzhiyun GRF_I2S1_2CH_SDI(0));
2367*4882a593Smuzhiyun
2368*4882a593Smuzhiyun for (idx = 0; idx < 2; idx++) {
2369*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2370*4882a593Smuzhiyun GRF_I2S3_4CH_SDI(idx, idx));
2371*4882a593Smuzhiyun }
2372*4882a593Smuzhiyun
2373*4882a593Smuzhiyun /* Using i2s2_8ch by default. */
2374*4882a593Smuzhiyun rk3308->which_i2s = ACODEC_TO_I2S2_8CH;
2375*4882a593Smuzhiyun rk3308->to_i2s_grps = ADC_LR_GROUP_MAX;
2376*4882a593Smuzhiyun
2377*4882a593Smuzhiyun for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) {
2378*4882a593Smuzhiyun rk3308->i2s_sdis[idx] = idx;
2379*4882a593Smuzhiyun regmap_write(rk3308->grf, GRF_SOC_CON1,
2380*4882a593Smuzhiyun GRF_I2S2_8CH_SDI(idx, idx));
2381*4882a593Smuzhiyun }
2382*4882a593Smuzhiyun
2383*4882a593Smuzhiyun return 0;
2384*4882a593Smuzhiyun }
2385*4882a593Smuzhiyun
rk3308_codec_adc_grps_route(struct rk3308_codec_priv * rk3308,struct device_node * np)2386*4882a593Smuzhiyun static int rk3308_codec_adc_grps_route(struct rk3308_codec_priv *rk3308,
2387*4882a593Smuzhiyun struct device_node *np)
2388*4882a593Smuzhiyun {
2389*4882a593Smuzhiyun int num, ret;
2390*4882a593Smuzhiyun
2391*4882a593Smuzhiyun num = of_count_phandle_with_args(np, "rockchip,adc-grps-route", NULL);
2392*4882a593Smuzhiyun if (num < 0) {
2393*4882a593Smuzhiyun if (num == -ENOENT) {
2394*4882a593Smuzhiyun /* Not use 'rockchip,adc-grps-route' property here */
2395*4882a593Smuzhiyun rk3308_codec_adc_grps_route_default(rk3308);
2396*4882a593Smuzhiyun ret = 0;
2397*4882a593Smuzhiyun } else {
2398*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
2399*4882a593Smuzhiyun "Failed to read 'rockchip,adc-grps-route' num: %d\n",
2400*4882a593Smuzhiyun num);
2401*4882a593Smuzhiyun ret = num;
2402*4882a593Smuzhiyun }
2403*4882a593Smuzhiyun return ret;
2404*4882a593Smuzhiyun }
2405*4882a593Smuzhiyun
2406*4882a593Smuzhiyun ret = of_property_read_u32_array(np, "rockchip,adc-grps-route",
2407*4882a593Smuzhiyun rk3308->i2s_sdis, num);
2408*4882a593Smuzhiyun if (ret < 0) {
2409*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
2410*4882a593Smuzhiyun "Failed to read 'rockchip,adc-grps-route': %d\n",
2411*4882a593Smuzhiyun ret);
2412*4882a593Smuzhiyun return ret;
2413*4882a593Smuzhiyun }
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun ret = rk3308_codec_check_i2s_sdis(rk3308, num);
2416*4882a593Smuzhiyun if (ret < 0) {
2417*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
2418*4882a593Smuzhiyun "Failed to check i2s_sdis: %d\n", ret);
2419*4882a593Smuzhiyun return ret;
2420*4882a593Smuzhiyun }
2421*4882a593Smuzhiyun
2422*4882a593Smuzhiyun rk3308->to_i2s_grps = num;
2423*4882a593Smuzhiyun
2424*4882a593Smuzhiyun rk3308_codec_adc_grps_route_config(rk3308);
2425*4882a593Smuzhiyun
2426*4882a593Smuzhiyun return 0;
2427*4882a593Smuzhiyun }
2428*4882a593Smuzhiyun
check_micbias(int micbias)2429*4882a593Smuzhiyun static int check_micbias(int micbias)
2430*4882a593Smuzhiyun {
2431*4882a593Smuzhiyun switch (micbias) {
2432*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_85:
2433*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_8:
2434*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_75:
2435*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_7:
2436*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_65:
2437*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_6:
2438*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_55:
2439*4882a593Smuzhiyun case RK3308_ADC_MICBIAS_VOLT_0_5:
2440*4882a593Smuzhiyun return 0;
2441*4882a593Smuzhiyun }
2442*4882a593Smuzhiyun
2443*4882a593Smuzhiyun return -EINVAL;
2444*4882a593Smuzhiyun }
2445*4882a593Smuzhiyun
handle_loopback(struct rk3308_codec_priv * rk3308)2446*4882a593Smuzhiyun static bool handle_loopback(struct rk3308_codec_priv *rk3308)
2447*4882a593Smuzhiyun {
2448*4882a593Smuzhiyun /* The version B doesn't need to handle loopback. */
2449*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B)
2450*4882a593Smuzhiyun return false;
2451*4882a593Smuzhiyun
2452*4882a593Smuzhiyun switch (rk3308->loopback_grp) {
2453*4882a593Smuzhiyun case 0:
2454*4882a593Smuzhiyun case 1:
2455*4882a593Smuzhiyun case 2:
2456*4882a593Smuzhiyun case 3:
2457*4882a593Smuzhiyun return true;
2458*4882a593Smuzhiyun }
2459*4882a593Smuzhiyun
2460*4882a593Smuzhiyun return false;
2461*4882a593Smuzhiyun }
2462*4882a593Smuzhiyun
has_en_always_grps(struct rk3308_codec_priv * rk3308)2463*4882a593Smuzhiyun static bool has_en_always_grps(struct rk3308_codec_priv *rk3308)
2464*4882a593Smuzhiyun {
2465*4882a593Smuzhiyun int idx;
2466*4882a593Smuzhiyun
2467*4882a593Smuzhiyun if (rk3308->en_always_grps_num) {
2468*4882a593Smuzhiyun for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) {
2469*4882a593Smuzhiyun if (rk3308->en_always_grps[idx] >= 0 &&
2470*4882a593Smuzhiyun rk3308->en_always_grps[idx] <= ADC_LR_GROUP_MAX - 1)
2471*4882a593Smuzhiyun return true;
2472*4882a593Smuzhiyun }
2473*4882a593Smuzhiyun }
2474*4882a593Smuzhiyun
2475*4882a593Smuzhiyun return false;
2476*4882a593Smuzhiyun }
2477*4882a593Smuzhiyun
rk3308_codec_micbias_enable(struct rk3308_codec_priv * rk3308,int micbias)2478*4882a593Smuzhiyun static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308,
2479*4882a593Smuzhiyun int micbias)
2480*4882a593Smuzhiyun {
2481*4882a593Smuzhiyun int ret;
2482*4882a593Smuzhiyun
2483*4882a593Smuzhiyun if (rk3308->ext_micbias != EXT_MICBIAS_NONE)
2484*4882a593Smuzhiyun return 0;
2485*4882a593Smuzhiyun
2486*4882a593Smuzhiyun /* 0. Power up the ACODEC and keep the AVDDH stable */
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun /* Step 1. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */
2489*4882a593Smuzhiyun ret = check_micbias(micbias);
2490*4882a593Smuzhiyun if (ret < 0) {
2491*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n",
2492*4882a593Smuzhiyun micbias);
2493*4882a593Smuzhiyun return ret;
2494*4882a593Smuzhiyun }
2495*4882a593Smuzhiyun
2496*4882a593Smuzhiyun /*
2497*4882a593Smuzhiyun * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range
2498*4882a593Smuzhiyun * control signal of MICBIAS voltage
2499*4882a593Smuzhiyun */
2500*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0),
2501*4882a593Smuzhiyun RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK,
2502*4882a593Smuzhiyun micbias);
2503*4882a593Smuzhiyun
2504*4882a593Smuzhiyun /* Step 2. Wait until the VCMH keep stable */
2505*4882a593Smuzhiyun msleep(20); /* estimated value */
2506*4882a593Smuzhiyun
2507*4882a593Smuzhiyun /*
2508*4882a593Smuzhiyun * Step 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x1
2509*4882a593Smuzhiyun *
2510*4882a593Smuzhiyun * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable
2511*4882a593Smuzhiyun * signal of current source for MICBIAS
2512*4882a593Smuzhiyun */
2513*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0),
2514*4882a593Smuzhiyun RK3308_ADC_MICBIAS_CURRENT_MSK,
2515*4882a593Smuzhiyun RK3308_ADC_MICBIAS_CURRENT_EN);
2516*4882a593Smuzhiyun
2517*4882a593Smuzhiyun /*
2518*4882a593Smuzhiyun * Step 4. Configure the (ADC_ANA_CON7+0x40)[3] or
2519*4882a593Smuzhiyun * (ADC_ANA_CON7+0x80)[3] to 0x1.
2520*4882a593Smuzhiyun *
2521*4882a593Smuzhiyun * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and
2522*4882a593Smuzhiyun * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2
2523*4882a593Smuzhiyun */
2524*4882a593Smuzhiyun if (rk3308->micbias1)
2525*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1),
2526*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN,
2527*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN);
2528*4882a593Smuzhiyun
2529*4882a593Smuzhiyun if (rk3308->micbias2)
2530*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2),
2531*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN,
2532*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN);
2533*4882a593Smuzhiyun
2534*4882a593Smuzhiyun /* waiting micbias stabled*/
2535*4882a593Smuzhiyun mdelay(50);
2536*4882a593Smuzhiyun
2537*4882a593Smuzhiyun rk3308->enable_micbias = true;
2538*4882a593Smuzhiyun
2539*4882a593Smuzhiyun return 0;
2540*4882a593Smuzhiyun }
2541*4882a593Smuzhiyun
rk3308_codec_micbias_disable(struct rk3308_codec_priv * rk3308)2542*4882a593Smuzhiyun static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308)
2543*4882a593Smuzhiyun {
2544*4882a593Smuzhiyun if (rk3308->ext_micbias != EXT_MICBIAS_NONE)
2545*4882a593Smuzhiyun return 0;
2546*4882a593Smuzhiyun
2547*4882a593Smuzhiyun /* Step 0. Enable the MICBIAS and keep the Audio Codec stable */
2548*4882a593Smuzhiyun /* Do nothing */
2549*4882a593Smuzhiyun
2550*4882a593Smuzhiyun /*
2551*4882a593Smuzhiyun * Step 1. Configure the (ADC_ANA_CON7+0x40)[3] or
2552*4882a593Smuzhiyun * (ADC_ANA_CON7+0x80)[3] to 0x0
2553*4882a593Smuzhiyun */
2554*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1),
2555*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN,
2556*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_DIS);
2557*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2),
2558*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_EN,
2559*4882a593Smuzhiyun RK3308_ADC_MIC_BIAS_BUF_DIS);
2560*4882a593Smuzhiyun
2561*4882a593Smuzhiyun /*
2562*4882a593Smuzhiyun * Step 2. Configure ACODEC_ADC_ANA_CON8[4] to 0x0
2563*4882a593Smuzhiyun *
2564*4882a593Smuzhiyun * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable
2565*4882a593Smuzhiyun * signal of current source for MICBIAS
2566*4882a593Smuzhiyun */
2567*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0),
2568*4882a593Smuzhiyun RK3308_ADC_MICBIAS_CURRENT_MSK,
2569*4882a593Smuzhiyun RK3308_ADC_MICBIAS_CURRENT_DIS);
2570*4882a593Smuzhiyun
2571*4882a593Smuzhiyun rk3308->enable_micbias = false;
2572*4882a593Smuzhiyun
2573*4882a593Smuzhiyun return 0;
2574*4882a593Smuzhiyun }
2575*4882a593Smuzhiyun
rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv * rk3308,int type)2576*4882a593Smuzhiyun static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
2577*4882a593Smuzhiyun int type)
2578*4882a593Smuzhiyun {
2579*4882a593Smuzhiyun int idx, grp;
2580*4882a593Smuzhiyun
2581*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2582*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2583*4882a593Smuzhiyun continue;
2584*4882a593Smuzhiyun
2585*4882a593Smuzhiyun /* vendor step 1 */
2586*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2587*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2588*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK,
2589*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_INIT |
2590*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_INIT);
2591*4882a593Smuzhiyun }
2592*4882a593Smuzhiyun
2593*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2594*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2595*4882a593Smuzhiyun continue;
2596*4882a593Smuzhiyun
2597*4882a593Smuzhiyun /* vendor step 2 */
2598*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2599*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2600*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK,
2601*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_INIT |
2602*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_INIT);
2603*4882a593Smuzhiyun }
2604*4882a593Smuzhiyun
2605*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2606*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2607*4882a593Smuzhiyun continue;
2608*4882a593Smuzhiyun
2609*4882a593Smuzhiyun /* vendor step 3 */
2610*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2611*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2612*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK,
2613*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_INIT |
2614*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_INIT);
2615*4882a593Smuzhiyun }
2616*4882a593Smuzhiyun
2617*4882a593Smuzhiyun usleep_range(200, 250); /* estimated value */
2618*4882a593Smuzhiyun
2619*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2620*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2621*4882a593Smuzhiyun continue;
2622*4882a593Smuzhiyun
2623*4882a593Smuzhiyun /* vendor step 1 */
2624*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2625*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2626*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK,
2627*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2628*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK);
2629*4882a593Smuzhiyun }
2630*4882a593Smuzhiyun
2631*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2632*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2633*4882a593Smuzhiyun continue;
2634*4882a593Smuzhiyun
2635*4882a593Smuzhiyun /* vendor step 2 */
2636*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2637*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2638*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK,
2639*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2640*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK);
2641*4882a593Smuzhiyun }
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2644*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2645*4882a593Smuzhiyun continue;
2646*4882a593Smuzhiyun
2647*4882a593Smuzhiyun /* vendor step 3 */
2648*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2649*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2650*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK,
2651*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2652*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK);
2653*4882a593Smuzhiyun }
2654*4882a593Smuzhiyun
2655*4882a593Smuzhiyun return 0;
2656*4882a593Smuzhiyun }
2657*4882a593Smuzhiyun
rk3308_codec_adc_ana_enable(struct rk3308_codec_priv * rk3308,int type)2658*4882a593Smuzhiyun static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
2659*4882a593Smuzhiyun int type)
2660*4882a593Smuzhiyun {
2661*4882a593Smuzhiyun unsigned int agc_func_en;
2662*4882a593Smuzhiyun int idx, grp;
2663*4882a593Smuzhiyun
2664*4882a593Smuzhiyun /*
2665*4882a593Smuzhiyun * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4],
2666*4882a593Smuzhiyun * to select the line-in or microphone as input of ADC
2667*4882a593Smuzhiyun *
2668*4882a593Smuzhiyun * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5,
2669*4882a593Smuzhiyun * ADC6, ADC7, and ADC8
2670*4882a593Smuzhiyun */
2671*4882a593Smuzhiyun if (rk3308->adc_grp0_using_linein) {
2672*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0),
2673*4882a593Smuzhiyun RK3308_ADC_CH1_IN_SEL_MSK |
2674*4882a593Smuzhiyun RK3308_ADC_CH2_IN_SEL_MSK,
2675*4882a593Smuzhiyun RK3308_ADC_CH1_IN_LINEIN |
2676*4882a593Smuzhiyun RK3308_ADC_CH2_IN_LINEIN);
2677*4882a593Smuzhiyun
2678*4882a593Smuzhiyun /* Keep other ADCs as MIC-IN */
2679*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2680*4882a593Smuzhiyun /* The groups without line-in are >= 1 */
2681*4882a593Smuzhiyun if (grp < 1 || grp > ADC_LR_GROUP_MAX - 1)
2682*4882a593Smuzhiyun continue;
2683*4882a593Smuzhiyun
2684*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
2685*4882a593Smuzhiyun RK3308_ADC_ANA_CON07(grp),
2686*4882a593Smuzhiyun RK3308_ADC_CH1_IN_SEL_MSK |
2687*4882a593Smuzhiyun RK3308_ADC_CH2_IN_SEL_MSK,
2688*4882a593Smuzhiyun RK3308_ADC_CH1_IN_MIC |
2689*4882a593Smuzhiyun RK3308_ADC_CH2_IN_MIC);
2690*4882a593Smuzhiyun }
2691*4882a593Smuzhiyun } else {
2692*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2693*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2694*4882a593Smuzhiyun continue;
2695*4882a593Smuzhiyun
2696*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
2697*4882a593Smuzhiyun RK3308_ADC_ANA_CON07(grp),
2698*4882a593Smuzhiyun RK3308_ADC_CH1_IN_SEL_MSK |
2699*4882a593Smuzhiyun RK3308_ADC_CH2_IN_SEL_MSK,
2700*4882a593Smuzhiyun RK3308_ADC_CH1_IN_MIC |
2701*4882a593Smuzhiyun RK3308_ADC_CH2_IN_MIC);
2702*4882a593Smuzhiyun }
2703*4882a593Smuzhiyun }
2704*4882a593Smuzhiyun
2705*4882a593Smuzhiyun /*
2706*4882a593Smuzhiyun * 2. Set ACODEC_ADC_ANA_CON0[7] and [3] to 0x1, to end the mute station
2707*4882a593Smuzhiyun * of ADC, to enable the MIC module, to enable the reference voltage
2708*4882a593Smuzhiyun * buffer, and to end the initialization of MIC
2709*4882a593Smuzhiyun */
2710*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2711*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2712*4882a593Smuzhiyun continue;
2713*4882a593Smuzhiyun
2714*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2715*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_UNMUTE |
2716*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_UNMUTE,
2717*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_UNMUTE |
2718*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_UNMUTE);
2719*4882a593Smuzhiyun }
2720*4882a593Smuzhiyun
2721*4882a593Smuzhiyun /*
2722*4882a593Smuzhiyun * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source
2723*4882a593Smuzhiyun * of audio
2724*4882a593Smuzhiyun */
2725*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2726*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2727*4882a593Smuzhiyun continue;
2728*4882a593Smuzhiyun
2729*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp),
2730*4882a593Smuzhiyun RK3308_ADC_CURRENT_MSK,
2731*4882a593Smuzhiyun RK3308_ADC_CURRENT_EN);
2732*4882a593Smuzhiyun }
2733*4882a593Smuzhiyun
2734*4882a593Smuzhiyun /*
2735*4882a593Smuzhiyun * This is mainly used for BIST mode that wait ADCs are stable.
2736*4882a593Smuzhiyun *
2737*4882a593Smuzhiyun * By tested results, the type delay is >40us, but we need to leave
2738*4882a593Smuzhiyun * enough delay margin.
2739*4882a593Smuzhiyun */
2740*4882a593Smuzhiyun usleep_range(400, 500);
2741*4882a593Smuzhiyun
2742*4882a593Smuzhiyun /* vendor step 4*/
2743*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2744*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2745*4882a593Smuzhiyun continue;
2746*4882a593Smuzhiyun
2747*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2748*4882a593Smuzhiyun RK3308_ADC_CH1_BUF_REF_EN |
2749*4882a593Smuzhiyun RK3308_ADC_CH2_BUF_REF_EN,
2750*4882a593Smuzhiyun RK3308_ADC_CH1_BUF_REF_EN |
2751*4882a593Smuzhiyun RK3308_ADC_CH2_BUF_REF_EN);
2752*4882a593Smuzhiyun }
2753*4882a593Smuzhiyun
2754*4882a593Smuzhiyun /* vendor step 5 */
2755*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2756*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2757*4882a593Smuzhiyun continue;
2758*4882a593Smuzhiyun
2759*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2760*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_EN |
2761*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_EN,
2762*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_EN |
2763*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_EN);
2764*4882a593Smuzhiyun }
2765*4882a593Smuzhiyun
2766*4882a593Smuzhiyun /* vendor step 6 */
2767*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2768*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2769*4882a593Smuzhiyun continue;
2770*4882a593Smuzhiyun
2771*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2772*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_EN |
2773*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_EN,
2774*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_EN |
2775*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_EN);
2776*4882a593Smuzhiyun }
2777*4882a593Smuzhiyun
2778*4882a593Smuzhiyun /* vendor step 7 */
2779*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2780*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2781*4882a593Smuzhiyun continue;
2782*4882a593Smuzhiyun
2783*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2784*4882a593Smuzhiyun RK3308_ADC_CH1_CLK_EN |
2785*4882a593Smuzhiyun RK3308_ADC_CH2_CLK_EN,
2786*4882a593Smuzhiyun RK3308_ADC_CH1_CLK_EN |
2787*4882a593Smuzhiyun RK3308_ADC_CH2_CLK_EN);
2788*4882a593Smuzhiyun }
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun /* vendor step 8 */
2791*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2792*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2793*4882a593Smuzhiyun continue;
2794*4882a593Smuzhiyun
2795*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2796*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_EN |
2797*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_EN,
2798*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_EN |
2799*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_EN);
2800*4882a593Smuzhiyun }
2801*4882a593Smuzhiyun
2802*4882a593Smuzhiyun /* vendor step 9 */
2803*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2804*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2805*4882a593Smuzhiyun continue;
2806*4882a593Smuzhiyun
2807*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2808*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2809*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK,
2810*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2811*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK);
2812*4882a593Smuzhiyun }
2813*4882a593Smuzhiyun
2814*4882a593Smuzhiyun /* vendor step 10 */
2815*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2816*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2817*4882a593Smuzhiyun continue;
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2820*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2821*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK,
2822*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2823*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK);
2824*4882a593Smuzhiyun }
2825*4882a593Smuzhiyun
2826*4882a593Smuzhiyun /* vendor step 11 */
2827*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2828*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2829*4882a593Smuzhiyun continue;
2830*4882a593Smuzhiyun
2831*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2832*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2833*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK,
2834*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2835*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK);
2836*4882a593Smuzhiyun }
2837*4882a593Smuzhiyun
2838*4882a593Smuzhiyun /* vendor step 12 */
2839*4882a593Smuzhiyun
2840*4882a593Smuzhiyun /* vendor step 13 */
2841*4882a593Smuzhiyun
2842*4882a593Smuzhiyun /* vendor step 14 */
2843*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2844*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2845*4882a593Smuzhiyun continue;
2846*4882a593Smuzhiyun
2847*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp),
2848*4882a593Smuzhiyun &agc_func_en);
2849*4882a593Smuzhiyun if (rk3308->adc_zerocross ||
2850*4882a593Smuzhiyun agc_func_en & RK3308_AGC_FUNC_SEL_EN) {
2851*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
2852*4882a593Smuzhiyun RK3308_ADC_ANA_CON02(grp),
2853*4882a593Smuzhiyun RK3308_ADC_CH1_ZEROCROSS_DET_EN,
2854*4882a593Smuzhiyun RK3308_ADC_CH1_ZEROCROSS_DET_EN);
2855*4882a593Smuzhiyun }
2856*4882a593Smuzhiyun regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp),
2857*4882a593Smuzhiyun &agc_func_en);
2858*4882a593Smuzhiyun if (rk3308->adc_zerocross ||
2859*4882a593Smuzhiyun agc_func_en & RK3308_AGC_FUNC_SEL_EN) {
2860*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
2861*4882a593Smuzhiyun RK3308_ADC_ANA_CON02(grp),
2862*4882a593Smuzhiyun RK3308_ADC_CH2_ZEROCROSS_DET_EN,
2863*4882a593Smuzhiyun RK3308_ADC_CH2_ZEROCROSS_DET_EN);
2864*4882a593Smuzhiyun }
2865*4882a593Smuzhiyun }
2866*4882a593Smuzhiyun
2867*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2868*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2869*4882a593Smuzhiyun continue;
2870*4882a593Smuzhiyun
2871*4882a593Smuzhiyun rk3308->adc_grps_endisable[grp] = true;
2872*4882a593Smuzhiyun }
2873*4882a593Smuzhiyun
2874*4882a593Smuzhiyun return 0;
2875*4882a593Smuzhiyun }
2876*4882a593Smuzhiyun
rk3308_codec_adc_ana_disable(struct rk3308_codec_priv * rk3308,int type)2877*4882a593Smuzhiyun static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308,
2878*4882a593Smuzhiyun int type)
2879*4882a593Smuzhiyun {
2880*4882a593Smuzhiyun int idx, grp;
2881*4882a593Smuzhiyun
2882*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2883*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2884*4882a593Smuzhiyun continue;
2885*4882a593Smuzhiyun
2886*4882a593Smuzhiyun /* vendor step 1 */
2887*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2888*4882a593Smuzhiyun RK3308_ADC_CH1_ZEROCROSS_DET_EN |
2889*4882a593Smuzhiyun RK3308_ADC_CH2_ZEROCROSS_DET_EN,
2890*4882a593Smuzhiyun RK3308_ADC_CH1_ZEROCROSS_DET_DIS |
2891*4882a593Smuzhiyun RK3308_ADC_CH2_ZEROCROSS_DET_DIS);
2892*4882a593Smuzhiyun }
2893*4882a593Smuzhiyun
2894*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2895*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2896*4882a593Smuzhiyun continue;
2897*4882a593Smuzhiyun
2898*4882a593Smuzhiyun /* vendor step 2 */
2899*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2900*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_EN |
2901*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_EN,
2902*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_DIS |
2903*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_DIS);
2904*4882a593Smuzhiyun }
2905*4882a593Smuzhiyun
2906*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2907*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2908*4882a593Smuzhiyun continue;
2909*4882a593Smuzhiyun
2910*4882a593Smuzhiyun /* vendor step 3 */
2911*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2912*4882a593Smuzhiyun RK3308_ADC_CH1_CLK_EN |
2913*4882a593Smuzhiyun RK3308_ADC_CH2_CLK_EN,
2914*4882a593Smuzhiyun RK3308_ADC_CH1_CLK_DIS |
2915*4882a593Smuzhiyun RK3308_ADC_CH2_CLK_DIS);
2916*4882a593Smuzhiyun }
2917*4882a593Smuzhiyun
2918*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2919*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2920*4882a593Smuzhiyun continue;
2921*4882a593Smuzhiyun
2922*4882a593Smuzhiyun /* vendor step 4 */
2923*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2924*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_EN |
2925*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_EN,
2926*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_DIS |
2927*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_DIS);
2928*4882a593Smuzhiyun }
2929*4882a593Smuzhiyun
2930*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2931*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2932*4882a593Smuzhiyun continue;
2933*4882a593Smuzhiyun
2934*4882a593Smuzhiyun /* vendor step 5 */
2935*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2936*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_EN |
2937*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_EN,
2938*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_DIS |
2939*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_DIS);
2940*4882a593Smuzhiyun }
2941*4882a593Smuzhiyun
2942*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2943*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2944*4882a593Smuzhiyun continue;
2945*4882a593Smuzhiyun
2946*4882a593Smuzhiyun /* vendor step 6 */
2947*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2948*4882a593Smuzhiyun RK3308_ADC_CH1_BUF_REF_EN |
2949*4882a593Smuzhiyun RK3308_ADC_CH2_BUF_REF_EN,
2950*4882a593Smuzhiyun RK3308_ADC_CH1_BUF_REF_DIS |
2951*4882a593Smuzhiyun RK3308_ADC_CH2_BUF_REF_DIS);
2952*4882a593Smuzhiyun }
2953*4882a593Smuzhiyun
2954*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2955*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2956*4882a593Smuzhiyun continue;
2957*4882a593Smuzhiyun
2958*4882a593Smuzhiyun /* vendor step 7 */
2959*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp),
2960*4882a593Smuzhiyun RK3308_ADC_CURRENT_MSK,
2961*4882a593Smuzhiyun RK3308_ADC_CURRENT_DIS);
2962*4882a593Smuzhiyun }
2963*4882a593Smuzhiyun
2964*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2965*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2966*4882a593Smuzhiyun continue;
2967*4882a593Smuzhiyun
2968*4882a593Smuzhiyun /* vendor step 8 */
2969*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
2970*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_WORK |
2971*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_WORK,
2972*4882a593Smuzhiyun RK3308_ADC_CH1_ADC_INIT |
2973*4882a593Smuzhiyun RK3308_ADC_CH2_ADC_INIT);
2974*4882a593Smuzhiyun }
2975*4882a593Smuzhiyun
2976*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2977*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2978*4882a593Smuzhiyun continue;
2979*4882a593Smuzhiyun
2980*4882a593Smuzhiyun /* vendor step 9 */
2981*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
2982*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_WORK |
2983*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_WORK,
2984*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_INIT |
2985*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_INIT);
2986*4882a593Smuzhiyun }
2987*4882a593Smuzhiyun
2988*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
2989*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
2990*4882a593Smuzhiyun continue;
2991*4882a593Smuzhiyun
2992*4882a593Smuzhiyun /* vendor step 10 */
2993*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
2994*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_WORK |
2995*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_WORK,
2996*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_INIT |
2997*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_INIT);
2998*4882a593Smuzhiyun }
2999*4882a593Smuzhiyun
3000*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3001*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3002*4882a593Smuzhiyun continue;
3003*4882a593Smuzhiyun
3004*4882a593Smuzhiyun rk3308->adc_grps_endisable[grp] = false;
3005*4882a593Smuzhiyun }
3006*4882a593Smuzhiyun
3007*4882a593Smuzhiyun return 0;
3008*4882a593Smuzhiyun }
3009*4882a593Smuzhiyun
rk3308_codec_open_capture(struct rk3308_codec_priv * rk3308)3010*4882a593Smuzhiyun static int rk3308_codec_open_capture(struct rk3308_codec_priv *rk3308)
3011*4882a593Smuzhiyun {
3012*4882a593Smuzhiyun int idx, grp = 0;
3013*4882a593Smuzhiyun int type = ADC_TYPE_NORMAL;
3014*4882a593Smuzhiyun
3015*4882a593Smuzhiyun rk3308_codec_adc_ana_enable(rk3308, type);
3016*4882a593Smuzhiyun rk3308_codec_adc_reinit_mics(rk3308, type);
3017*4882a593Smuzhiyun
3018*4882a593Smuzhiyun if (rk3308->adc_grp0_using_linein) {
3019*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0),
3020*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3021*4882a593Smuzhiyun RK3308_ADC_L_CH_NORMAL_RIGHT);
3022*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0),
3023*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3024*4882a593Smuzhiyun RK3308_ADC_R_CH_NORMAL_LEFT);
3025*4882a593Smuzhiyun } else {
3026*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3027*4882a593Smuzhiyun if (handle_loopback(rk3308) &&
3028*4882a593Smuzhiyun idx == rk3308->loopback_grp &&
3029*4882a593Smuzhiyun grp == ADC_GRP_SKIP_MAGIC) {
3030*4882a593Smuzhiyun /*
3031*4882a593Smuzhiyun * Switch to dummy BIST mode (BIST keep reset
3032*4882a593Smuzhiyun * now) to keep the zero input data in I2S bus.
3033*4882a593Smuzhiyun *
3034*4882a593Smuzhiyun * It may cause the glitch if we hold the ADC
3035*4882a593Smuzhiyun * digtital i2s module in codec.
3036*4882a593Smuzhiyun *
3037*4882a593Smuzhiyun * Then, the grp which is set from loopback_grp.
3038*4882a593Smuzhiyun */
3039*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3040*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(rk3308->loopback_grp),
3041*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3042*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_SINE);
3043*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3044*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(rk3308->loopback_grp),
3045*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3046*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_SINE);
3047*4882a593Smuzhiyun } else {
3048*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3049*4882a593Smuzhiyun continue;
3050*4882a593Smuzhiyun
3051*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3052*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3053*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3054*4882a593Smuzhiyun RK3308_ADC_L_CH_NORMAL_LEFT);
3055*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3056*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3057*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3058*4882a593Smuzhiyun RK3308_ADC_R_CH_NORMAL_RIGHT);
3059*4882a593Smuzhiyun }
3060*4882a593Smuzhiyun }
3061*4882a593Smuzhiyun }
3062*4882a593Smuzhiyun
3063*4882a593Smuzhiyun return 0;
3064*4882a593Smuzhiyun }
3065*4882a593Smuzhiyun
rk3308_codec_adc_mclk_disable(struct rk3308_codec_priv * rk3308)3066*4882a593Smuzhiyun static void rk3308_codec_adc_mclk_disable(struct rk3308_codec_priv *rk3308)
3067*4882a593Smuzhiyun {
3068*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
3069*4882a593Smuzhiyun RK3308_ADC_MCLK_MSK,
3070*4882a593Smuzhiyun RK3308_ADC_MCLK_DIS);
3071*4882a593Smuzhiyun }
3072*4882a593Smuzhiyun
rk3308_codec_adc_mclk_enable(struct rk3308_codec_priv * rk3308)3073*4882a593Smuzhiyun static void rk3308_codec_adc_mclk_enable(struct rk3308_codec_priv *rk3308)
3074*4882a593Smuzhiyun {
3075*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
3076*4882a593Smuzhiyun RK3308_ADC_MCLK_MSK,
3077*4882a593Smuzhiyun RK3308_ADC_MCLK_EN);
3078*4882a593Smuzhiyun udelay(20);
3079*4882a593Smuzhiyun }
3080*4882a593Smuzhiyun
rk3308_codec_dac_mclk_disable(struct rk3308_codec_priv * rk3308)3081*4882a593Smuzhiyun static void rk3308_codec_dac_mclk_disable(struct rk3308_codec_priv *rk3308)
3082*4882a593Smuzhiyun {
3083*4882a593Smuzhiyun if (!rk3308->no_hp_det && rk3308->codec_ver == ACODEC_VERSION_C)
3084*4882a593Smuzhiyun return;
3085*4882a593Smuzhiyun
3086*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
3087*4882a593Smuzhiyun RK3308_DAC_MCLK_MSK,
3088*4882a593Smuzhiyun RK3308_DAC_MCLK_DIS);
3089*4882a593Smuzhiyun }
3090*4882a593Smuzhiyun
rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv * rk3308)3091*4882a593Smuzhiyun static void rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv *rk3308)
3092*4882a593Smuzhiyun {
3093*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_GLB_CON,
3094*4882a593Smuzhiyun RK3308_DAC_MCLK_MSK,
3095*4882a593Smuzhiyun RK3308_DAC_MCLK_EN);
3096*4882a593Smuzhiyun udelay(20);
3097*4882a593Smuzhiyun }
3098*4882a593Smuzhiyun
rk3308_codec_open_dbg_capture(struct rk3308_codec_priv * rk3308)3099*4882a593Smuzhiyun static int rk3308_codec_open_dbg_capture(struct rk3308_codec_priv *rk3308)
3100*4882a593Smuzhiyun {
3101*4882a593Smuzhiyun rk3308_codec_adc_ana_enable(rk3308, ADC_TYPE_DBG);
3102*4882a593Smuzhiyun
3103*4882a593Smuzhiyun return 0;
3104*4882a593Smuzhiyun }
3105*4882a593Smuzhiyun
rk3308_codec_close_dbg_capture(struct rk3308_codec_priv * rk3308)3106*4882a593Smuzhiyun static int rk3308_codec_close_dbg_capture(struct rk3308_codec_priv *rk3308)
3107*4882a593Smuzhiyun {
3108*4882a593Smuzhiyun rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_DBG);
3109*4882a593Smuzhiyun
3110*4882a593Smuzhiyun return 0;
3111*4882a593Smuzhiyun }
3112*4882a593Smuzhiyun
rk3308_codec_close_all_capture(struct rk3308_codec_priv * rk3308)3113*4882a593Smuzhiyun static int rk3308_codec_close_all_capture(struct rk3308_codec_priv *rk3308)
3114*4882a593Smuzhiyun {
3115*4882a593Smuzhiyun rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_ALL);
3116*4882a593Smuzhiyun
3117*4882a593Smuzhiyun return 0;
3118*4882a593Smuzhiyun }
3119*4882a593Smuzhiyun
rk3308_codec_close_capture(struct rk3308_codec_priv * rk3308)3120*4882a593Smuzhiyun static int rk3308_codec_close_capture(struct rk3308_codec_priv *rk3308)
3121*4882a593Smuzhiyun {
3122*4882a593Smuzhiyun rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_NORMAL);
3123*4882a593Smuzhiyun
3124*4882a593Smuzhiyun return 0;
3125*4882a593Smuzhiyun }
3126*4882a593Smuzhiyun
rk3308_codec_open_playback(struct rk3308_codec_priv * rk3308)3127*4882a593Smuzhiyun static int rk3308_codec_open_playback(struct rk3308_codec_priv *rk3308)
3128*4882a593Smuzhiyun {
3129*4882a593Smuzhiyun rk3308_codec_dac_enable(rk3308);
3130*4882a593Smuzhiyun
3131*4882a593Smuzhiyun return 0;
3132*4882a593Smuzhiyun }
3133*4882a593Smuzhiyun
rk3308_codec_close_playback(struct rk3308_codec_priv * rk3308)3134*4882a593Smuzhiyun static int rk3308_codec_close_playback(struct rk3308_codec_priv *rk3308)
3135*4882a593Smuzhiyun {
3136*4882a593Smuzhiyun rk3308_codec_dac_disable(rk3308);
3137*4882a593Smuzhiyun
3138*4882a593Smuzhiyun return 0;
3139*4882a593Smuzhiyun }
3140*4882a593Smuzhiyun
rk3308_codec_llp_down(struct rk3308_codec_priv * rk3308)3141*4882a593Smuzhiyun static int rk3308_codec_llp_down(struct rk3308_codec_priv *rk3308)
3142*4882a593Smuzhiyun {
3143*4882a593Smuzhiyun rk3308_codec_adc_mclk_disable(rk3308);
3144*4882a593Smuzhiyun rk3308_codec_dac_mclk_disable(rk3308);
3145*4882a593Smuzhiyun
3146*4882a593Smuzhiyun return 0;
3147*4882a593Smuzhiyun }
3148*4882a593Smuzhiyun
rk3308_codec_llp_up(struct rk3308_codec_priv * rk3308)3149*4882a593Smuzhiyun static int rk3308_codec_llp_up(struct rk3308_codec_priv *rk3308)
3150*4882a593Smuzhiyun {
3151*4882a593Smuzhiyun rk3308_codec_adc_mclk_enable(rk3308);
3152*4882a593Smuzhiyun rk3308_codec_dac_mclk_enable(rk3308);
3153*4882a593Smuzhiyun
3154*4882a593Smuzhiyun return 0;
3155*4882a593Smuzhiyun }
3156*4882a593Smuzhiyun
rk3308_codec_dlp_down(struct rk3308_codec_priv * rk3308)3157*4882a593Smuzhiyun static int rk3308_codec_dlp_down(struct rk3308_codec_priv *rk3308)
3158*4882a593Smuzhiyun {
3159*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
3160*4882a593Smuzhiyun rk3308_codec_power_off(rk3308);
3161*4882a593Smuzhiyun
3162*4882a593Smuzhiyun return 0;
3163*4882a593Smuzhiyun }
3164*4882a593Smuzhiyun
rk3308_codec_dlp_up(struct rk3308_codec_priv * rk3308)3165*4882a593Smuzhiyun static int rk3308_codec_dlp_up(struct rk3308_codec_priv *rk3308)
3166*4882a593Smuzhiyun {
3167*4882a593Smuzhiyun rk3308_codec_power_on(rk3308);
3168*4882a593Smuzhiyun rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt);
3169*4882a593Smuzhiyun
3170*4882a593Smuzhiyun return 0;
3171*4882a593Smuzhiyun }
3172*4882a593Smuzhiyun
3173*4882a593Smuzhiyun /* Just used for debug and trace power state */
rk3308_codec_set_pm_state(struct rk3308_codec_priv * rk3308,int pm_state)3174*4882a593Smuzhiyun static void rk3308_codec_set_pm_state(struct rk3308_codec_priv *rk3308,
3175*4882a593Smuzhiyun int pm_state)
3176*4882a593Smuzhiyun {
3177*4882a593Smuzhiyun int ret;
3178*4882a593Smuzhiyun
3179*4882a593Smuzhiyun switch (pm_state) {
3180*4882a593Smuzhiyun case PM_LLP_DOWN:
3181*4882a593Smuzhiyun rk3308_codec_llp_down(rk3308);
3182*4882a593Smuzhiyun break;
3183*4882a593Smuzhiyun case PM_LLP_UP:
3184*4882a593Smuzhiyun rk3308_codec_llp_up(rk3308);
3185*4882a593Smuzhiyun break;
3186*4882a593Smuzhiyun case PM_DLP_DOWN:
3187*4882a593Smuzhiyun rk3308_codec_dlp_down(rk3308);
3188*4882a593Smuzhiyun break;
3189*4882a593Smuzhiyun case PM_DLP_UP:
3190*4882a593Smuzhiyun rk3308_codec_dlp_up(rk3308);
3191*4882a593Smuzhiyun break;
3192*4882a593Smuzhiyun case PM_DLP_DOWN2:
3193*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_rx);
3194*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_tx);
3195*4882a593Smuzhiyun clk_disable_unprepare(rk3308->pclk);
3196*4882a593Smuzhiyun break;
3197*4882a593Smuzhiyun case PM_DLP_UP2:
3198*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->pclk);
3199*4882a593Smuzhiyun if (ret < 0) {
3200*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3201*4882a593Smuzhiyun "Failed to enable acodec pclk: %d\n", ret);
3202*4882a593Smuzhiyun goto err;
3203*4882a593Smuzhiyun }
3204*4882a593Smuzhiyun
3205*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_rx);
3206*4882a593Smuzhiyun if (ret < 0) {
3207*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3208*4882a593Smuzhiyun "Failed to enable i2s mclk_rx: %d\n", ret);
3209*4882a593Smuzhiyun goto err;
3210*4882a593Smuzhiyun }
3211*4882a593Smuzhiyun
3212*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_tx);
3213*4882a593Smuzhiyun if (ret < 0) {
3214*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3215*4882a593Smuzhiyun "Failed to enable i2s mclk_tx: %d\n", ret);
3216*4882a593Smuzhiyun goto err;
3217*4882a593Smuzhiyun }
3218*4882a593Smuzhiyun break;
3219*4882a593Smuzhiyun default:
3220*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "Invalid pm_state: %d\n", pm_state);
3221*4882a593Smuzhiyun goto err;
3222*4882a593Smuzhiyun }
3223*4882a593Smuzhiyun
3224*4882a593Smuzhiyun rk3308->pm_state = pm_state;
3225*4882a593Smuzhiyun
3226*4882a593Smuzhiyun err:
3227*4882a593Smuzhiyun return;
3228*4882a593Smuzhiyun }
3229*4882a593Smuzhiyun
rk3308_codec_update_adcs_status(struct rk3308_codec_priv * rk3308,int state)3230*4882a593Smuzhiyun static void rk3308_codec_update_adcs_status(struct rk3308_codec_priv *rk3308,
3231*4882a593Smuzhiyun int state)
3232*4882a593Smuzhiyun {
3233*4882a593Smuzhiyun int idx, grp;
3234*4882a593Smuzhiyun
3235*4882a593Smuzhiyun /* Update skip_grps flags if the ADCs need to be enabled always. */
3236*4882a593Smuzhiyun if (state == PATH_BUSY) {
3237*4882a593Smuzhiyun for (idx = 0; idx < rk3308->used_adc_grps; idx++) {
3238*4882a593Smuzhiyun u32 mapped_grp = to_mapped_grp(rk3308, idx);
3239*4882a593Smuzhiyun
3240*4882a593Smuzhiyun for (grp = 0; grp < rk3308->en_always_grps_num; grp++) {
3241*4882a593Smuzhiyun u32 en_always_grp = rk3308->en_always_grps[grp];
3242*4882a593Smuzhiyun
3243*4882a593Smuzhiyun if (mapped_grp == en_always_grp)
3244*4882a593Smuzhiyun rk3308->skip_grps[en_always_grp] = 1;
3245*4882a593Smuzhiyun }
3246*4882a593Smuzhiyun }
3247*4882a593Smuzhiyun }
3248*4882a593Smuzhiyun }
3249*4882a593Smuzhiyun
rk3308_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)3250*4882a593Smuzhiyun static int rk3308_hw_params(struct snd_pcm_substream *substream,
3251*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
3252*4882a593Smuzhiyun struct snd_soc_dai *dai)
3253*4882a593Smuzhiyun {
3254*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
3255*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3256*4882a593Smuzhiyun struct snd_pcm_str *playback_str =
3257*4882a593Smuzhiyun &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
3258*4882a593Smuzhiyun int type = ADC_TYPE_LOOPBACK;
3259*4882a593Smuzhiyun int idx, grp;
3260*4882a593Smuzhiyun int ret;
3261*4882a593Smuzhiyun
3262*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3263*4882a593Smuzhiyun /* DAC only supports 2 channels */
3264*4882a593Smuzhiyun rk3308_codec_dac_mclk_enable(rk3308);
3265*4882a593Smuzhiyun rk3308_codec_open_playback(rk3308);
3266*4882a593Smuzhiyun rk3308_codec_dac_dig_config(rk3308, params);
3267*4882a593Smuzhiyun rk3308_codec_set_dac_path_state(rk3308, PATH_BUSY);
3268*4882a593Smuzhiyun } else {
3269*4882a593Smuzhiyun if (rk3308->micbias_num &&
3270*4882a593Smuzhiyun !rk3308->enable_micbias)
3271*4882a593Smuzhiyun rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt);
3272*4882a593Smuzhiyun
3273*4882a593Smuzhiyun rk3308_codec_adc_mclk_enable(rk3308);
3274*4882a593Smuzhiyun ret = rk3308_codec_update_adc_grps(rk3308, params);
3275*4882a593Smuzhiyun if (ret < 0)
3276*4882a593Smuzhiyun return ret;
3277*4882a593Smuzhiyun
3278*4882a593Smuzhiyun if (handle_loopback(rk3308)) {
3279*4882a593Smuzhiyun if (rk3308->micbias_num &&
3280*4882a593Smuzhiyun (params_channels(params) == 2) &&
3281*4882a593Smuzhiyun to_mapped_grp(rk3308, 0) == rk3308->loopback_grp)
3282*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
3283*4882a593Smuzhiyun
3284*4882a593Smuzhiyun /* Check the DACs are opened */
3285*4882a593Smuzhiyun if (playback_str->substream_opened) {
3286*4882a593Smuzhiyun rk3308->loopback_dacs_enabled = true;
3287*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3288*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3289*4882a593Smuzhiyun continue;
3290*4882a593Smuzhiyun
3291*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3292*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3293*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3294*4882a593Smuzhiyun RK3308_ADC_L_CH_NORMAL_LEFT);
3295*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3296*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3297*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3298*4882a593Smuzhiyun RK3308_ADC_R_CH_NORMAL_RIGHT);
3299*4882a593Smuzhiyun }
3300*4882a593Smuzhiyun } else {
3301*4882a593Smuzhiyun rk3308->loopback_dacs_enabled = false;
3302*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3303*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3304*4882a593Smuzhiyun continue;
3305*4882a593Smuzhiyun
3306*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3307*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3308*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3309*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_SINE);
3310*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3311*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3312*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3313*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_SINE);
3314*4882a593Smuzhiyun }
3315*4882a593Smuzhiyun }
3316*4882a593Smuzhiyun }
3317*4882a593Smuzhiyun
3318*4882a593Smuzhiyun rk3308_codec_open_capture(rk3308);
3319*4882a593Smuzhiyun rk3308_codec_adc_dig_config(rk3308, params);
3320*4882a593Smuzhiyun rk3308_codec_update_adcs_status(rk3308, PATH_BUSY);
3321*4882a593Smuzhiyun }
3322*4882a593Smuzhiyun
3323*4882a593Smuzhiyun return 0;
3324*4882a593Smuzhiyun }
3325*4882a593Smuzhiyun
rk3308_pcm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)3326*4882a593Smuzhiyun static int rk3308_pcm_trigger(struct snd_pcm_substream *substream,
3327*4882a593Smuzhiyun int cmd, struct snd_soc_dai *dai)
3328*4882a593Smuzhiyun {
3329*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
3330*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3331*4882a593Smuzhiyun int type = ADC_TYPE_LOOPBACK;
3332*4882a593Smuzhiyun int idx, grp;
3333*4882a593Smuzhiyun
3334*4882a593Smuzhiyun if (handle_loopback(rk3308) &&
3335*4882a593Smuzhiyun rk3308->dac_output == DAC_LINEOUT &&
3336*4882a593Smuzhiyun substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3337*4882a593Smuzhiyun if (cmd == SNDRV_PCM_TRIGGER_START) {
3338*4882a593Smuzhiyun struct snd_pcm_str *capture_str =
3339*4882a593Smuzhiyun &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
3340*4882a593Smuzhiyun
3341*4882a593Smuzhiyun if (capture_str->substream_opened)
3342*4882a593Smuzhiyun queue_delayed_work(system_power_efficient_wq,
3343*4882a593Smuzhiyun &rk3308->loopback_work,
3344*4882a593Smuzhiyun msecs_to_jiffies(rk3308->delay_loopback_handle_ms));
3345*4882a593Smuzhiyun } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
3346*4882a593Smuzhiyun /*
3347*4882a593Smuzhiyun * Switch to dummy bist mode to kick the glitch during disable
3348*4882a593Smuzhiyun * ADCs and keep zero input data
3349*4882a593Smuzhiyun */
3350*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3351*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3352*4882a593Smuzhiyun continue;
3353*4882a593Smuzhiyun
3354*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3355*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3356*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3357*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_SINE);
3358*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3359*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3360*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3361*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_SINE);
3362*4882a593Smuzhiyun }
3363*4882a593Smuzhiyun rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_LOOPBACK);
3364*4882a593Smuzhiyun }
3365*4882a593Smuzhiyun }
3366*4882a593Smuzhiyun
3367*4882a593Smuzhiyun return 0;
3368*4882a593Smuzhiyun }
3369*4882a593Smuzhiyun
rk3308_pcm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)3370*4882a593Smuzhiyun static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream,
3371*4882a593Smuzhiyun struct snd_soc_dai *dai)
3372*4882a593Smuzhiyun {
3373*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
3374*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3375*4882a593Smuzhiyun
3376*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3377*4882a593Smuzhiyun rk3308_codec_close_playback(rk3308);
3378*4882a593Smuzhiyun rk3308_codec_dac_mclk_disable(rk3308);
3379*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
3380*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
3381*4882a593Smuzhiyun rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE);
3382*4882a593Smuzhiyun } else {
3383*4882a593Smuzhiyun rk3308_codec_close_capture(rk3308);
3384*4882a593Smuzhiyun if (!has_en_always_grps(rk3308)) {
3385*4882a593Smuzhiyun rk3308_codec_adc_mclk_disable(rk3308);
3386*4882a593Smuzhiyun rk3308_codec_update_adcs_status(rk3308, PATH_IDLE);
3387*4882a593Smuzhiyun if (rk3308->micbias_num &&
3388*4882a593Smuzhiyun rk3308->enable_micbias)
3389*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
3390*4882a593Smuzhiyun }
3391*4882a593Smuzhiyun
3392*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
3393*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
3394*4882a593Smuzhiyun }
3395*4882a593Smuzhiyun }
3396*4882a593Smuzhiyun
3397*4882a593Smuzhiyun static struct snd_soc_dai_ops rk3308_dai_ops = {
3398*4882a593Smuzhiyun .hw_params = rk3308_hw_params,
3399*4882a593Smuzhiyun .set_fmt = rk3308_set_dai_fmt,
3400*4882a593Smuzhiyun .mute_stream = rk3308_mute_stream,
3401*4882a593Smuzhiyun .trigger = rk3308_pcm_trigger,
3402*4882a593Smuzhiyun .shutdown = rk3308_pcm_shutdown,
3403*4882a593Smuzhiyun };
3404*4882a593Smuzhiyun
3405*4882a593Smuzhiyun static struct snd_soc_dai_driver rk3308_dai[] = {
3406*4882a593Smuzhiyun {
3407*4882a593Smuzhiyun .name = "rk3308-hifi",
3408*4882a593Smuzhiyun .id = RK3308_HIFI,
3409*4882a593Smuzhiyun .playback = {
3410*4882a593Smuzhiyun .stream_name = "HiFi Playback",
3411*4882a593Smuzhiyun .channels_min = 2,
3412*4882a593Smuzhiyun .channels_max = 2,
3413*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_8000_192000,
3414*4882a593Smuzhiyun .formats = (SNDRV_PCM_FMTBIT_S16_LE |
3415*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_3LE |
3416*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |
3417*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE),
3418*4882a593Smuzhiyun },
3419*4882a593Smuzhiyun .capture = {
3420*4882a593Smuzhiyun .stream_name = "HiFi Capture",
3421*4882a593Smuzhiyun .channels_min = 1,
3422*4882a593Smuzhiyun .channels_max = 8,
3423*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_8000_192000,
3424*4882a593Smuzhiyun .formats = (SNDRV_PCM_FMTBIT_S16_LE |
3425*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_3LE |
3426*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |
3427*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE),
3428*4882a593Smuzhiyun },
3429*4882a593Smuzhiyun .ops = &rk3308_dai_ops,
3430*4882a593Smuzhiyun },
3431*4882a593Smuzhiyun };
3432*4882a593Smuzhiyun
rk3308_suspend(struct snd_soc_component * component)3433*4882a593Smuzhiyun static int rk3308_suspend(struct snd_soc_component *component)
3434*4882a593Smuzhiyun {
3435*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3436*4882a593Smuzhiyun
3437*4882a593Smuzhiyun if (rk3308->no_deep_low_power)
3438*4882a593Smuzhiyun goto out;
3439*4882a593Smuzhiyun
3440*4882a593Smuzhiyun rk3308_codec_dlp_down(rk3308);
3441*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_rx);
3442*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_tx);
3443*4882a593Smuzhiyun clk_disable_unprepare(rk3308->pclk);
3444*4882a593Smuzhiyun
3445*4882a593Smuzhiyun out:
3446*4882a593Smuzhiyun rk3308_set_bias_level(component, SND_SOC_BIAS_OFF);
3447*4882a593Smuzhiyun return 0;
3448*4882a593Smuzhiyun }
3449*4882a593Smuzhiyun
rk3308_resume(struct snd_soc_component * component)3450*4882a593Smuzhiyun static int rk3308_resume(struct snd_soc_component *component)
3451*4882a593Smuzhiyun {
3452*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3453*4882a593Smuzhiyun int ret = 0;
3454*4882a593Smuzhiyun
3455*4882a593Smuzhiyun if (rk3308->no_deep_low_power)
3456*4882a593Smuzhiyun goto out;
3457*4882a593Smuzhiyun
3458*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->pclk);
3459*4882a593Smuzhiyun if (ret < 0) {
3460*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3461*4882a593Smuzhiyun "Failed to enable acodec pclk: %d\n", ret);
3462*4882a593Smuzhiyun goto out;
3463*4882a593Smuzhiyun }
3464*4882a593Smuzhiyun
3465*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_rx);
3466*4882a593Smuzhiyun if (ret < 0) {
3467*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3468*4882a593Smuzhiyun "Failed to enable i2s mclk_rx: %d\n", ret);
3469*4882a593Smuzhiyun goto out;
3470*4882a593Smuzhiyun }
3471*4882a593Smuzhiyun
3472*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_tx);
3473*4882a593Smuzhiyun if (ret < 0) {
3474*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3475*4882a593Smuzhiyun "Failed to enable i2s mclk_tx: %d\n", ret);
3476*4882a593Smuzhiyun goto out;
3477*4882a593Smuzhiyun }
3478*4882a593Smuzhiyun
3479*4882a593Smuzhiyun rk3308_codec_dlp_up(rk3308);
3480*4882a593Smuzhiyun out:
3481*4882a593Smuzhiyun rk3308_set_bias_level(component, SND_SOC_BIAS_STANDBY);
3482*4882a593Smuzhiyun return ret;
3483*4882a593Smuzhiyun }
3484*4882a593Smuzhiyun
rk3308_codec_default_gains(struct rk3308_codec_priv * rk3308)3485*4882a593Smuzhiyun static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308)
3486*4882a593Smuzhiyun {
3487*4882a593Smuzhiyun int grp;
3488*4882a593Smuzhiyun
3489*4882a593Smuzhiyun /* Prepare ADC gains */
3490*4882a593Smuzhiyun /* vendor step 12, set MIC PGA default gains */
3491*4882a593Smuzhiyun for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
3492*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp),
3493*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_MSK |
3494*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_MSK,
3495*4882a593Smuzhiyun RK3308_ADC_CH1_MIC_GAIN_0DB |
3496*4882a593Smuzhiyun RK3308_ADC_CH2_MIC_GAIN_0DB);
3497*4882a593Smuzhiyun }
3498*4882a593Smuzhiyun
3499*4882a593Smuzhiyun /* vendor step 13, set ALC default gains */
3500*4882a593Smuzhiyun for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
3501*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp),
3502*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_MSK,
3503*4882a593Smuzhiyun RK3308_ADC_CH1_ALC_GAIN_0DB);
3504*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp),
3505*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_MSK,
3506*4882a593Smuzhiyun RK3308_ADC_CH2_ALC_GAIN_0DB);
3507*4882a593Smuzhiyun }
3508*4882a593Smuzhiyun
3509*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
3510*4882a593Smuzhiyun /* recover ADC digtial volume to 0dB */
3511*4882a593Smuzhiyun for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
3512*4882a593Smuzhiyun /* DIG_VOL: -97dB ~ +32dB */
3513*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308BS_ADC_DIG_CON05(grp),
3514*4882a593Smuzhiyun RK3308_ADC_DIG_VOL_CON_L(RK3308_ADC_DIG_VOL_0DB));
3515*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308BS_ADC_DIG_CON06(grp),
3516*4882a593Smuzhiyun RK3308_ADC_DIG_VOL_CON_R(RK3308_ADC_DIG_VOL_0DB));
3517*4882a593Smuzhiyun }
3518*4882a593Smuzhiyun }
3519*4882a593Smuzhiyun
3520*4882a593Smuzhiyun /* Prepare DAC gains */
3521*4882a593Smuzhiyun /* Step 15, set HPMIX default gains */
3522*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
3523*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_GAIN_MSK |
3524*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_GAIN_MSK,
3525*4882a593Smuzhiyun RK3308_DAC_L_HPMIX_GAIN_0DB |
3526*4882a593Smuzhiyun RK3308_DAC_R_HPMIX_GAIN_0DB);
3527*4882a593Smuzhiyun
3528*4882a593Smuzhiyun /* Step 18, set HPOUT default gains */
3529*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
3530*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_MSK,
3531*4882a593Smuzhiyun RK3308_DAC_L_HPOUT_GAIN_0DB);
3532*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
3533*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_MSK,
3534*4882a593Smuzhiyun RK3308_DAC_R_HPOUT_GAIN_0DB);
3535*4882a593Smuzhiyun
3536*4882a593Smuzhiyun /* Using the same gain to HPOUT LR channels */
3537*4882a593Smuzhiyun rk3308->hpout_l_dgain = RK3308_DAC_L_HPOUT_GAIN_0DB;
3538*4882a593Smuzhiyun rk3308->hpout_r_dgain = RK3308_DAC_R_HPOUT_GAIN_0DB;
3539*4882a593Smuzhiyun
3540*4882a593Smuzhiyun /* Step 19, set LINEOUT default gains */
3541*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
3542*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_GAIN_MSK |
3543*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_GAIN_MSK,
3544*4882a593Smuzhiyun RK3308_DAC_L_LINEOUT_GAIN_0DB |
3545*4882a593Smuzhiyun RK3308_DAC_R_LINEOUT_GAIN_0DB);
3546*4882a593Smuzhiyun
3547*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C) {
3548*4882a593Smuzhiyun /* recover DAC digtial gain to 0dB */
3549*4882a593Smuzhiyun regmap_write(rk3308->regmap, RK3308BS_DAC_DIG_CON04,
3550*4882a593Smuzhiyun RK3308BS_DAC_DIG_GAIN(RK3308BS_DAC_DIG_0DB));
3551*4882a593Smuzhiyun }
3552*4882a593Smuzhiyun
3553*4882a593Smuzhiyun return 0;
3554*4882a593Smuzhiyun }
3555*4882a593Smuzhiyun
rk3308_codec_setup_en_always_adcs(struct rk3308_codec_priv * rk3308,struct device_node * np)3556*4882a593Smuzhiyun static int rk3308_codec_setup_en_always_adcs(struct rk3308_codec_priv *rk3308,
3557*4882a593Smuzhiyun struct device_node *np)
3558*4882a593Smuzhiyun {
3559*4882a593Smuzhiyun int num, ret;
3560*4882a593Smuzhiyun
3561*4882a593Smuzhiyun num = of_count_phandle_with_args(np, "rockchip,en-always-grps", NULL);
3562*4882a593Smuzhiyun if (num < 0) {
3563*4882a593Smuzhiyun if (num == -ENOENT) {
3564*4882a593Smuzhiyun /*
3565*4882a593Smuzhiyun * If there is note use 'rockchip,en-always-grps'
3566*4882a593Smuzhiyun * property, return 0 is also right.
3567*4882a593Smuzhiyun */
3568*4882a593Smuzhiyun ret = 0;
3569*4882a593Smuzhiyun } else {
3570*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3571*4882a593Smuzhiyun "Failed to read 'rockchip,adc-grps-route' num: %d\n",
3572*4882a593Smuzhiyun num);
3573*4882a593Smuzhiyun ret = num;
3574*4882a593Smuzhiyun }
3575*4882a593Smuzhiyun
3576*4882a593Smuzhiyun rk3308->en_always_grps_num = 0;
3577*4882a593Smuzhiyun return ret;
3578*4882a593Smuzhiyun }
3579*4882a593Smuzhiyun
3580*4882a593Smuzhiyun rk3308->en_always_grps_num = num;
3581*4882a593Smuzhiyun
3582*4882a593Smuzhiyun ret = of_property_read_u32_array(np, "rockchip,en-always-grps",
3583*4882a593Smuzhiyun rk3308->en_always_grps, num);
3584*4882a593Smuzhiyun if (ret < 0) {
3585*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3586*4882a593Smuzhiyun "Failed to read 'rockchip,en-always-grps': %d\n",
3587*4882a593Smuzhiyun ret);
3588*4882a593Smuzhiyun return ret;
3589*4882a593Smuzhiyun }
3590*4882a593Smuzhiyun
3591*4882a593Smuzhiyun /* Clear all of skip_grps flags. */
3592*4882a593Smuzhiyun for (num = 0; num < ADC_LR_GROUP_MAX; num++)
3593*4882a593Smuzhiyun rk3308->skip_grps[num] = 0;
3594*4882a593Smuzhiyun
3595*4882a593Smuzhiyun /* The loopback grp should not be enabled always. */
3596*4882a593Smuzhiyun for (num = 0; num < rk3308->en_always_grps_num; num++) {
3597*4882a593Smuzhiyun if (rk3308->en_always_grps[num] == rk3308->loopback_grp) {
3598*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3599*4882a593Smuzhiyun "loopback_grp: %d should not be enabled always!\n",
3600*4882a593Smuzhiyun rk3308->loopback_grp);
3601*4882a593Smuzhiyun ret = -EINVAL;
3602*4882a593Smuzhiyun return ret;
3603*4882a593Smuzhiyun }
3604*4882a593Smuzhiyun }
3605*4882a593Smuzhiyun
3606*4882a593Smuzhiyun return 0;
3607*4882a593Smuzhiyun }
3608*4882a593Smuzhiyun
rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv * rk3308)3609*4882a593Smuzhiyun static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308)
3610*4882a593Smuzhiyun {
3611*4882a593Smuzhiyun int ret;
3612*4882a593Smuzhiyun
3613*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
3614*4882a593Smuzhiyun ret = snd_soc_add_component_controls(rk3308->component,
3615*4882a593Smuzhiyun mic_gains_b,
3616*4882a593Smuzhiyun ARRAY_SIZE(mic_gains_b));
3617*4882a593Smuzhiyun if (ret) {
3618*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3619*4882a593Smuzhiyun "%s: add mic_gains_b failed: %d\n",
3620*4882a593Smuzhiyun __func__, ret);
3621*4882a593Smuzhiyun return ret;
3622*4882a593Smuzhiyun }
3623*4882a593Smuzhiyun } else {
3624*4882a593Smuzhiyun ret = snd_soc_add_component_controls(rk3308->component,
3625*4882a593Smuzhiyun mic_gains_a,
3626*4882a593Smuzhiyun ARRAY_SIZE(mic_gains_a));
3627*4882a593Smuzhiyun if (ret) {
3628*4882a593Smuzhiyun dev_err(rk3308->plat_dev,
3629*4882a593Smuzhiyun "%s: add mic_gains_a failed: %d\n",
3630*4882a593Smuzhiyun __func__, ret);
3631*4882a593Smuzhiyun return ret;
3632*4882a593Smuzhiyun }
3633*4882a593Smuzhiyun }
3634*4882a593Smuzhiyun
3635*4882a593Smuzhiyun return 0;
3636*4882a593Smuzhiyun }
3637*4882a593Smuzhiyun
rk3308_codec_check_micbias(struct rk3308_codec_priv * rk3308,struct device_node * np)3638*4882a593Smuzhiyun static int rk3308_codec_check_micbias(struct rk3308_codec_priv *rk3308,
3639*4882a593Smuzhiyun struct device_node *np)
3640*4882a593Smuzhiyun {
3641*4882a593Smuzhiyun struct device *dev = (struct device *)rk3308->plat_dev;
3642*4882a593Smuzhiyun int num = 0, ret;
3643*4882a593Smuzhiyun
3644*4882a593Smuzhiyun /* Check internal micbias */
3645*4882a593Smuzhiyun rk3308->micbias1 =
3646*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,micbias1");
3647*4882a593Smuzhiyun if (rk3308->micbias1)
3648*4882a593Smuzhiyun num++;
3649*4882a593Smuzhiyun
3650*4882a593Smuzhiyun rk3308->micbias2 =
3651*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,micbias2");
3652*4882a593Smuzhiyun if (rk3308->micbias2)
3653*4882a593Smuzhiyun num++;
3654*4882a593Smuzhiyun
3655*4882a593Smuzhiyun rk3308->micbias_volt = RK3308_ADC_MICBIAS_VOLT_0_85; /* by default */
3656*4882a593Smuzhiyun rk3308->micbias_num = num;
3657*4882a593Smuzhiyun
3658*4882a593Smuzhiyun /* Check external micbias */
3659*4882a593Smuzhiyun rk3308->ext_micbias = EXT_MICBIAS_NONE;
3660*4882a593Smuzhiyun
3661*4882a593Smuzhiyun rk3308->micbias_en_gpio = devm_gpiod_get_optional(dev,
3662*4882a593Smuzhiyun "micbias-en",
3663*4882a593Smuzhiyun GPIOD_IN);
3664*4882a593Smuzhiyun if (!rk3308->micbias_en_gpio) {
3665*4882a593Smuzhiyun dev_info(dev, "Don't need micbias-en gpio\n");
3666*4882a593Smuzhiyun } else if (IS_ERR(rk3308->micbias_en_gpio)) {
3667*4882a593Smuzhiyun ret = PTR_ERR(rk3308->micbias_en_gpio);
3668*4882a593Smuzhiyun dev_err(dev, "Unable to claim gpio micbias-en\n");
3669*4882a593Smuzhiyun return ret;
3670*4882a593Smuzhiyun } else if (gpiod_get_value(rk3308->micbias_en_gpio)) {
3671*4882a593Smuzhiyun rk3308->ext_micbias = EXT_MICBIAS_FUNC1;
3672*4882a593Smuzhiyun }
3673*4882a593Smuzhiyun
3674*4882a593Smuzhiyun rk3308->vcc_micbias = devm_regulator_get_optional(dev,
3675*4882a593Smuzhiyun "vmicbias");
3676*4882a593Smuzhiyun if (IS_ERR(rk3308->vcc_micbias)) {
3677*4882a593Smuzhiyun if (PTR_ERR(rk3308->vcc_micbias) == -EPROBE_DEFER)
3678*4882a593Smuzhiyun return -EPROBE_DEFER;
3679*4882a593Smuzhiyun dev_info(dev, "no vmicbias regulator found\n");
3680*4882a593Smuzhiyun } else {
3681*4882a593Smuzhiyun ret = regulator_enable(rk3308->vcc_micbias);
3682*4882a593Smuzhiyun if (ret) {
3683*4882a593Smuzhiyun dev_err(dev, "Can't enable vmicbias: %d\n", ret);
3684*4882a593Smuzhiyun return ret;
3685*4882a593Smuzhiyun }
3686*4882a593Smuzhiyun rk3308->ext_micbias = EXT_MICBIAS_FUNC2;
3687*4882a593Smuzhiyun }
3688*4882a593Smuzhiyun
3689*4882a593Smuzhiyun dev_info(dev, "Check ext_micbias: %d\n", rk3308->ext_micbias);
3690*4882a593Smuzhiyun
3691*4882a593Smuzhiyun return 0;
3692*4882a593Smuzhiyun }
3693*4882a593Smuzhiyun
rk3308_codec_dapm_controls_prepare(struct rk3308_codec_priv * rk3308)3694*4882a593Smuzhiyun static int rk3308_codec_dapm_controls_prepare(struct rk3308_codec_priv *rk3308)
3695*4882a593Smuzhiyun {
3696*4882a593Smuzhiyun int grp;
3697*4882a593Smuzhiyun
3698*4882a593Smuzhiyun for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++)
3699*4882a593Smuzhiyun rk3308->hpf_cutoff[grp] = 0;
3700*4882a593Smuzhiyun
3701*4882a593Smuzhiyun rk3308_codec_dapm_mic_gains(rk3308);
3702*4882a593Smuzhiyun
3703*4882a593Smuzhiyun return 0;
3704*4882a593Smuzhiyun }
3705*4882a593Smuzhiyun
rk3308_codec_prepare(struct rk3308_codec_priv * rk3308)3706*4882a593Smuzhiyun static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308)
3707*4882a593Smuzhiyun {
3708*4882a593Smuzhiyun /* Clear registers for ADC and DAC */
3709*4882a593Smuzhiyun rk3308_codec_close_playback(rk3308);
3710*4882a593Smuzhiyun rk3308_codec_close_all_capture(rk3308);
3711*4882a593Smuzhiyun rk3308_codec_default_gains(rk3308);
3712*4882a593Smuzhiyun rk3308_codec_llp_down(rk3308);
3713*4882a593Smuzhiyun rk3308_codec_dapm_controls_prepare(rk3308);
3714*4882a593Smuzhiyun
3715*4882a593Smuzhiyun return 0;
3716*4882a593Smuzhiyun }
3717*4882a593Smuzhiyun
rk3308_probe(struct snd_soc_component * component)3718*4882a593Smuzhiyun static int rk3308_probe(struct snd_soc_component *component)
3719*4882a593Smuzhiyun {
3720*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3721*4882a593Smuzhiyun int ext_micbias;
3722*4882a593Smuzhiyun
3723*4882a593Smuzhiyun rk3308->component = component;
3724*4882a593Smuzhiyun rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE);
3725*4882a593Smuzhiyun
3726*4882a593Smuzhiyun rk3308_codec_reset(component);
3727*4882a593Smuzhiyun rk3308_codec_power_on(rk3308);
3728*4882a593Smuzhiyun
3729*4882a593Smuzhiyun /* From vendor recommend, disable micbias at first. */
3730*4882a593Smuzhiyun ext_micbias = rk3308->ext_micbias;
3731*4882a593Smuzhiyun rk3308->ext_micbias = EXT_MICBIAS_NONE;
3732*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
3733*4882a593Smuzhiyun rk3308->ext_micbias = ext_micbias;
3734*4882a593Smuzhiyun
3735*4882a593Smuzhiyun rk3308_codec_prepare(rk3308);
3736*4882a593Smuzhiyun if (!rk3308->no_hp_det)
3737*4882a593Smuzhiyun rk3308_codec_headset_detect_enable(rk3308);
3738*4882a593Smuzhiyun
3739*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
3740*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
3741*4882a593Smuzhiyun
3742*4882a593Smuzhiyun return 0;
3743*4882a593Smuzhiyun }
3744*4882a593Smuzhiyun
rk3308_remove(struct snd_soc_component * component)3745*4882a593Smuzhiyun static void rk3308_remove(struct snd_soc_component *component)
3746*4882a593Smuzhiyun {
3747*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3748*4882a593Smuzhiyun
3749*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 0);
3750*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 0);
3751*4882a593Smuzhiyun if (!rk3308->no_hp_det)
3752*4882a593Smuzhiyun rk3308_codec_headset_detect_disable(rk3308);
3753*4882a593Smuzhiyun rk3308_codec_micbias_disable(rk3308);
3754*4882a593Smuzhiyun rk3308_codec_power_off(rk3308);
3755*4882a593Smuzhiyun
3756*4882a593Smuzhiyun rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE);
3757*4882a593Smuzhiyun
3758*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
3759*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
3760*4882a593Smuzhiyun }
3761*4882a593Smuzhiyun
rk3308_codec_set_jack(struct snd_soc_component * component,struct snd_soc_jack * jack,void * data)3762*4882a593Smuzhiyun static int rk3308_codec_set_jack(struct snd_soc_component *component,
3763*4882a593Smuzhiyun struct snd_soc_jack *jack, void *data)
3764*4882a593Smuzhiyun {
3765*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
3766*4882a593Smuzhiyun
3767*4882a593Smuzhiyun /* Return directly if the DUT don't need to support headphone detection */
3768*4882a593Smuzhiyun if (rk3308->no_hp_det)
3769*4882a593Smuzhiyun return 0;
3770*4882a593Smuzhiyun
3771*4882a593Smuzhiyun rk3308->hpdet_jack = jack;
3772*4882a593Smuzhiyun
3773*4882a593Smuzhiyun /* To detect jack once during startup */
3774*4882a593Smuzhiyun disable_irq_nosync(rk3308->irq);
3775*4882a593Smuzhiyun queue_delayed_work(system_power_efficient_wq,
3776*4882a593Smuzhiyun &rk3308->hpdet_work, msecs_to_jiffies(10));
3777*4882a593Smuzhiyun
3778*4882a593Smuzhiyun dev_info(rk3308->plat_dev, "%s: Request detect hp jack once\n",
3779*4882a593Smuzhiyun __func__);
3780*4882a593Smuzhiyun
3781*4882a593Smuzhiyun return 0;
3782*4882a593Smuzhiyun }
3783*4882a593Smuzhiyun
3784*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rk3308 = {
3785*4882a593Smuzhiyun .probe = rk3308_probe,
3786*4882a593Smuzhiyun .remove = rk3308_remove,
3787*4882a593Smuzhiyun .suspend = rk3308_suspend,
3788*4882a593Smuzhiyun .resume = rk3308_resume,
3789*4882a593Smuzhiyun .set_bias_level = rk3308_set_bias_level,
3790*4882a593Smuzhiyun .controls = rk3308_codec_dapm_controls,
3791*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls),
3792*4882a593Smuzhiyun .set_jack = rk3308_codec_set_jack,
3793*4882a593Smuzhiyun };
3794*4882a593Smuzhiyun
3795*4882a593Smuzhiyun static const struct reg_default rk3308_codec_reg_defaults[] = {
3796*4882a593Smuzhiyun { RK3308_GLB_CON, 0x07 },
3797*4882a593Smuzhiyun };
3798*4882a593Smuzhiyun
rk3308_codec_write_read_reg(struct device * dev,unsigned int reg)3799*4882a593Smuzhiyun static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg)
3800*4882a593Smuzhiyun {
3801*4882a593Smuzhiyun /* All registers can be read / write */
3802*4882a593Smuzhiyun return true;
3803*4882a593Smuzhiyun }
3804*4882a593Smuzhiyun
rk3308_codec_volatile_reg(struct device * dev,unsigned int reg)3805*4882a593Smuzhiyun static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg)
3806*4882a593Smuzhiyun {
3807*4882a593Smuzhiyun return true;
3808*4882a593Smuzhiyun }
3809*4882a593Smuzhiyun
rk3308_codec_hpdetect_work(struct work_struct * work)3810*4882a593Smuzhiyun static void rk3308_codec_hpdetect_work(struct work_struct *work)
3811*4882a593Smuzhiyun {
3812*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
3813*4882a593Smuzhiyun container_of(work, struct rk3308_codec_priv, hpdet_work.work);
3814*4882a593Smuzhiyun unsigned int val, headphone_con = RK3308_CODEC_HEADPHONE_CON;
3815*4882a593Smuzhiyun int need_poll = 0, need_irq = 0;
3816*4882a593Smuzhiyun int need_report = 0, report_type = 0;
3817*4882a593Smuzhiyun int dac_output = DAC_LINEOUT;
3818*4882a593Smuzhiyun
3819*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_C)
3820*4882a593Smuzhiyun headphone_con = RK3308BS_CODEC_HEADPHONE_CON;
3821*4882a593Smuzhiyun
3822*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
3823*4882a593Smuzhiyun /* Check headphone plugged/unplugged directly. */
3824*4882a593Smuzhiyun regmap_read(rk3308->detect_grf,
3825*4882a593Smuzhiyun DETECT_GRF_ACODEC_HPDET_STATUS, &val);
3826*4882a593Smuzhiyun regmap_write(rk3308->detect_grf,
3827*4882a593Smuzhiyun DETECT_GRF_ACODEC_HPDET_STATUS_CLR, val);
3828*4882a593Smuzhiyun
3829*4882a593Smuzhiyun if (rk3308->hp_jack_reversed) {
3830*4882a593Smuzhiyun switch (val) {
3831*4882a593Smuzhiyun case 0x0:
3832*4882a593Smuzhiyun case 0x2:
3833*4882a593Smuzhiyun dac_output = DAC_HPOUT;
3834*4882a593Smuzhiyun report_type = SND_JACK_HEADPHONE;
3835*4882a593Smuzhiyun break;
3836*4882a593Smuzhiyun default:
3837*4882a593Smuzhiyun break;
3838*4882a593Smuzhiyun }
3839*4882a593Smuzhiyun } else {
3840*4882a593Smuzhiyun switch (val) {
3841*4882a593Smuzhiyun case 0x1:
3842*4882a593Smuzhiyun dac_output = DAC_HPOUT;
3843*4882a593Smuzhiyun report_type = SND_JACK_HEADPHONE;
3844*4882a593Smuzhiyun break;
3845*4882a593Smuzhiyun default:
3846*4882a593Smuzhiyun /* Includes val == 2 or others. */
3847*4882a593Smuzhiyun break;
3848*4882a593Smuzhiyun }
3849*4882a593Smuzhiyun }
3850*4882a593Smuzhiyun
3851*4882a593Smuzhiyun rk3308_codec_dac_switch(rk3308, dac_output);
3852*4882a593Smuzhiyun if (rk3308->hpdet_jack)
3853*4882a593Smuzhiyun snd_soc_jack_report(rk3308->hpdet_jack,
3854*4882a593Smuzhiyun report_type,
3855*4882a593Smuzhiyun SND_JACK_HEADPHONE);
3856*4882a593Smuzhiyun
3857*4882a593Smuzhiyun enable_irq(rk3308->irq);
3858*4882a593Smuzhiyun
3859*4882a593Smuzhiyun return;
3860*4882a593Smuzhiyun }
3861*4882a593Smuzhiyun
3862*4882a593Smuzhiyun /* Check headphone unplugged via poll. */
3863*4882a593Smuzhiyun regmap_read(rk3308->regmap, headphone_con, &val);
3864*4882a593Smuzhiyun
3865*4882a593Smuzhiyun if (rk3308->hp_jack_reversed) {
3866*4882a593Smuzhiyun if (!val) {
3867*4882a593Smuzhiyun rk3308->hp_plugged = true;
3868*4882a593Smuzhiyun report_type = SND_JACK_HEADPHONE;
3869*4882a593Smuzhiyun
3870*4882a593Smuzhiyun need_report = 1;
3871*4882a593Smuzhiyun need_irq = 1;
3872*4882a593Smuzhiyun } else {
3873*4882a593Smuzhiyun if (rk3308->hp_plugged) {
3874*4882a593Smuzhiyun rk3308->hp_plugged = false;
3875*4882a593Smuzhiyun need_report = 1;
3876*4882a593Smuzhiyun }
3877*4882a593Smuzhiyun need_poll = 1;
3878*4882a593Smuzhiyun }
3879*4882a593Smuzhiyun } else {
3880*4882a593Smuzhiyun if (!val) {
3881*4882a593Smuzhiyun rk3308->hp_plugged = false;
3882*4882a593Smuzhiyun
3883*4882a593Smuzhiyun need_report = 1;
3884*4882a593Smuzhiyun need_irq = 1;
3885*4882a593Smuzhiyun } else {
3886*4882a593Smuzhiyun if (!rk3308->hp_plugged) {
3887*4882a593Smuzhiyun rk3308->hp_plugged = true;
3888*4882a593Smuzhiyun report_type = SND_JACK_HEADPHONE;
3889*4882a593Smuzhiyun need_report = 1;
3890*4882a593Smuzhiyun }
3891*4882a593Smuzhiyun need_poll = 1;
3892*4882a593Smuzhiyun }
3893*4882a593Smuzhiyun }
3894*4882a593Smuzhiyun
3895*4882a593Smuzhiyun if (need_poll)
3896*4882a593Smuzhiyun queue_delayed_work(system_power_efficient_wq,
3897*4882a593Smuzhiyun &rk3308->hpdet_work,
3898*4882a593Smuzhiyun msecs_to_jiffies(HPDET_POLL_MS));
3899*4882a593Smuzhiyun
3900*4882a593Smuzhiyun if (need_report) {
3901*4882a593Smuzhiyun if (report_type)
3902*4882a593Smuzhiyun dac_output = DAC_HPOUT;
3903*4882a593Smuzhiyun
3904*4882a593Smuzhiyun rk3308_codec_dac_switch(rk3308, dac_output);
3905*4882a593Smuzhiyun
3906*4882a593Smuzhiyun if (rk3308->hpdet_jack)
3907*4882a593Smuzhiyun snd_soc_jack_report(rk3308->hpdet_jack,
3908*4882a593Smuzhiyun report_type,
3909*4882a593Smuzhiyun SND_JACK_HEADPHONE);
3910*4882a593Smuzhiyun }
3911*4882a593Smuzhiyun
3912*4882a593Smuzhiyun if (need_irq)
3913*4882a593Smuzhiyun enable_irq(rk3308->irq);
3914*4882a593Smuzhiyun }
3915*4882a593Smuzhiyun
rk3308_codec_loopback_work(struct work_struct * work)3916*4882a593Smuzhiyun static void rk3308_codec_loopback_work(struct work_struct *work)
3917*4882a593Smuzhiyun {
3918*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
3919*4882a593Smuzhiyun container_of(work, struct rk3308_codec_priv, loopback_work.work);
3920*4882a593Smuzhiyun int type = ADC_TYPE_LOOPBACK;
3921*4882a593Smuzhiyun int idx, grp;
3922*4882a593Smuzhiyun
3923*4882a593Smuzhiyun /* Prepare loopback ADCs */
3924*4882a593Smuzhiyun rk3308_codec_adc_ana_enable(rk3308, type);
3925*4882a593Smuzhiyun
3926*4882a593Smuzhiyun /* Waiting ADCs are stable */
3927*4882a593Smuzhiyun msleep(ADC_STABLE_MS);
3928*4882a593Smuzhiyun
3929*4882a593Smuzhiyun /* Recover normal mode after enable ADCs */
3930*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
3931*4882a593Smuzhiyun if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1)
3932*4882a593Smuzhiyun continue;
3933*4882a593Smuzhiyun
3934*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3935*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3936*4882a593Smuzhiyun RK3308_ADC_L_CH_BIST_MSK,
3937*4882a593Smuzhiyun RK3308_ADC_L_CH_NORMAL_LEFT);
3938*4882a593Smuzhiyun regmap_update_bits(rk3308->regmap,
3939*4882a593Smuzhiyun RK3308_ADC_DIG_CON03(grp),
3940*4882a593Smuzhiyun RK3308_ADC_R_CH_BIST_MSK,
3941*4882a593Smuzhiyun RK3308_ADC_R_CH_NORMAL_RIGHT);
3942*4882a593Smuzhiyun }
3943*4882a593Smuzhiyun }
3944*4882a593Smuzhiyun
rk3308_codec_hpdet_isr(int irq,void * data)3945*4882a593Smuzhiyun static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data)
3946*4882a593Smuzhiyun {
3947*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = data;
3948*4882a593Smuzhiyun
3949*4882a593Smuzhiyun /*
3950*4882a593Smuzhiyun * For the high level irq trigger, disable irq and avoid a lot of
3951*4882a593Smuzhiyun * repeated irq handlers entry.
3952*4882a593Smuzhiyun */
3953*4882a593Smuzhiyun disable_irq_nosync(rk3308->irq);
3954*4882a593Smuzhiyun queue_delayed_work(system_power_efficient_wq,
3955*4882a593Smuzhiyun &rk3308->hpdet_work, msecs_to_jiffies(10));
3956*4882a593Smuzhiyun
3957*4882a593Smuzhiyun return IRQ_HANDLED;
3958*4882a593Smuzhiyun }
3959*4882a593Smuzhiyun
3960*4882a593Smuzhiyun static const struct regmap_config rk3308_codec_regmap_config = {
3961*4882a593Smuzhiyun .reg_bits = 32,
3962*4882a593Smuzhiyun .reg_stride = 4,
3963*4882a593Smuzhiyun .val_bits = 32,
3964*4882a593Smuzhiyun .max_register = RK3308_DAC_ANA_CON15,
3965*4882a593Smuzhiyun .writeable_reg = rk3308_codec_write_read_reg,
3966*4882a593Smuzhiyun .readable_reg = rk3308_codec_write_read_reg,
3967*4882a593Smuzhiyun .volatile_reg = rk3308_codec_volatile_reg,
3968*4882a593Smuzhiyun .reg_defaults = rk3308_codec_reg_defaults,
3969*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults),
3970*4882a593Smuzhiyun .cache_type = REGCACHE_FLAT,
3971*4882a593Smuzhiyun };
3972*4882a593Smuzhiyun
pm_state_show(struct device * dev,struct device_attribute * attr,char * buf)3973*4882a593Smuzhiyun static ssize_t pm_state_show(struct device *dev,
3974*4882a593Smuzhiyun struct device_attribute *attr,
3975*4882a593Smuzhiyun char *buf)
3976*4882a593Smuzhiyun {
3977*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
3978*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
3979*4882a593Smuzhiyun
3980*4882a593Smuzhiyun return sprintf(buf, "pm_state: %d\n", rk3308->pm_state);
3981*4882a593Smuzhiyun }
3982*4882a593Smuzhiyun
pm_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3983*4882a593Smuzhiyun static ssize_t pm_state_store(struct device *dev,
3984*4882a593Smuzhiyun struct device_attribute *attr,
3985*4882a593Smuzhiyun const char *buf, size_t count)
3986*4882a593Smuzhiyun {
3987*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
3988*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
3989*4882a593Smuzhiyun unsigned long pm_state;
3990*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &pm_state);
3991*4882a593Smuzhiyun
3992*4882a593Smuzhiyun if (ret < 0) {
3993*4882a593Smuzhiyun dev_err(dev, "Invalid pm_state: %ld, ret: %d\n",
3994*4882a593Smuzhiyun pm_state, ret);
3995*4882a593Smuzhiyun return -EINVAL;
3996*4882a593Smuzhiyun }
3997*4882a593Smuzhiyun
3998*4882a593Smuzhiyun rk3308_codec_set_pm_state(rk3308, pm_state);
3999*4882a593Smuzhiyun
4000*4882a593Smuzhiyun dev_info(dev, "Store pm_state: %d\n", rk3308->pm_state);
4001*4882a593Smuzhiyun
4002*4882a593Smuzhiyun return count;
4003*4882a593Smuzhiyun }
4004*4882a593Smuzhiyun
adc_grps_show(struct device * dev,struct device_attribute * attr,char * buf)4005*4882a593Smuzhiyun static ssize_t adc_grps_show(struct device *dev,
4006*4882a593Smuzhiyun struct device_attribute *attr,
4007*4882a593Smuzhiyun char *buf)
4008*4882a593Smuzhiyun {
4009*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4010*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4011*4882a593Smuzhiyun u32 grp;
4012*4882a593Smuzhiyun int type = ADC_TYPE_NORMAL, count = 0;
4013*4882a593Smuzhiyun int idx;
4014*4882a593Smuzhiyun
4015*4882a593Smuzhiyun count += sprintf(buf + count, "current used adc_grps:\n");
4016*4882a593Smuzhiyun count += sprintf(buf + count, "- normal:");
4017*4882a593Smuzhiyun for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++)
4018*4882a593Smuzhiyun count += sprintf(buf + count, " %d", grp);
4019*4882a593Smuzhiyun count += sprintf(buf + count, "\n");
4020*4882a593Smuzhiyun count += sprintf(buf + count, "- loopback: %d\n",
4021*4882a593Smuzhiyun rk3308->loopback_grp);
4022*4882a593Smuzhiyun
4023*4882a593Smuzhiyun return count;
4024*4882a593Smuzhiyun }
4025*4882a593Smuzhiyun
adc_grps_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4026*4882a593Smuzhiyun static ssize_t adc_grps_store(struct device *dev,
4027*4882a593Smuzhiyun struct device_attribute *attr,
4028*4882a593Smuzhiyun const char *buf, size_t count)
4029*4882a593Smuzhiyun {
4030*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4031*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4032*4882a593Smuzhiyun char adc_type;
4033*4882a593Smuzhiyun int grps, ret;
4034*4882a593Smuzhiyun
4035*4882a593Smuzhiyun ret = sscanf(buf, "%c,%d", &adc_type, &grps);
4036*4882a593Smuzhiyun if (ret != 2) {
4037*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n",
4038*4882a593Smuzhiyun __func__, ret);
4039*4882a593Smuzhiyun return -EFAULT;
4040*4882a593Smuzhiyun }
4041*4882a593Smuzhiyun
4042*4882a593Smuzhiyun if (adc_type == 'n')
4043*4882a593Smuzhiyun rk3308->used_adc_grps = grps;
4044*4882a593Smuzhiyun else if (adc_type == 'l')
4045*4882a593Smuzhiyun rk3308->loopback_grp = grps;
4046*4882a593Smuzhiyun
4047*4882a593Smuzhiyun return count;
4048*4882a593Smuzhiyun }
4049*4882a593Smuzhiyun
adc_grps_route_show(struct device * dev,struct device_attribute * attr,char * buf)4050*4882a593Smuzhiyun static ssize_t adc_grps_route_show(struct device *dev,
4051*4882a593Smuzhiyun struct device_attribute *attr,
4052*4882a593Smuzhiyun char *buf)
4053*4882a593Smuzhiyun {
4054*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4055*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4056*4882a593Smuzhiyun char which_i2s[32] = {0};
4057*4882a593Smuzhiyun int count = 0;
4058*4882a593Smuzhiyun u32 grp;
4059*4882a593Smuzhiyun
4060*4882a593Smuzhiyun switch (rk3308->which_i2s) {
4061*4882a593Smuzhiyun case ACODEC_TO_I2S1_2CH:
4062*4882a593Smuzhiyun strcpy(which_i2s, "i2s1_2ch");
4063*4882a593Smuzhiyun break;
4064*4882a593Smuzhiyun case ACODEC_TO_I2S3_4CH:
4065*4882a593Smuzhiyun strcpy(which_i2s, "i2s3_4ch");
4066*4882a593Smuzhiyun break;
4067*4882a593Smuzhiyun default:
4068*4882a593Smuzhiyun strcpy(which_i2s, "i2s2_8ch");
4069*4882a593Smuzhiyun break;
4070*4882a593Smuzhiyun }
4071*4882a593Smuzhiyun
4072*4882a593Smuzhiyun count += sprintf(buf + count, "%s from acodec route mapping:\n",
4073*4882a593Smuzhiyun which_i2s);
4074*4882a593Smuzhiyun for (grp = 0; grp < rk3308->to_i2s_grps; grp++) {
4075*4882a593Smuzhiyun count += sprintf(buf + count, "* sdi_%d <-- sdo_%d\n",
4076*4882a593Smuzhiyun grp, rk3308->i2s_sdis[grp]);
4077*4882a593Smuzhiyun }
4078*4882a593Smuzhiyun
4079*4882a593Smuzhiyun return count;
4080*4882a593Smuzhiyun }
4081*4882a593Smuzhiyun
adc_grps_route_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4082*4882a593Smuzhiyun static ssize_t adc_grps_route_store(struct device *dev,
4083*4882a593Smuzhiyun struct device_attribute *attr,
4084*4882a593Smuzhiyun const char *buf, size_t count)
4085*4882a593Smuzhiyun {
4086*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4087*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4088*4882a593Smuzhiyun int which_i2s, idx, i2s_sdis[ADC_LR_GROUP_MAX];
4089*4882a593Smuzhiyun int ret;
4090*4882a593Smuzhiyun
4091*4882a593Smuzhiyun ret = sscanf(buf, "%d,%d,%d,%d,%d", &which_i2s,
4092*4882a593Smuzhiyun &i2s_sdis[0], &i2s_sdis[1], &i2s_sdis[2], &i2s_sdis[3]);
4093*4882a593Smuzhiyun if (ret != 5) {
4094*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n",
4095*4882a593Smuzhiyun __func__, ret);
4096*4882a593Smuzhiyun goto err;
4097*4882a593Smuzhiyun }
4098*4882a593Smuzhiyun
4099*4882a593Smuzhiyun if (which_i2s < ACODEC_TO_I2S2_8CH ||
4100*4882a593Smuzhiyun which_i2s > ACODEC_TO_I2S1_2CH) {
4101*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "Invalid i2s type: %d\n", which_i2s);
4102*4882a593Smuzhiyun goto err;
4103*4882a593Smuzhiyun }
4104*4882a593Smuzhiyun
4105*4882a593Smuzhiyun rk3308->which_i2s = which_i2s;
4106*4882a593Smuzhiyun
4107*4882a593Smuzhiyun switch (rk3308->which_i2s) {
4108*4882a593Smuzhiyun case ACODEC_TO_I2S1_2CH:
4109*4882a593Smuzhiyun rk3308->to_i2s_grps = 1;
4110*4882a593Smuzhiyun break;
4111*4882a593Smuzhiyun case ACODEC_TO_I2S3_4CH:
4112*4882a593Smuzhiyun rk3308->to_i2s_grps = 2;
4113*4882a593Smuzhiyun break;
4114*4882a593Smuzhiyun default:
4115*4882a593Smuzhiyun rk3308->to_i2s_grps = 4;
4116*4882a593Smuzhiyun break;
4117*4882a593Smuzhiyun }
4118*4882a593Smuzhiyun
4119*4882a593Smuzhiyun for (idx = 0; idx < rk3308->to_i2s_grps; idx++)
4120*4882a593Smuzhiyun rk3308->i2s_sdis[idx] = i2s_sdis[idx];
4121*4882a593Smuzhiyun
4122*4882a593Smuzhiyun rk3308_codec_adc_grps_route_config(rk3308);
4123*4882a593Smuzhiyun
4124*4882a593Smuzhiyun err:
4125*4882a593Smuzhiyun return count;
4126*4882a593Smuzhiyun }
4127*4882a593Smuzhiyun
adc_grp0_in_show(struct device * dev,struct device_attribute * attr,char * buf)4128*4882a593Smuzhiyun static ssize_t adc_grp0_in_show(struct device *dev,
4129*4882a593Smuzhiyun struct device_attribute *attr,
4130*4882a593Smuzhiyun char *buf)
4131*4882a593Smuzhiyun {
4132*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4133*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4134*4882a593Smuzhiyun
4135*4882a593Smuzhiyun return sprintf(buf, "adc ch0 using: %s\n",
4136*4882a593Smuzhiyun rk3308->adc_grp0_using_linein ? "line in" : "mic in");
4137*4882a593Smuzhiyun }
4138*4882a593Smuzhiyun
adc_grp0_in_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4139*4882a593Smuzhiyun static ssize_t adc_grp0_in_store(struct device *dev,
4140*4882a593Smuzhiyun struct device_attribute *attr,
4141*4882a593Smuzhiyun const char *buf, size_t count)
4142*4882a593Smuzhiyun {
4143*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4144*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4145*4882a593Smuzhiyun unsigned long using_linein;
4146*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &using_linein);
4147*4882a593Smuzhiyun
4148*4882a593Smuzhiyun if (ret < 0 || using_linein > 1) {
4149*4882a593Smuzhiyun dev_err(dev, "Invalid input status: %ld, ret: %d\n",
4150*4882a593Smuzhiyun using_linein, ret);
4151*4882a593Smuzhiyun return -EINVAL;
4152*4882a593Smuzhiyun }
4153*4882a593Smuzhiyun
4154*4882a593Smuzhiyun rk3308->adc_grp0_using_linein = using_linein;
4155*4882a593Smuzhiyun
4156*4882a593Smuzhiyun dev_info(dev, "store using_linein: %d\n",
4157*4882a593Smuzhiyun rk3308->adc_grp0_using_linein);
4158*4882a593Smuzhiyun
4159*4882a593Smuzhiyun return count;
4160*4882a593Smuzhiyun }
4161*4882a593Smuzhiyun
adc_zerocross_show(struct device * dev,struct device_attribute * attr,char * buf)4162*4882a593Smuzhiyun static ssize_t adc_zerocross_show(struct device *dev,
4163*4882a593Smuzhiyun struct device_attribute *attr,
4164*4882a593Smuzhiyun char *buf)
4165*4882a593Smuzhiyun {
4166*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4167*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4168*4882a593Smuzhiyun
4169*4882a593Smuzhiyun return sprintf(buf, "adc zerocross: %s\n",
4170*4882a593Smuzhiyun rk3308->adc_zerocross ? "enabled" : "disabled");
4171*4882a593Smuzhiyun }
4172*4882a593Smuzhiyun
adc_zerocross_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4173*4882a593Smuzhiyun static ssize_t adc_zerocross_store(struct device *dev,
4174*4882a593Smuzhiyun struct device_attribute *attr,
4175*4882a593Smuzhiyun const char *buf, size_t count)
4176*4882a593Smuzhiyun {
4177*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4178*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4179*4882a593Smuzhiyun unsigned long zerocross;
4180*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &zerocross);
4181*4882a593Smuzhiyun
4182*4882a593Smuzhiyun if (ret < 0 || zerocross > 1) {
4183*4882a593Smuzhiyun dev_err(dev, "Invalid zerocross: %ld, ret: %d\n",
4184*4882a593Smuzhiyun zerocross, ret);
4185*4882a593Smuzhiyun return -EINVAL;
4186*4882a593Smuzhiyun }
4187*4882a593Smuzhiyun
4188*4882a593Smuzhiyun rk3308->adc_zerocross = zerocross;
4189*4882a593Smuzhiyun
4190*4882a593Smuzhiyun dev_info(dev, "store adc zerocross: %d\n", rk3308->adc_zerocross);
4191*4882a593Smuzhiyun
4192*4882a593Smuzhiyun return count;
4193*4882a593Smuzhiyun }
4194*4882a593Smuzhiyun
adc_grps_endisable_show(struct device * dev,struct device_attribute * attr,char * buf)4195*4882a593Smuzhiyun static ssize_t adc_grps_endisable_show(struct device *dev,
4196*4882a593Smuzhiyun struct device_attribute *attr,
4197*4882a593Smuzhiyun char *buf)
4198*4882a593Smuzhiyun {
4199*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4200*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4201*4882a593Smuzhiyun int count = 0, i;
4202*4882a593Smuzhiyun
4203*4882a593Smuzhiyun count += sprintf(buf + count, "enabled adc grps:");
4204*4882a593Smuzhiyun for (i = 0; i < ADC_LR_GROUP_MAX; i++)
4205*4882a593Smuzhiyun count += sprintf(buf + count, "%d ",
4206*4882a593Smuzhiyun rk3308->adc_grps_endisable[i]);
4207*4882a593Smuzhiyun
4208*4882a593Smuzhiyun count += sprintf(buf + count, "\n");
4209*4882a593Smuzhiyun return count;
4210*4882a593Smuzhiyun }
4211*4882a593Smuzhiyun
adc_grps_endisable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4212*4882a593Smuzhiyun static ssize_t adc_grps_endisable_store(struct device *dev,
4213*4882a593Smuzhiyun struct device_attribute *attr,
4214*4882a593Smuzhiyun const char *buf, size_t count)
4215*4882a593Smuzhiyun {
4216*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4217*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4218*4882a593Smuzhiyun int grp, endisable, ret;
4219*4882a593Smuzhiyun
4220*4882a593Smuzhiyun ret = sscanf(buf, "%d,%d", &grp, &endisable);
4221*4882a593Smuzhiyun if (ret != 2) {
4222*4882a593Smuzhiyun dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n",
4223*4882a593Smuzhiyun __func__, ret);
4224*4882a593Smuzhiyun return -EFAULT;
4225*4882a593Smuzhiyun }
4226*4882a593Smuzhiyun
4227*4882a593Smuzhiyun rk3308->cur_dbg_grp = grp;
4228*4882a593Smuzhiyun
4229*4882a593Smuzhiyun if (endisable)
4230*4882a593Smuzhiyun rk3308_codec_open_dbg_capture(rk3308);
4231*4882a593Smuzhiyun else
4232*4882a593Smuzhiyun rk3308_codec_close_dbg_capture(rk3308);
4233*4882a593Smuzhiyun
4234*4882a593Smuzhiyun dev_info(dev, "ADC grp %d endisable: %d\n", grp, endisable);
4235*4882a593Smuzhiyun
4236*4882a593Smuzhiyun return count;
4237*4882a593Smuzhiyun }
4238*4882a593Smuzhiyun
dac_endisable_show(struct device * dev,struct device_attribute * attr,char * buf)4239*4882a593Smuzhiyun static ssize_t dac_endisable_show(struct device *dev,
4240*4882a593Smuzhiyun struct device_attribute *attr,
4241*4882a593Smuzhiyun char *buf)
4242*4882a593Smuzhiyun {
4243*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4244*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4245*4882a593Smuzhiyun
4246*4882a593Smuzhiyun return sprintf(buf, "%d\n", rk3308->dac_endisable);
4247*4882a593Smuzhiyun }
4248*4882a593Smuzhiyun
dac_endisable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4249*4882a593Smuzhiyun static ssize_t dac_endisable_store(struct device *dev,
4250*4882a593Smuzhiyun struct device_attribute *attr,
4251*4882a593Smuzhiyun const char *buf, size_t count)
4252*4882a593Smuzhiyun {
4253*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4254*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4255*4882a593Smuzhiyun unsigned long endisable;
4256*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &endisable);
4257*4882a593Smuzhiyun
4258*4882a593Smuzhiyun if (ret < 0) {
4259*4882a593Smuzhiyun dev_err(dev, "Invalid endisable: %ld, ret: %d\n",
4260*4882a593Smuzhiyun endisable, ret);
4261*4882a593Smuzhiyun return -EINVAL;
4262*4882a593Smuzhiyun }
4263*4882a593Smuzhiyun
4264*4882a593Smuzhiyun if (endisable)
4265*4882a593Smuzhiyun rk3308_codec_open_playback(rk3308);
4266*4882a593Smuzhiyun else
4267*4882a593Smuzhiyun rk3308_codec_close_playback(rk3308);
4268*4882a593Smuzhiyun
4269*4882a593Smuzhiyun dev_info(dev, "DAC endisable: %ld\n", endisable);
4270*4882a593Smuzhiyun
4271*4882a593Smuzhiyun return count;
4272*4882a593Smuzhiyun }
4273*4882a593Smuzhiyun
dac_output_show(struct device * dev,struct device_attribute * attr,char * buf)4274*4882a593Smuzhiyun static ssize_t dac_output_show(struct device *dev,
4275*4882a593Smuzhiyun struct device_attribute *attr,
4276*4882a593Smuzhiyun char *buf)
4277*4882a593Smuzhiyun {
4278*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4279*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4280*4882a593Smuzhiyun ssize_t ret = 0;
4281*4882a593Smuzhiyun
4282*4882a593Smuzhiyun switch (rk3308->dac_output) {
4283*4882a593Smuzhiyun case DAC_LINEOUT:
4284*4882a593Smuzhiyun ret = sprintf(buf, "dac path: %s\n", "line out");
4285*4882a593Smuzhiyun break;
4286*4882a593Smuzhiyun case DAC_HPOUT:
4287*4882a593Smuzhiyun ret = sprintf(buf, "dac path: %s\n", "hp out");
4288*4882a593Smuzhiyun break;
4289*4882a593Smuzhiyun case DAC_LINEOUT_HPOUT:
4290*4882a593Smuzhiyun ret = sprintf(buf, "dac path: %s\n",
4291*4882a593Smuzhiyun "both line out and hp out");
4292*4882a593Smuzhiyun break;
4293*4882a593Smuzhiyun default:
4294*4882a593Smuzhiyun pr_err("Invalid dac path: %d ?\n", rk3308->dac_output);
4295*4882a593Smuzhiyun break;
4296*4882a593Smuzhiyun }
4297*4882a593Smuzhiyun
4298*4882a593Smuzhiyun return ret;
4299*4882a593Smuzhiyun }
4300*4882a593Smuzhiyun
dac_output_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4301*4882a593Smuzhiyun static ssize_t dac_output_store(struct device *dev,
4302*4882a593Smuzhiyun struct device_attribute *attr,
4303*4882a593Smuzhiyun const char *buf, size_t count)
4304*4882a593Smuzhiyun {
4305*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4306*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4307*4882a593Smuzhiyun unsigned long dac_output;
4308*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &dac_output);
4309*4882a593Smuzhiyun
4310*4882a593Smuzhiyun if (ret < 0) {
4311*4882a593Smuzhiyun dev_err(dev, "Invalid input status: %ld, ret: %d\n",
4312*4882a593Smuzhiyun dac_output, ret);
4313*4882a593Smuzhiyun return -EINVAL;
4314*4882a593Smuzhiyun }
4315*4882a593Smuzhiyun
4316*4882a593Smuzhiyun rk3308_codec_dac_switch(rk3308, dac_output);
4317*4882a593Smuzhiyun
4318*4882a593Smuzhiyun dev_info(dev, "Store dac_output: %d\n", rk3308->dac_output);
4319*4882a593Smuzhiyun
4320*4882a593Smuzhiyun return count;
4321*4882a593Smuzhiyun }
4322*4882a593Smuzhiyun
enable_all_adcs_show(struct device * dev,struct device_attribute * attr,char * buf)4323*4882a593Smuzhiyun static ssize_t enable_all_adcs_show(struct device *dev,
4324*4882a593Smuzhiyun struct device_attribute *attr,
4325*4882a593Smuzhiyun char *buf)
4326*4882a593Smuzhiyun {
4327*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4328*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4329*4882a593Smuzhiyun
4330*4882a593Smuzhiyun return sprintf(buf, "%d\n", rk3308->enable_all_adcs);
4331*4882a593Smuzhiyun }
4332*4882a593Smuzhiyun
enable_all_adcs_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4333*4882a593Smuzhiyun static ssize_t enable_all_adcs_store(struct device *dev,
4334*4882a593Smuzhiyun struct device_attribute *attr,
4335*4882a593Smuzhiyun const char *buf, size_t count)
4336*4882a593Smuzhiyun {
4337*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4338*4882a593Smuzhiyun container_of(dev, struct rk3308_codec_priv, dev);
4339*4882a593Smuzhiyun unsigned long enable;
4340*4882a593Smuzhiyun int ret = kstrtoul(buf, 10, &enable);
4341*4882a593Smuzhiyun
4342*4882a593Smuzhiyun if (ret < 0) {
4343*4882a593Smuzhiyun dev_err(dev, "Invalid enable value: %ld, ret: %d\n",
4344*4882a593Smuzhiyun enable, ret);
4345*4882a593Smuzhiyun return -EINVAL;
4346*4882a593Smuzhiyun }
4347*4882a593Smuzhiyun
4348*4882a593Smuzhiyun rk3308->enable_all_adcs = enable;
4349*4882a593Smuzhiyun
4350*4882a593Smuzhiyun return count;
4351*4882a593Smuzhiyun }
4352*4882a593Smuzhiyun
4353*4882a593Smuzhiyun static const struct device_attribute acodec_attrs[] = {
4354*4882a593Smuzhiyun __ATTR_RW(adc_grps),
4355*4882a593Smuzhiyun __ATTR_RW(adc_grps_endisable),
4356*4882a593Smuzhiyun __ATTR_RW(adc_grps_route),
4357*4882a593Smuzhiyun __ATTR_RW(adc_grp0_in),
4358*4882a593Smuzhiyun __ATTR_RW(adc_zerocross),
4359*4882a593Smuzhiyun __ATTR_RW(dac_endisable),
4360*4882a593Smuzhiyun __ATTR_RW(dac_output),
4361*4882a593Smuzhiyun __ATTR_RW(enable_all_adcs),
4362*4882a593Smuzhiyun __ATTR_RW(pm_state),
4363*4882a593Smuzhiyun };
4364*4882a593Smuzhiyun
rk3308_codec_device_release(struct device * dev)4365*4882a593Smuzhiyun static void rk3308_codec_device_release(struct device *dev)
4366*4882a593Smuzhiyun {
4367*4882a593Smuzhiyun /* Do nothing */
4368*4882a593Smuzhiyun }
4369*4882a593Smuzhiyun
rk3308_codec_sysfs_init(struct platform_device * pdev,struct rk3308_codec_priv * rk3308)4370*4882a593Smuzhiyun static int rk3308_codec_sysfs_init(struct platform_device *pdev,
4371*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308)
4372*4882a593Smuzhiyun {
4373*4882a593Smuzhiyun struct device *dev = &rk3308->dev;
4374*4882a593Smuzhiyun int i;
4375*4882a593Smuzhiyun
4376*4882a593Smuzhiyun dev->release = rk3308_codec_device_release;
4377*4882a593Smuzhiyun dev->parent = &pdev->dev;
4378*4882a593Smuzhiyun set_dev_node(dev, dev_to_node(&pdev->dev));
4379*4882a593Smuzhiyun dev_set_name(dev, "rk3308-acodec-dev");
4380*4882a593Smuzhiyun
4381*4882a593Smuzhiyun if (device_register(dev)) {
4382*4882a593Smuzhiyun dev_err(&pdev->dev,
4383*4882a593Smuzhiyun "Register 'rk3308-acodec-dev' failed\n");
4384*4882a593Smuzhiyun dev->parent = NULL;
4385*4882a593Smuzhiyun return -ENOMEM;
4386*4882a593Smuzhiyun }
4387*4882a593Smuzhiyun
4388*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++) {
4389*4882a593Smuzhiyun if (device_create_file(dev, &acodec_attrs[i])) {
4390*4882a593Smuzhiyun dev_err(&pdev->dev,
4391*4882a593Smuzhiyun "Create 'rk3308-acodec-dev' attr failed\n");
4392*4882a593Smuzhiyun device_unregister(dev);
4393*4882a593Smuzhiyun return -ENOMEM;
4394*4882a593Smuzhiyun }
4395*4882a593Smuzhiyun }
4396*4882a593Smuzhiyun
4397*4882a593Smuzhiyun return 0;
4398*4882a593Smuzhiyun }
4399*4882a593Smuzhiyun
rk3308_codec_sysfs_exit(struct rk3308_codec_priv * rk3308)4400*4882a593Smuzhiyun static void rk3308_codec_sysfs_exit(struct rk3308_codec_priv *rk3308)
4401*4882a593Smuzhiyun {
4402*4882a593Smuzhiyun struct device *dev = &rk3308->dev;
4403*4882a593Smuzhiyun unsigned int i;
4404*4882a593Smuzhiyun
4405*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++)
4406*4882a593Smuzhiyun device_remove_file(dev, &acodec_attrs[i]);
4407*4882a593Smuzhiyun device_unregister(dev);
4408*4882a593Smuzhiyun }
4409*4882a593Smuzhiyun
4410*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
rk3308_codec_debugfs_reg_show(struct seq_file * s,void * v)4411*4882a593Smuzhiyun static int rk3308_codec_debugfs_reg_show(struct seq_file *s, void *v)
4412*4882a593Smuzhiyun {
4413*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 = s->private;
4414*4882a593Smuzhiyun unsigned int i;
4415*4882a593Smuzhiyun unsigned int val;
4416*4882a593Smuzhiyun
4417*4882a593Smuzhiyun for (i = RK3308_GLB_CON; i <= RK3308_DAC_ANA_CON13; i += 4) {
4418*4882a593Smuzhiyun regmap_read(rk3308->regmap, i, &val);
4419*4882a593Smuzhiyun if (!(i % 16))
4420*4882a593Smuzhiyun seq_printf(s, "\nR:%04x: ", i);
4421*4882a593Smuzhiyun seq_printf(s, "%08x ", val);
4422*4882a593Smuzhiyun }
4423*4882a593Smuzhiyun
4424*4882a593Smuzhiyun seq_puts(s, "\n");
4425*4882a593Smuzhiyun
4426*4882a593Smuzhiyun return 0;
4427*4882a593Smuzhiyun }
4428*4882a593Smuzhiyun
rk3308_codec_debugfs_reg_operate(struct file * file,const char __user * buf,size_t count,loff_t * ppos)4429*4882a593Smuzhiyun static ssize_t rk3308_codec_debugfs_reg_operate(struct file *file,
4430*4882a593Smuzhiyun const char __user *buf,
4431*4882a593Smuzhiyun size_t count, loff_t *ppos)
4432*4882a593Smuzhiyun {
4433*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4434*4882a593Smuzhiyun ((struct seq_file *)file->private_data)->private;
4435*4882a593Smuzhiyun unsigned int reg, val;
4436*4882a593Smuzhiyun char op;
4437*4882a593Smuzhiyun char kbuf[32];
4438*4882a593Smuzhiyun int ret;
4439*4882a593Smuzhiyun
4440*4882a593Smuzhiyun if (count >= sizeof(kbuf))
4441*4882a593Smuzhiyun return -EINVAL;
4442*4882a593Smuzhiyun
4443*4882a593Smuzhiyun if (copy_from_user(kbuf, buf, count))
4444*4882a593Smuzhiyun return -EFAULT;
4445*4882a593Smuzhiyun kbuf[count] = '\0';
4446*4882a593Smuzhiyun
4447*4882a593Smuzhiyun ret = sscanf(kbuf, "%c,%x,%x", &op, ®, &val);
4448*4882a593Smuzhiyun if (ret != 3) {
4449*4882a593Smuzhiyun pr_err("sscanf failed: %d\n", ret);
4450*4882a593Smuzhiyun return -EFAULT;
4451*4882a593Smuzhiyun }
4452*4882a593Smuzhiyun
4453*4882a593Smuzhiyun if (op == 'w') {
4454*4882a593Smuzhiyun pr_info("Write reg: 0x%04x with val: 0x%08x\n", reg, val);
4455*4882a593Smuzhiyun regmap_write(rk3308->regmap, reg, val);
4456*4882a593Smuzhiyun regcache_cache_only(rk3308->regmap, false);
4457*4882a593Smuzhiyun regcache_sync(rk3308->regmap);
4458*4882a593Smuzhiyun pr_info("Read back reg: 0x%04x with val: 0x%08x\n", reg, val);
4459*4882a593Smuzhiyun } else if (op == 'r') {
4460*4882a593Smuzhiyun regmap_read(rk3308->regmap, reg, &val);
4461*4882a593Smuzhiyun pr_info("Read reg: 0x%04x with val: 0x%08x\n", reg, val);
4462*4882a593Smuzhiyun } else {
4463*4882a593Smuzhiyun pr_err("This is an invalid operation: %c\n", op);
4464*4882a593Smuzhiyun }
4465*4882a593Smuzhiyun
4466*4882a593Smuzhiyun return count;
4467*4882a593Smuzhiyun }
4468*4882a593Smuzhiyun
rk3308_codec_debugfs_open(struct inode * inode,struct file * file)4469*4882a593Smuzhiyun static int rk3308_codec_debugfs_open(struct inode *inode, struct file *file)
4470*4882a593Smuzhiyun {
4471*4882a593Smuzhiyun return single_open(file,
4472*4882a593Smuzhiyun rk3308_codec_debugfs_reg_show, inode->i_private);
4473*4882a593Smuzhiyun }
4474*4882a593Smuzhiyun
4475*4882a593Smuzhiyun static const struct file_operations rk3308_codec_reg_debugfs_fops = {
4476*4882a593Smuzhiyun .owner = THIS_MODULE,
4477*4882a593Smuzhiyun .open = rk3308_codec_debugfs_open,
4478*4882a593Smuzhiyun .read = seq_read,
4479*4882a593Smuzhiyun .write = rk3308_codec_debugfs_reg_operate,
4480*4882a593Smuzhiyun .llseek = seq_lseek,
4481*4882a593Smuzhiyun .release = single_release,
4482*4882a593Smuzhiyun };
4483*4882a593Smuzhiyun #endif /* CONFIG_DEBUG_FS */
4484*4882a593Smuzhiyun
rk3308_codec_get_version(struct rk3308_codec_priv * rk3308)4485*4882a593Smuzhiyun static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308)
4486*4882a593Smuzhiyun {
4487*4882a593Smuzhiyun unsigned int chip_id;
4488*4882a593Smuzhiyun
4489*4882a593Smuzhiyun regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id);
4490*4882a593Smuzhiyun switch (chip_id) {
4491*4882a593Smuzhiyun case 3306:
4492*4882a593Smuzhiyun rk3308->codec_ver = ACODEC_VERSION_A;
4493*4882a593Smuzhiyun break;
4494*4882a593Smuzhiyun case 0x3308:
4495*4882a593Smuzhiyun rk3308->codec_ver = ACODEC_VERSION_B;
4496*4882a593Smuzhiyun break;
4497*4882a593Smuzhiyun case 0x3308c:
4498*4882a593Smuzhiyun rk3308->codec_ver = ACODEC_VERSION_C;
4499*4882a593Smuzhiyun break;
4500*4882a593Smuzhiyun default:
4501*4882a593Smuzhiyun pr_err("Unknown chip_id: %d / 0x%x\n", chip_id, chip_id);
4502*4882a593Smuzhiyun return -EFAULT;
4503*4882a593Smuzhiyun }
4504*4882a593Smuzhiyun
4505*4882a593Smuzhiyun pr_info("The acodec version is: %x\n", rk3308->codec_ver);
4506*4882a593Smuzhiyun return 0;
4507*4882a593Smuzhiyun }
4508*4882a593Smuzhiyun
rk3308_platform_probe(struct platform_device * pdev)4509*4882a593Smuzhiyun static int rk3308_platform_probe(struct platform_device *pdev)
4510*4882a593Smuzhiyun {
4511*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
4512*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308;
4513*4882a593Smuzhiyun struct resource *res;
4514*4882a593Smuzhiyun void __iomem *base;
4515*4882a593Smuzhiyun int ret;
4516*4882a593Smuzhiyun
4517*4882a593Smuzhiyun rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL);
4518*4882a593Smuzhiyun if (!rk3308)
4519*4882a593Smuzhiyun return -ENOMEM;
4520*4882a593Smuzhiyun
4521*4882a593Smuzhiyun rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
4522*4882a593Smuzhiyun if (IS_ERR(rk3308->grf)) {
4523*4882a593Smuzhiyun dev_err(&pdev->dev,
4524*4882a593Smuzhiyun "Missing 'rockchip,grf' property\n");
4525*4882a593Smuzhiyun return PTR_ERR(rk3308->grf);
4526*4882a593Smuzhiyun }
4527*4882a593Smuzhiyun
4528*4882a593Smuzhiyun ret = rk3308_codec_get_version(rk3308);
4529*4882a593Smuzhiyun if (ret < 0)
4530*4882a593Smuzhiyun return dev_err_probe(&pdev->dev, ret, "Failed to get acodec version\n");
4531*4882a593Smuzhiyun
4532*4882a593Smuzhiyun ret = rk3308_codec_sysfs_init(pdev, rk3308);
4533*4882a593Smuzhiyun if (ret < 0) {
4534*4882a593Smuzhiyun dev_err(&pdev->dev, "Sysfs init failed\n");
4535*4882a593Smuzhiyun return ret;
4536*4882a593Smuzhiyun }
4537*4882a593Smuzhiyun
4538*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
4539*4882a593Smuzhiyun rk3308->dbg_codec = debugfs_create_dir(CODEC_DRV_NAME, NULL);
4540*4882a593Smuzhiyun if (IS_ERR(rk3308->dbg_codec))
4541*4882a593Smuzhiyun dev_err(&pdev->dev,
4542*4882a593Smuzhiyun "Failed to create debugfs dir for rk3308!\n");
4543*4882a593Smuzhiyun else
4544*4882a593Smuzhiyun debugfs_create_file("reg", 0644, rk3308->dbg_codec,
4545*4882a593Smuzhiyun rk3308, &rk3308_codec_reg_debugfs_fops);
4546*4882a593Smuzhiyun #endif
4547*4882a593Smuzhiyun rk3308->plat_dev = &pdev->dev;
4548*4882a593Smuzhiyun
4549*4882a593Smuzhiyun rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset");
4550*4882a593Smuzhiyun if (IS_ERR(rk3308->reset)) {
4551*4882a593Smuzhiyun ret = PTR_ERR(rk3308->reset);
4552*4882a593Smuzhiyun if (ret != -ENOENT)
4553*4882a593Smuzhiyun goto out_sysfs;
4554*4882a593Smuzhiyun
4555*4882a593Smuzhiyun dev_dbg(&pdev->dev, "No reset control found\n");
4556*4882a593Smuzhiyun rk3308->reset = NULL;
4557*4882a593Smuzhiyun }
4558*4882a593Smuzhiyun
4559*4882a593Smuzhiyun rk3308->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-ctl",
4560*4882a593Smuzhiyun GPIOD_OUT_LOW);
4561*4882a593Smuzhiyun if (!rk3308->hp_ctl_gpio) {
4562*4882a593Smuzhiyun dev_info(&pdev->dev, "Don't need hp-ctl gpio\n");
4563*4882a593Smuzhiyun } else if (IS_ERR(rk3308->hp_ctl_gpio)) {
4564*4882a593Smuzhiyun ret = PTR_ERR(rk3308->hp_ctl_gpio);
4565*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to claim gpio hp-ctl\n");
4566*4882a593Smuzhiyun goto out_sysfs;
4567*4882a593Smuzhiyun }
4568*4882a593Smuzhiyun
4569*4882a593Smuzhiyun rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl",
4570*4882a593Smuzhiyun GPIOD_OUT_LOW);
4571*4882a593Smuzhiyun
4572*4882a593Smuzhiyun if (!rk3308->spk_ctl_gpio) {
4573*4882a593Smuzhiyun dev_info(&pdev->dev, "Don't need spk-ctl gpio\n");
4574*4882a593Smuzhiyun } else if (IS_ERR(rk3308->spk_ctl_gpio)) {
4575*4882a593Smuzhiyun ret = PTR_ERR(rk3308->spk_ctl_gpio);
4576*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to claim gpio spk-ctl\n");
4577*4882a593Smuzhiyun goto out_sysfs;
4578*4882a593Smuzhiyun }
4579*4882a593Smuzhiyun
4580*4882a593Smuzhiyun rk3308->pa_drv_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-drv",
4581*4882a593Smuzhiyun GPIOD_OUT_LOW);
4582*4882a593Smuzhiyun
4583*4882a593Smuzhiyun if (!rk3308->pa_drv_gpio) {
4584*4882a593Smuzhiyun dev_info(&pdev->dev, "Don't need pa-drv gpio\n");
4585*4882a593Smuzhiyun } else if (IS_ERR(rk3308->pa_drv_gpio)) {
4586*4882a593Smuzhiyun ret = PTR_ERR(rk3308->pa_drv_gpio);
4587*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to claim gpio pa-drv\n");
4588*4882a593Smuzhiyun goto out_sysfs;
4589*4882a593Smuzhiyun }
4590*4882a593Smuzhiyun
4591*4882a593Smuzhiyun if (rk3308->pa_drv_gpio) {
4592*4882a593Smuzhiyun rk3308->delay_pa_drv_ms = PA_DRV_MS;
4593*4882a593Smuzhiyun ret = of_property_read_u32(np, "rockchip,delay-pa-drv-ms",
4594*4882a593Smuzhiyun &rk3308->delay_pa_drv_ms);
4595*4882a593Smuzhiyun }
4596*4882a593Smuzhiyun
4597*4882a593Smuzhiyun #if DEBUG_POP_ALWAYS
4598*4882a593Smuzhiyun dev_info(&pdev->dev, "Enable all ctl gpios always for debugging pop\n");
4599*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 1);
4600*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 1);
4601*4882a593Smuzhiyun #else
4602*4882a593Smuzhiyun dev_info(&pdev->dev, "De-pop as much as possible\n");
4603*4882a593Smuzhiyun rk3308_headphone_ctl(rk3308, 0);
4604*4882a593Smuzhiyun rk3308_speaker_ctl(rk3308, 0);
4605*4882a593Smuzhiyun #endif
4606*4882a593Smuzhiyun
4607*4882a593Smuzhiyun rk3308->pclk = devm_clk_get(&pdev->dev, "acodec");
4608*4882a593Smuzhiyun if (IS_ERR(rk3308->pclk)) {
4609*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get acodec pclk\n");
4610*4882a593Smuzhiyun ret = PTR_ERR(rk3308->pclk);
4611*4882a593Smuzhiyun goto out_sysfs;
4612*4882a593Smuzhiyun }
4613*4882a593Smuzhiyun
4614*4882a593Smuzhiyun rk3308->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx");
4615*4882a593Smuzhiyun if (IS_ERR(rk3308->mclk_rx)) {
4616*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get acodec mclk_rx\n");
4617*4882a593Smuzhiyun ret = PTR_ERR(rk3308->mclk_rx);
4618*4882a593Smuzhiyun goto out_sysfs;
4619*4882a593Smuzhiyun }
4620*4882a593Smuzhiyun
4621*4882a593Smuzhiyun rk3308->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx");
4622*4882a593Smuzhiyun if (IS_ERR(rk3308->mclk_tx)) {
4623*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get acodec mclk_tx\n");
4624*4882a593Smuzhiyun ret = PTR_ERR(rk3308->mclk_tx);
4625*4882a593Smuzhiyun goto out_sysfs;
4626*4882a593Smuzhiyun }
4627*4882a593Smuzhiyun
4628*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->pclk);
4629*4882a593Smuzhiyun if (ret < 0) {
4630*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret);
4631*4882a593Smuzhiyun goto out_sysfs;
4632*4882a593Smuzhiyun }
4633*4882a593Smuzhiyun
4634*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_rx);
4635*4882a593Smuzhiyun if (ret < 0) {
4636*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to enable i2s mclk_rx: %d\n", ret);
4637*4882a593Smuzhiyun goto out_pclk;
4638*4882a593Smuzhiyun }
4639*4882a593Smuzhiyun
4640*4882a593Smuzhiyun ret = clk_prepare_enable(rk3308->mclk_tx);
4641*4882a593Smuzhiyun if (ret < 0) {
4642*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to enable i2s mclk_tx: %d\n", ret);
4643*4882a593Smuzhiyun goto out_mclk_rx;
4644*4882a593Smuzhiyun }
4645*4882a593Smuzhiyun
4646*4882a593Smuzhiyun rk3308_codec_check_micbias(rk3308, np);
4647*4882a593Smuzhiyun
4648*4882a593Smuzhiyun rk3308->enable_all_adcs =
4649*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,enable-all-adcs");
4650*4882a593Smuzhiyun
4651*4882a593Smuzhiyun rk3308->hp_jack_reversed =
4652*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,hp-jack-reversed");
4653*4882a593Smuzhiyun
4654*4882a593Smuzhiyun rk3308->no_deep_low_power =
4655*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,no-deep-low-power");
4656*4882a593Smuzhiyun
4657*4882a593Smuzhiyun rk3308->no_hp_det =
4658*4882a593Smuzhiyun of_property_read_bool(np, "rockchip,no-hp-det");
4659*4882a593Smuzhiyun
4660*4882a593Smuzhiyun rk3308->delay_loopback_handle_ms = LOOPBACK_HANDLE_MS;
4661*4882a593Smuzhiyun ret = of_property_read_u32(np, "rockchip,delay-loopback-handle-ms",
4662*4882a593Smuzhiyun &rk3308->delay_loopback_handle_ms);
4663*4882a593Smuzhiyun
4664*4882a593Smuzhiyun rk3308->delay_start_play_ms = 0;
4665*4882a593Smuzhiyun ret = of_property_read_u32(np, "rockchip,delay-start-play-ms",
4666*4882a593Smuzhiyun &rk3308->delay_start_play_ms);
4667*4882a593Smuzhiyun
4668*4882a593Smuzhiyun rk3308->loopback_grp = NOT_USED;
4669*4882a593Smuzhiyun ret = of_property_read_u32(np, "rockchip,loopback-grp",
4670*4882a593Smuzhiyun &rk3308->loopback_grp);
4671*4882a593Smuzhiyun /*
4672*4882a593Smuzhiyun * If there is no loopback on some board, the -EINVAL indicates that
4673*4882a593Smuzhiyun * we don't need add the node, and it is not an error.
4674*4882a593Smuzhiyun */
4675*4882a593Smuzhiyun if (ret < 0 && ret != -EINVAL) {
4676*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to read loopback property: %d\n",
4677*4882a593Smuzhiyun ret);
4678*4882a593Smuzhiyun goto failed;
4679*4882a593Smuzhiyun }
4680*4882a593Smuzhiyun
4681*4882a593Smuzhiyun ret = rk3308_codec_adc_grps_route(rk3308, np);
4682*4882a593Smuzhiyun if (ret < 0) {
4683*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to route ADC groups: %d\n",
4684*4882a593Smuzhiyun ret);
4685*4882a593Smuzhiyun goto failed;
4686*4882a593Smuzhiyun }
4687*4882a593Smuzhiyun
4688*4882a593Smuzhiyun ret = rk3308_codec_setup_en_always_adcs(rk3308, np);
4689*4882a593Smuzhiyun if (ret < 0) {
4690*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to setup enabled always ADCs: %d\n",
4691*4882a593Smuzhiyun ret);
4692*4882a593Smuzhiyun goto failed;
4693*4882a593Smuzhiyun }
4694*4882a593Smuzhiyun
4695*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4696*4882a593Smuzhiyun base = devm_ioremap_resource(&pdev->dev, res);
4697*4882a593Smuzhiyun if (IS_ERR(base)) {
4698*4882a593Smuzhiyun ret = PTR_ERR(base);
4699*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to ioremap resource\n");
4700*4882a593Smuzhiyun goto failed;
4701*4882a593Smuzhiyun }
4702*4882a593Smuzhiyun
4703*4882a593Smuzhiyun rk3308->regmap = devm_regmap_init_mmio(&pdev->dev, base,
4704*4882a593Smuzhiyun &rk3308_codec_regmap_config);
4705*4882a593Smuzhiyun if (IS_ERR(rk3308->regmap)) {
4706*4882a593Smuzhiyun ret = PTR_ERR(rk3308->regmap);
4707*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to regmap mmio\n");
4708*4882a593Smuzhiyun goto failed;
4709*4882a593Smuzhiyun }
4710*4882a593Smuzhiyun
4711*4882a593Smuzhiyun if (!rk3308->no_hp_det) {
4712*4882a593Smuzhiyun int index = 0;
4713*4882a593Smuzhiyun
4714*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B)
4715*4882a593Smuzhiyun index = 1;
4716*4882a593Smuzhiyun
4717*4882a593Smuzhiyun rk3308->irq = platform_get_irq(pdev, index);
4718*4882a593Smuzhiyun if (rk3308->irq < 0) {
4719*4882a593Smuzhiyun dev_err(&pdev->dev, "Can not get codec irq\n");
4720*4882a593Smuzhiyun goto failed;
4721*4882a593Smuzhiyun }
4722*4882a593Smuzhiyun
4723*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work);
4724*4882a593Smuzhiyun
4725*4882a593Smuzhiyun ret = devm_request_irq(&pdev->dev, rk3308->irq,
4726*4882a593Smuzhiyun rk3308_codec_hpdet_isr,
4727*4882a593Smuzhiyun 0,
4728*4882a593Smuzhiyun "acodec-hpdet",
4729*4882a593Smuzhiyun rk3308);
4730*4882a593Smuzhiyun if (ret < 0) {
4731*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret);
4732*4882a593Smuzhiyun goto failed;
4733*4882a593Smuzhiyun }
4734*4882a593Smuzhiyun
4735*4882a593Smuzhiyun if (rk3308->codec_ver >= ACODEC_VERSION_B) {
4736*4882a593Smuzhiyun rk3308->detect_grf =
4737*4882a593Smuzhiyun syscon_regmap_lookup_by_phandle(np, "rockchip,detect-grf");
4738*4882a593Smuzhiyun if (IS_ERR(rk3308->detect_grf)) {
4739*4882a593Smuzhiyun dev_err(&pdev->dev,
4740*4882a593Smuzhiyun "Missing 'rockchip,detect-grf' property\n");
4741*4882a593Smuzhiyun ret = PTR_ERR(rk3308->detect_grf);
4742*4882a593Smuzhiyun goto failed;
4743*4882a593Smuzhiyun }
4744*4882a593Smuzhiyun
4745*4882a593Smuzhiyun /* Configure filter count and enable hpdet irq. */
4746*4882a593Smuzhiyun regmap_write(rk3308->detect_grf,
4747*4882a593Smuzhiyun DETECT_GRF_ACODEC_HPDET_COUNTER,
4748*4882a593Smuzhiyun DEFAULT_HPDET_COUNT);
4749*4882a593Smuzhiyun regmap_write(rk3308->detect_grf,
4750*4882a593Smuzhiyun DETECT_GRF_ACODEC_HPDET_CON,
4751*4882a593Smuzhiyun (HPDET_BOTH_NEG_POS << 16) |
4752*4882a593Smuzhiyun HPDET_BOTH_NEG_POS);
4753*4882a593Smuzhiyun }
4754*4882a593Smuzhiyun }
4755*4882a593Smuzhiyun
4756*4882a593Smuzhiyun if (rk3308->codec_ver == ACODEC_VERSION_A)
4757*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk3308->loopback_work,
4758*4882a593Smuzhiyun rk3308_codec_loopback_work);
4759*4882a593Smuzhiyun
4760*4882a593Smuzhiyun rk3308->adc_grp0_using_linein = ADC_GRP0_MICIN;
4761*4882a593Smuzhiyun rk3308->dac_output = DAC_LINEOUT;
4762*4882a593Smuzhiyun rk3308->adc_zerocross = 0;
4763*4882a593Smuzhiyun rk3308->pm_state = PM_NORMAL;
4764*4882a593Smuzhiyun
4765*4882a593Smuzhiyun platform_set_drvdata(pdev, rk3308);
4766*4882a593Smuzhiyun
4767*4882a593Smuzhiyun ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3308,
4768*4882a593Smuzhiyun rk3308_dai, ARRAY_SIZE(rk3308_dai));
4769*4882a593Smuzhiyun if (ret < 0) {
4770*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
4771*4882a593Smuzhiyun goto failed;
4772*4882a593Smuzhiyun }
4773*4882a593Smuzhiyun
4774*4882a593Smuzhiyun return ret;
4775*4882a593Smuzhiyun
4776*4882a593Smuzhiyun failed:
4777*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_tx);
4778*4882a593Smuzhiyun out_mclk_rx:
4779*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_rx);
4780*4882a593Smuzhiyun out_pclk:
4781*4882a593Smuzhiyun clk_disable_unprepare(rk3308->pclk);
4782*4882a593Smuzhiyun out_sysfs:
4783*4882a593Smuzhiyun rk3308_codec_sysfs_exit(rk3308);
4784*4882a593Smuzhiyun
4785*4882a593Smuzhiyun return ret;
4786*4882a593Smuzhiyun }
4787*4882a593Smuzhiyun
rk3308_platform_remove(struct platform_device * pdev)4788*4882a593Smuzhiyun static int rk3308_platform_remove(struct platform_device *pdev)
4789*4882a593Smuzhiyun {
4790*4882a593Smuzhiyun struct rk3308_codec_priv *rk3308 =
4791*4882a593Smuzhiyun (struct rk3308_codec_priv *)platform_get_drvdata(pdev);
4792*4882a593Smuzhiyun
4793*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_rx);
4794*4882a593Smuzhiyun clk_disable_unprepare(rk3308->mclk_tx);
4795*4882a593Smuzhiyun clk_disable_unprepare(rk3308->pclk);
4796*4882a593Smuzhiyun device_unregister(&rk3308->dev);
4797*4882a593Smuzhiyun
4798*4882a593Smuzhiyun return 0;
4799*4882a593Smuzhiyun }
4800*4882a593Smuzhiyun
4801*4882a593Smuzhiyun static const struct of_device_id rk3308codec_of_match[] = {
4802*4882a593Smuzhiyun { .compatible = "rockchip,rk3308-codec", },
4803*4882a593Smuzhiyun {},
4804*4882a593Smuzhiyun };
4805*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk3308codec_of_match);
4806*4882a593Smuzhiyun
4807*4882a593Smuzhiyun static struct platform_driver rk3308_codec_driver = {
4808*4882a593Smuzhiyun .driver = {
4809*4882a593Smuzhiyun .name = CODEC_DRV_NAME,
4810*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk3308codec_of_match),
4811*4882a593Smuzhiyun },
4812*4882a593Smuzhiyun .probe = rk3308_platform_probe,
4813*4882a593Smuzhiyun .remove = rk3308_platform_remove,
4814*4882a593Smuzhiyun };
4815*4882a593Smuzhiyun module_platform_driver(rk3308_codec_driver);
4816*4882a593Smuzhiyun
4817*4882a593Smuzhiyun MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
4818*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC RK3308 Codec Driver");
4819*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
4820