1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * rk312x_codec.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Driver for rockchip rk312x codec
5*4882a593Smuzhiyun * Copyright (C) 2014
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
8*4882a593Smuzhiyun * under the terms of the GNU General Public License as published by the
9*4882a593Smuzhiyun * Free Software Foundation; either version 2 of the License, or (at your
10*4882a593Smuzhiyun * option) any later version.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun #include <linux/init.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/interrupt.h>
17*4882a593Smuzhiyun #include <linux/device.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun #include <linux/clk.h>
20*4882a593Smuzhiyun #include <linux/version.h>
21*4882a593Smuzhiyun #include <linux/of.h>
22*4882a593Smuzhiyun #include <linux/of_gpio.h>
23*4882a593Smuzhiyun #include <linux/clk.h>
24*4882a593Smuzhiyun #include <linux/io.h>
25*4882a593Smuzhiyun #include <linux/rockchip/grf.h>
26*4882a593Smuzhiyun #include <linux/platform_device.h>
27*4882a593Smuzhiyun #include <linux/pm_runtime.h>
28*4882a593Smuzhiyun #include <linux/regmap.h>
29*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
30*4882a593Smuzhiyun #include <linux/slab.h>
31*4882a593Smuzhiyun #include <asm/dma.h>
32*4882a593Smuzhiyun #include <sound/core.h>
33*4882a593Smuzhiyun #include <sound/pcm.h>
34*4882a593Smuzhiyun #include <sound/pcm_params.h>
35*4882a593Smuzhiyun #include <sound/initval.h>
36*4882a593Smuzhiyun #include <sound/soc.h>
37*4882a593Smuzhiyun #include <sound/soc-dapm.h>
38*4882a593Smuzhiyun #include <sound/dmaengine_pcm.h>
39*4882a593Smuzhiyun #include <linux/io.h>
40*4882a593Smuzhiyun #include <linux/spinlock.h>
41*4882a593Smuzhiyun #include <sound/tlv.h>
42*4882a593Smuzhiyun #include <linux/extcon-provider.h>
43*4882a593Smuzhiyun #include "rk312x_codec.h"
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun static int debug = -1;
46*4882a593Smuzhiyun module_param(debug, int, S_IRUGO|S_IWUSR);
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define dbg_codec(level, fmt, arg...) \
49*4882a593Smuzhiyun do { \
50*4882a593Smuzhiyun if (debug >= level) \
51*4882a593Smuzhiyun printk(fmt , ## arg); \
52*4882a593Smuzhiyun } while (0)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define DBG(fmt, ...) dbg_codec(0, fmt, ## __VA_ARGS__)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define INVALID_GPIO -1
57*4882a593Smuzhiyun #define CODEC_SET_SPK 1
58*4882a593Smuzhiyun #define CODEC_SET_HP 2
59*4882a593Smuzhiyun #define SWITCH_SPK 1
60*4882a593Smuzhiyun #define GRF_ACODEC_CON 0x013c
61*4882a593Smuzhiyun #define GRF_SOC_STATUS0 0x014c
62*4882a593Smuzhiyun /* volume setting
63*4882a593Smuzhiyun * 0: -39dB
64*4882a593Smuzhiyun * 26: 0dB
65*4882a593Smuzhiyun * 31: 6dB
66*4882a593Smuzhiyun * Step: 1.5dB
67*4882a593Smuzhiyun */
68*4882a593Smuzhiyun #define OUT_VOLUME 25
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* capture vol set
71*4882a593Smuzhiyun * 0: -18db
72*4882a593Smuzhiyun * 12: 0db
73*4882a593Smuzhiyun * 31: 28.5db
74*4882a593Smuzhiyun * step: 1.5db
75*4882a593Smuzhiyun */
76*4882a593Smuzhiyun #define CAP_VOL 26 /*0-31 */
77*4882a593Smuzhiyun /*with capacity or not*/
78*4882a593Smuzhiyun #define WITH_CAP
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun struct rk312x_codec_priv {
81*4882a593Smuzhiyun void __iomem *regbase;
82*4882a593Smuzhiyun struct regmap *regmap;
83*4882a593Smuzhiyun struct regmap *grf;
84*4882a593Smuzhiyun struct device *dev;
85*4882a593Smuzhiyun unsigned int irq;
86*4882a593Smuzhiyun struct snd_soc_component *component;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun unsigned int stereo_sysclk;
89*4882a593Smuzhiyun unsigned int rate;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun int playback_active;
92*4882a593Smuzhiyun int capture_active;
93*4882a593Smuzhiyun struct gpio_desc *spk_ctl_gpio;
94*4882a593Smuzhiyun struct gpio_desc *hp_ctl_gpio;
95*4882a593Smuzhiyun int spk_mute_delay;
96*4882a593Smuzhiyun int hp_mute_delay;
97*4882a593Smuzhiyun int spk_hp_switch_gpio;
98*4882a593Smuzhiyun /* 1 spk; */
99*4882a593Smuzhiyun /* 0 hp; */
100*4882a593Smuzhiyun enum of_gpio_flags spk_io;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* 0 for box; */
103*4882a593Smuzhiyun /* 1 default for mid; */
104*4882a593Smuzhiyun int rk312x_for_mid;
105*4882a593Smuzhiyun /* 1: for rk3128 */
106*4882a593Smuzhiyun /* 0: for rk3126 */
107*4882a593Smuzhiyun int is_rk3128;
108*4882a593Smuzhiyun int gpio_debug;
109*4882a593Smuzhiyun int codec_hp_det;
110*4882a593Smuzhiyun unsigned int spk_volume;
111*4882a593Smuzhiyun unsigned int hp_volume;
112*4882a593Smuzhiyun unsigned int capture_volume;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun long int playback_path;
115*4882a593Smuzhiyun long int capture_path;
116*4882a593Smuzhiyun long int voice_call_path;
117*4882a593Smuzhiyun struct clk *pclk;
118*4882a593Smuzhiyun struct clk *mclk;
119*4882a593Smuzhiyun struct extcon_dev *edev;
120*4882a593Smuzhiyun struct work_struct work;
121*4882a593Smuzhiyun struct delayed_work init_delayed_work;
122*4882a593Smuzhiyun struct delayed_work mute_delayed_work;
123*4882a593Smuzhiyun struct delayed_work hpdet_work;
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun static const unsigned int headset_extcon_cable[] = {
127*4882a593Smuzhiyun EXTCON_JACK_MICROPHONE,
128*4882a593Smuzhiyun EXTCON_JACK_HEADPHONE,
129*4882a593Smuzhiyun EXTCON_NONE,
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static struct rk312x_codec_priv *rk312x_priv;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun #define RK312x_CODEC_ALL 0
135*4882a593Smuzhiyun #define RK312x_CODEC_PLAYBACK 1
136*4882a593Smuzhiyun #define RK312x_CODEC_CAPTURE 2
137*4882a593Smuzhiyun #define RK312x_CODEC_INCALL 3
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun #define RK312x_CODEC_WORK_NULL 0
140*4882a593Smuzhiyun #define RK312x_CODEC_WORK_POWER_DOWN 1
141*4882a593Smuzhiyun #define RK312x_CODEC_WORK_POWER_UP 2
142*4882a593Smuzhiyun static struct workqueue_struct *rk312x_codec_workq;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun static void rk312x_codec_capture_work(struct work_struct *work);
145*4882a593Smuzhiyun static void rk312x_codec_unpop(struct work_struct *work);
146*4882a593Smuzhiyun static DECLARE_DELAYED_WORK(capture_delayed_work, rk312x_codec_capture_work);
147*4882a593Smuzhiyun static int rk312x_codec_work_capture_type = RK312x_CODEC_WORK_NULL;
148*4882a593Smuzhiyun /* static bool rk312x_for_mid = 1; */
149*4882a593Smuzhiyun static int rk312x_codec_power_up(int type);
150*4882a593Smuzhiyun static const unsigned int rk312x_reg_defaults[RK312x_PGAR_AGC_CTL5+1] = {
151*4882a593Smuzhiyun [RK312x_RESET] = 0x0003,
152*4882a593Smuzhiyun [RK312x_ADC_INT_CTL1] = 0x0050,
153*4882a593Smuzhiyun [RK312x_ADC_INT_CTL2] = 0x000e,
154*4882a593Smuzhiyun [RK312x_DAC_INT_CTL1] = 0x0050,
155*4882a593Smuzhiyun [RK312x_DAC_INT_CTL2] = 0x000e,
156*4882a593Smuzhiyun [RK312x_DAC_INT_CTL3] = 0x22,
157*4882a593Smuzhiyun [RK312x_ADC_MIC_CTL] = 0x0000,
158*4882a593Smuzhiyun [RK312x_BST_CTL] = 0x000,
159*4882a593Smuzhiyun [RK312x_ALC_MUNIN_CTL] = 0x0044,
160*4882a593Smuzhiyun [RK312x_BSTL_ALCL_CTL] = 0x000c,
161*4882a593Smuzhiyun [RK312x_ALCR_GAIN_CTL] = 0x000C,
162*4882a593Smuzhiyun [RK312x_ADC_ENABLE] = 0x0000,
163*4882a593Smuzhiyun [RK312x_DAC_CTL] = 0x0000,
164*4882a593Smuzhiyun [RK312x_DAC_ENABLE] = 0x0000,
165*4882a593Smuzhiyun [RK312x_HPMIX_CTL] = 0x0000,
166*4882a593Smuzhiyun [RK312x_HPMIX_S_SELECT] = 0x0000,
167*4882a593Smuzhiyun [RK312x_HPOUT_CTL] = 0x0000,
168*4882a593Smuzhiyun [RK312x_HPOUTL_GAIN] = 0x0000,
169*4882a593Smuzhiyun [RK312x_HPOUTR_GAIN] = 0x0000,
170*4882a593Smuzhiyun [RK312x_SELECT_CURRENT] = 0x003e,
171*4882a593Smuzhiyun [RK312x_PGAL_AGC_CTL1] = 0x0000,
172*4882a593Smuzhiyun [RK312x_PGAL_AGC_CTL2] = 0x0046,
173*4882a593Smuzhiyun [RK312x_PGAL_AGC_CTL3] = 0x0041,
174*4882a593Smuzhiyun [RK312x_PGAL_AGC_CTL4] = 0x002c,
175*4882a593Smuzhiyun [RK312x_PGAL_ASR_CTL] = 0x0000,
176*4882a593Smuzhiyun [RK312x_PGAL_AGC_MAX_H] = 0x0026,
177*4882a593Smuzhiyun [RK312x_PGAL_AGC_MAX_L] = 0x0040,
178*4882a593Smuzhiyun [RK312x_PGAL_AGC_MIN_H] = 0x0036,
179*4882a593Smuzhiyun [RK312x_PGAL_AGC_MIN_L] = 0x0020,
180*4882a593Smuzhiyun [RK312x_PGAL_AGC_CTL5] = 0x0038,
181*4882a593Smuzhiyun [RK312x_PGAR_AGC_CTL1] = 0x0000,
182*4882a593Smuzhiyun [RK312x_PGAR_AGC_CTL2] = 0x0046,
183*4882a593Smuzhiyun [RK312x_PGAR_AGC_CTL3] = 0x0041,
184*4882a593Smuzhiyun [RK312x_PGAR_AGC_CTL4] = 0x002c,
185*4882a593Smuzhiyun [RK312x_PGAR_ASR_CTL] = 0x0000,
186*4882a593Smuzhiyun [RK312x_PGAR_AGC_MAX_H] = 0x0026,
187*4882a593Smuzhiyun [RK312x_PGAR_AGC_MAX_L] = 0x0040,
188*4882a593Smuzhiyun [RK312x_PGAR_AGC_MIN_H] = 0x0036,
189*4882a593Smuzhiyun [RK312x_PGAR_AGC_MIN_L] = 0x0020,
190*4882a593Smuzhiyun [RK312x_PGAR_AGC_CTL5] = 0x0038,
191*4882a593Smuzhiyun };
192*4882a593Smuzhiyun
rk312x_volatile_register(struct device * dev,unsigned int reg)193*4882a593Smuzhiyun static bool rk312x_volatile_register(struct device *dev, unsigned int reg)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun switch (reg) {
196*4882a593Smuzhiyun case RK312x_RESET:
197*4882a593Smuzhiyun return true;
198*4882a593Smuzhiyun default:
199*4882a593Smuzhiyun return false;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
rk312x_codec_register(struct device * dev,unsigned int reg)203*4882a593Smuzhiyun static bool rk312x_codec_register(struct device *dev, unsigned int reg)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun switch (reg) {
206*4882a593Smuzhiyun case RK312x_RESET:
207*4882a593Smuzhiyun case RK312x_ADC_INT_CTL1:
208*4882a593Smuzhiyun case RK312x_ADC_INT_CTL2:
209*4882a593Smuzhiyun case RK312x_DAC_INT_CTL1:
210*4882a593Smuzhiyun case RK312x_DAC_INT_CTL2:
211*4882a593Smuzhiyun case RK312x_DAC_INT_CTL3:
212*4882a593Smuzhiyun case RK312x_ADC_MIC_CTL:
213*4882a593Smuzhiyun case RK312x_BST_CTL:
214*4882a593Smuzhiyun case RK312x_ALC_MUNIN_CTL:
215*4882a593Smuzhiyun case RK312x_BSTL_ALCL_CTL:
216*4882a593Smuzhiyun case RK312x_ALCR_GAIN_CTL:
217*4882a593Smuzhiyun case RK312x_ADC_ENABLE:
218*4882a593Smuzhiyun case RK312x_DAC_CTL:
219*4882a593Smuzhiyun case RK312x_DAC_ENABLE:
220*4882a593Smuzhiyun case RK312x_HPMIX_CTL:
221*4882a593Smuzhiyun case RK312x_HPMIX_S_SELECT:
222*4882a593Smuzhiyun case RK312x_HPOUT_CTL:
223*4882a593Smuzhiyun case RK312x_HPOUTL_GAIN:
224*4882a593Smuzhiyun case RK312x_HPOUTR_GAIN:
225*4882a593Smuzhiyun case RK312x_SELECT_CURRENT:
226*4882a593Smuzhiyun case RK312x_PGAL_AGC_CTL1:
227*4882a593Smuzhiyun case RK312x_PGAL_AGC_CTL2:
228*4882a593Smuzhiyun case RK312x_PGAL_AGC_CTL3:
229*4882a593Smuzhiyun case RK312x_PGAL_AGC_CTL4:
230*4882a593Smuzhiyun case RK312x_PGAL_ASR_CTL:
231*4882a593Smuzhiyun case RK312x_PGAL_AGC_MAX_H:
232*4882a593Smuzhiyun case RK312x_PGAL_AGC_MAX_L:
233*4882a593Smuzhiyun case RK312x_PGAL_AGC_MIN_H:
234*4882a593Smuzhiyun case RK312x_PGAL_AGC_MIN_L:
235*4882a593Smuzhiyun case RK312x_PGAL_AGC_CTL5:
236*4882a593Smuzhiyun case RK312x_PGAR_AGC_CTL1:
237*4882a593Smuzhiyun case RK312x_PGAR_AGC_CTL2:
238*4882a593Smuzhiyun case RK312x_PGAR_AGC_CTL3:
239*4882a593Smuzhiyun case RK312x_PGAR_AGC_CTL4:
240*4882a593Smuzhiyun case RK312x_PGAR_ASR_CTL:
241*4882a593Smuzhiyun case RK312x_PGAR_AGC_MAX_H:
242*4882a593Smuzhiyun case RK312x_PGAR_AGC_MAX_L:
243*4882a593Smuzhiyun case RK312x_PGAR_AGC_MIN_H:
244*4882a593Smuzhiyun case RK312x_PGAR_AGC_MIN_L:
245*4882a593Smuzhiyun case RK312x_PGAR_AGC_CTL5:
246*4882a593Smuzhiyun case RK312x_ALC_CTL:
247*4882a593Smuzhiyun return true;
248*4882a593Smuzhiyun default:
249*4882a593Smuzhiyun return false;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
rk312x_codec_ctl_gpio(int gpio,int level)253*4882a593Smuzhiyun static int rk312x_codec_ctl_gpio(int gpio, int level)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (!rk312x_priv) {
257*4882a593Smuzhiyun DBG("%s : rk312x is NULL\n", __func__);
258*4882a593Smuzhiyun return -EINVAL;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if ((gpio & CODEC_SET_SPK) && rk312x_priv &&
262*4882a593Smuzhiyun rk312x_priv->spk_ctl_gpio) {
263*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->spk_ctl_gpio, level);
264*4882a593Smuzhiyun DBG(KERN_INFO"%s set spk clt %d\n", __func__, level);
265*4882a593Smuzhiyun msleep(rk312x_priv->spk_mute_delay);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if ((gpio & CODEC_SET_HP) && rk312x_priv &&
269*4882a593Smuzhiyun rk312x_priv->hp_ctl_gpio) {
270*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->hp_ctl_gpio, level);
271*4882a593Smuzhiyun DBG(KERN_INFO"%s set hp clt %d\n", __func__, level);
272*4882a593Smuzhiyun msleep(rk312x_priv->hp_mute_delay);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun #if 0
279*4882a593Smuzhiyun static int switch_to_spk(int enable)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun if (!rk312x_priv) {
282*4882a593Smuzhiyun DBG(KERN_ERR"%s : rk312x is NULL\n", __func__);
283*4882a593Smuzhiyun return -EINVAL;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun if (enable) {
286*4882a593Smuzhiyun if (rk312x_priv->spk_hp_switch_gpio != INVALID_GPIO) {
287*4882a593Smuzhiyun gpio_set_value(rk312x_priv->spk_hp_switch_gpio, rk312x_priv->spk_io);
288*4882a593Smuzhiyun DBG(KERN_INFO"%s switch to spk\n", __func__);
289*4882a593Smuzhiyun msleep(rk312x_priv->spk_mute_delay);
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun } else {
292*4882a593Smuzhiyun if (rk312x_priv->spk_hp_switch_gpio != INVALID_GPIO) {
293*4882a593Smuzhiyun gpio_set_value(rk312x_priv->spk_hp_switch_gpio, !rk312x_priv->spk_io);
294*4882a593Smuzhiyun DBG(KERN_INFO"%s switch to hp\n", __func__);
295*4882a593Smuzhiyun msleep(rk312x_priv->hp_mute_delay);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun return 0;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun #endif
301*4882a593Smuzhiyun
rk312x_reset(struct snd_soc_component * component)302*4882a593Smuzhiyun static int rk312x_reset(struct snd_soc_component *component)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun DBG("%s\n", __func__);
305*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_RESET, 0x00);
306*4882a593Smuzhiyun mdelay(10);
307*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_RESET, 0x43);
308*4882a593Smuzhiyun mdelay(10);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun return 0;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -3900, 150, 0);
314*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1800, 150, 0);
315*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(bst_vol_tlv, 0, 2000, 0);
316*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(pga_agc_max_vol_tlv, -1350, 600, 0);
317*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(pga_agc_min_vol_tlv, -1800, 600, 0);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun static const char *const rk312x_input_mode[] = {
320*4882a593Smuzhiyun "Differential", "Single-Ended"};
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static const char *const rk312x_micbias_ratio[] = {
323*4882a593Smuzhiyun "1.0 Vref", "1.1 Vref",
324*4882a593Smuzhiyun "1.2 Vref", "1.3 Vref",
325*4882a593Smuzhiyun "1.4 Vref", "1.5 Vref",
326*4882a593Smuzhiyun "1.6 Vref", "1.7 Vref",};
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun static const char *const rk312x_dis_en_sel[] = {"Disable", "Enable"};
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun static const char *const rk312x_pga_agc_way[] = {"Normal", "Jack"};
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun static const char *const rk312x_agc_backup_way[] = {
333*4882a593Smuzhiyun "Normal", "Jack1", "Jack2", "Jack3"};
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun static const char *const rk312x_pga_agc_hold_time[] = {
336*4882a593Smuzhiyun "0ms", "2ms", "4ms", "8ms",
337*4882a593Smuzhiyun "16ms", "32ms", "64ms",
338*4882a593Smuzhiyun "128ms", "256ms", "512ms", "1s"};
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun static const char *const rk312x_pga_agc_ramp_up_time[] = {
341*4882a593Smuzhiyun "Normal:500us Jack:125us",
342*4882a593Smuzhiyun "Normal:1ms Jack:250us",
343*4882a593Smuzhiyun "Normal:2ms Jack:500us",
344*4882a593Smuzhiyun "Normal:4ms Jack:1ms",
345*4882a593Smuzhiyun "Normal:8ms Jack:2ms",
346*4882a593Smuzhiyun "Normal:16ms Jack:4ms",
347*4882a593Smuzhiyun "Normal:32ms Jack:8ms",
348*4882a593Smuzhiyun "Normal:64ms Jack:16ms",
349*4882a593Smuzhiyun "Normal:128ms Jack:32ms",
350*4882a593Smuzhiyun "Normal:256ms Jack:64ms",
351*4882a593Smuzhiyun "Normal:512ms Jack:128ms"};
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun static const char *const rk312x_pga_agc_ramp_down_time[] = {
354*4882a593Smuzhiyun "Normal:125us Jack:32us",
355*4882a593Smuzhiyun "Normal:250us Jack:64us",
356*4882a593Smuzhiyun "Normal:500us Jack:125us",
357*4882a593Smuzhiyun "Normal:1ms Jack:250us",
358*4882a593Smuzhiyun "Normal:2ms Jack:500us",
359*4882a593Smuzhiyun "Normal:4ms Jack:1ms",
360*4882a593Smuzhiyun "Normal:8ms Jack:2ms",
361*4882a593Smuzhiyun "Normal:16ms Jack:4ms",
362*4882a593Smuzhiyun "Normal:32ms Jack:8ms",
363*4882a593Smuzhiyun "Normal:64ms Jack:16ms",
364*4882a593Smuzhiyun "Normal:128ms Jack:32ms"};
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun static const char *const rk312x_pga_agc_mode[] = {"Normal", "Limiter"};
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun static const char *const rk312x_pga_agc_recovery_mode[] = {
369*4882a593Smuzhiyun "Right Now", "After AGC to Limiter"};
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun static const char *const rk312x_pga_agc_noise_gate_threhold[] = {
372*4882a593Smuzhiyun "-39dB", "-45dB", "-51dB",
373*4882a593Smuzhiyun "-57dB", "-63dB", "-69dB", "-75dB", "-81dB"};
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun static const char *const rk312x_pga_agc_update_gain[] = {
376*4882a593Smuzhiyun "Right Now", "After 1st Zero Cross"};
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun static const char *const rk312x_pga_agc_approximate_sample_rate[] = {
379*4882a593Smuzhiyun "96KHZ", "48KHz", "441KHZ", "32KHz",
380*4882a593Smuzhiyun "24KHz", "16KHz", "12KHz", "8KHz"};
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun static const struct soc_enum rk312x_bst_enum[] = {
383*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_BSTL_ALCL_CTL,
384*4882a593Smuzhiyun RK312x_BSTL_MODE_SFT, 2,
385*4882a593Smuzhiyun rk312x_input_mode),
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun static const struct soc_enum rk312x_micbias_enum[] = {
390*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_ADC_MIC_CTL,
391*4882a593Smuzhiyun RK312x_MICBIAS_VOL_SHT, 8,
392*4882a593Smuzhiyun rk312x_micbias_ratio),
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun static const struct soc_enum rk312x_agcl_enum[] = {
396*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL1,
397*4882a593Smuzhiyun RK312x_PGA_AGC_BK_WAY_SFT, 4,
398*4882a593Smuzhiyun rk312x_agc_backup_way),/*0*/
399*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL1,
400*4882a593Smuzhiyun RK312x_PGA_AGC_WAY_SFT, 2,
401*4882a593Smuzhiyun rk312x_pga_agc_way),/*1*/
402*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL1,
403*4882a593Smuzhiyun RK312x_PGA_AGC_HOLD_T_SFT, 11,
404*4882a593Smuzhiyun rk312x_pga_agc_hold_time),/*2*/
405*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL2,
406*4882a593Smuzhiyun RK312x_PGA_AGC_GRU_T_SFT, 11,
407*4882a593Smuzhiyun rk312x_pga_agc_ramp_up_time),/*3*/
408*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL2,
409*4882a593Smuzhiyun RK312x_PGA_AGC_GRD_T_SFT, 11,
410*4882a593Smuzhiyun rk312x_pga_agc_ramp_down_time),/*4*/
411*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
412*4882a593Smuzhiyun RK312x_PGA_AGC_MODE_SFT, 2,
413*4882a593Smuzhiyun rk312x_pga_agc_mode),/*5*/
414*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
415*4882a593Smuzhiyun RK312x_PGA_AGC_ZO_SFT, 2,
416*4882a593Smuzhiyun rk312x_dis_en_sel),/*6*/
417*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
418*4882a593Smuzhiyun RK312x_PGA_AGC_REC_MODE_SFT, 2,
419*4882a593Smuzhiyun rk312x_pga_agc_recovery_mode),/*7*/
420*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
421*4882a593Smuzhiyun RK312x_PGA_AGC_FAST_D_SFT, 2,
422*4882a593Smuzhiyun rk312x_dis_en_sel),/*8*/
423*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
424*4882a593Smuzhiyun RK312x_PGA_AGC_NG_SFT, 2,
425*4882a593Smuzhiyun rk312x_dis_en_sel),/*9*/
426*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL3,
427*4882a593Smuzhiyun RK312x_PGA_AGC_NG_THR_SFT, 8,
428*4882a593Smuzhiyun rk312x_pga_agc_noise_gate_threhold),/*10*/
429*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL4,
430*4882a593Smuzhiyun RK312x_PGA_AGC_ZO_MODE_SFT, 2,
431*4882a593Smuzhiyun rk312x_pga_agc_update_gain),/*11*/
432*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_ASR_CTL,
433*4882a593Smuzhiyun RK312x_PGA_SLOW_CLK_SFT, 2,
434*4882a593Smuzhiyun rk312x_dis_en_sel),/*12*/
435*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_ASR_CTL,
436*4882a593Smuzhiyun RK312x_PGA_ASR_SFT, 8,
437*4882a593Smuzhiyun rk312x_pga_agc_approximate_sample_rate),/*13*/
438*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAL_AGC_CTL5,
439*4882a593Smuzhiyun RK312x_PGA_AGC_SFT, 2,
440*4882a593Smuzhiyun rk312x_dis_en_sel),/*14*/
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun static const struct soc_enum rk312x_agcr_enum[] = {
444*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL1,
445*4882a593Smuzhiyun RK312x_PGA_AGC_BK_WAY_SFT, 4,
446*4882a593Smuzhiyun rk312x_agc_backup_way),/*0*/
447*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL1,
448*4882a593Smuzhiyun RK312x_PGA_AGC_WAY_SFT, 2,
449*4882a593Smuzhiyun rk312x_pga_agc_way),/*1*/
450*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL1,
451*4882a593Smuzhiyun RK312x_PGA_AGC_HOLD_T_SFT, 11,
452*4882a593Smuzhiyun rk312x_pga_agc_hold_time),/*2*/
453*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL2,
454*4882a593Smuzhiyun RK312x_PGA_AGC_GRU_T_SFT, 11,
455*4882a593Smuzhiyun rk312x_pga_agc_ramp_up_time),/*3*/
456*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL2,
457*4882a593Smuzhiyun RK312x_PGA_AGC_GRD_T_SFT, 11,
458*4882a593Smuzhiyun rk312x_pga_agc_ramp_down_time),/*4*/
459*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
460*4882a593Smuzhiyun RK312x_PGA_AGC_MODE_SFT, 2,
461*4882a593Smuzhiyun rk312x_pga_agc_mode),/*5*/
462*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
463*4882a593Smuzhiyun RK312x_PGA_AGC_ZO_SFT, 2,
464*4882a593Smuzhiyun rk312x_dis_en_sel),/*6*/
465*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
466*4882a593Smuzhiyun RK312x_PGA_AGC_REC_MODE_SFT, 2,
467*4882a593Smuzhiyun rk312x_pga_agc_recovery_mode),/*7*/
468*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
469*4882a593Smuzhiyun RK312x_PGA_AGC_FAST_D_SFT, 2,
470*4882a593Smuzhiyun rk312x_dis_en_sel),/*8*/
471*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
472*4882a593Smuzhiyun RK312x_PGA_AGC_NG_SFT, 2, rk312x_dis_en_sel),/*9*/
473*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL3,
474*4882a593Smuzhiyun RK312x_PGA_AGC_NG_THR_SFT, 8,
475*4882a593Smuzhiyun rk312x_pga_agc_noise_gate_threhold),/*10*/
476*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL4,
477*4882a593Smuzhiyun RK312x_PGA_AGC_ZO_MODE_SFT, 2,
478*4882a593Smuzhiyun rk312x_pga_agc_update_gain),/*11*/
479*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_ASR_CTL,
480*4882a593Smuzhiyun RK312x_PGA_SLOW_CLK_SFT, 2,
481*4882a593Smuzhiyun rk312x_dis_en_sel),/*12*/
482*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_ASR_CTL,
483*4882a593Smuzhiyun RK312x_PGA_ASR_SFT, 8,
484*4882a593Smuzhiyun rk312x_pga_agc_approximate_sample_rate),/*13*/
485*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_PGAR_AGC_CTL5,
486*4882a593Smuzhiyun RK312x_PGA_AGC_SFT, 2,
487*4882a593Smuzhiyun rk312x_dis_en_sel),/*14*/
488*4882a593Smuzhiyun };
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun static const struct snd_kcontrol_new rk312x_snd_controls[] = {
491*4882a593Smuzhiyun /* Add for set voice volume */
492*4882a593Smuzhiyun SOC_DOUBLE_R_TLV("Speaker Playback Volume", RK312x_HPOUTL_GAIN,
493*4882a593Smuzhiyun RK312x_HPOUTR_GAIN, RK312x_HPOUT_GAIN_SFT,
494*4882a593Smuzhiyun 31, 0, out_vol_tlv),
495*4882a593Smuzhiyun SOC_DOUBLE("Speaker Playback Switch", RK312x_HPOUT_CTL,
496*4882a593Smuzhiyun RK312x_HPOUTL_MUTE_SHT, RK312x_HPOUTR_MUTE_SHT, 1, 0),
497*4882a593Smuzhiyun SOC_DOUBLE_R_TLV("Headphone Playback Volume", RK312x_HPOUTL_GAIN,
498*4882a593Smuzhiyun RK312x_HPOUTR_GAIN, RK312x_HPOUT_GAIN_SFT,
499*4882a593Smuzhiyun 31, 0, out_vol_tlv),
500*4882a593Smuzhiyun SOC_DOUBLE("Headphone Playback Switch", RK312x_HPOUT_CTL,
501*4882a593Smuzhiyun RK312x_HPOUTL_MUTE_SHT, RK312x_HPOUTR_MUTE_SHT, 1, 0),
502*4882a593Smuzhiyun SOC_DOUBLE_R_TLV("Earpiece Playback Volume", RK312x_HPOUTL_GAIN,
503*4882a593Smuzhiyun RK312x_HPOUTR_GAIN, RK312x_HPOUT_GAIN_SFT,
504*4882a593Smuzhiyun 31, 0, out_vol_tlv),
505*4882a593Smuzhiyun SOC_DOUBLE("Earpiece Playback Switch", RK312x_HPOUT_CTL,
506*4882a593Smuzhiyun RK312x_HPOUTL_MUTE_SHT, RK312x_HPOUTR_MUTE_SHT, 1, 0),
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* Add for set capture mute */
510*4882a593Smuzhiyun SOC_SINGLE_TLV("Main Mic Capture Volume", RK312x_BST_CTL,
511*4882a593Smuzhiyun RK312x_BSTL_GAIN_SHT, 1, 0, bst_vol_tlv),
512*4882a593Smuzhiyun SOC_SINGLE("Main Mic Capture Switch", RK312x_BST_CTL,
513*4882a593Smuzhiyun RK312x_BSTL_MUTE_SHT, 1, 0),
514*4882a593Smuzhiyun SOC_SINGLE_TLV("Headset Mic Capture Volume", RK312x_BST_CTL,
515*4882a593Smuzhiyun RK312x_BSTR_GAIN_SHT, 1, 0, bst_vol_tlv),
516*4882a593Smuzhiyun SOC_SINGLE("Headset Mic Capture Switch", RK312x_BST_CTL,
517*4882a593Smuzhiyun RK312x_BSTR_MUTE_SHT, 1, 0),
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun SOC_SINGLE("ALCL Switch", RK312x_ALC_MUNIN_CTL,
520*4882a593Smuzhiyun RK312x_ALCL_MUTE_SHT, 1, 0),
521*4882a593Smuzhiyun SOC_SINGLE_TLV("ALCL Capture Volume", RK312x_BSTL_ALCL_CTL,
522*4882a593Smuzhiyun RK312x_ALCL_GAIN_SHT, 31, 0, pga_vol_tlv),
523*4882a593Smuzhiyun SOC_SINGLE("ALCR Switch", RK312x_ALC_MUNIN_CTL,
524*4882a593Smuzhiyun RK312x_ALCR_MUTE_SHT, 1, 0),
525*4882a593Smuzhiyun SOC_SINGLE_TLV("ALCR Capture Volume", RK312x_ALCR_GAIN_CTL,
526*4882a593Smuzhiyun RK312x_ALCL_GAIN_SHT, 31, 0, pga_vol_tlv),
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun SOC_ENUM("BST_L Mode", rk312x_bst_enum[0]),
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun SOC_ENUM("Micbias Voltage", rk312x_micbias_enum[0]),
531*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Back Way", rk312x_agcl_enum[0]),
532*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Way", rk312x_agcl_enum[1]),
533*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Hold Time", rk312x_agcl_enum[2]),
534*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Ramp Up Time", rk312x_agcl_enum[3]),
535*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Ramp Down Time", rk312x_agcl_enum[4]),
536*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Mode", rk312x_agcl_enum[5]),
537*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Gain Update Zero Enable", rk312x_agcl_enum[6]),
538*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Gain Recovery LPGA VOL", rk312x_agcl_enum[7]),
539*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Fast Decrement Enable", rk312x_agcl_enum[8]),
540*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Noise Gate Enable", rk312x_agcl_enum[9]),
541*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Noise Gate Threhold", rk312x_agcl_enum[10]),
542*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Upate Gain", rk312x_agcl_enum[11]),
543*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Slow Clock Enable", rk312x_agcl_enum[12]),
544*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Approximate Sample Rate", rk312x_agcl_enum[13]),
545*4882a593Smuzhiyun SOC_ENUM("PGAL AGC Enable", rk312x_agcl_enum[14]),
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAL AGC Volume", RK312x_PGAL_AGC_CTL4,
548*4882a593Smuzhiyun RK312x_PGA_AGC_VOL_SFT, 31, 0, pga_vol_tlv),
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun SOC_SINGLE("PGAL AGC Max Level High 8 Bits",
551*4882a593Smuzhiyun RK312x_PGAL_AGC_MAX_H,
552*4882a593Smuzhiyun 0, 255, 0),
553*4882a593Smuzhiyun SOC_SINGLE("PGAL AGC Max Level Low 8 Bits",
554*4882a593Smuzhiyun RK312x_PGAL_AGC_MAX_L,
555*4882a593Smuzhiyun 0, 255, 0),
556*4882a593Smuzhiyun SOC_SINGLE("PGAL AGC Min Level High 8 Bits",
557*4882a593Smuzhiyun RK312x_PGAL_AGC_MIN_H,
558*4882a593Smuzhiyun 0, 255, 0),
559*4882a593Smuzhiyun SOC_SINGLE("PGAL AGC Min Level Low 8 Bits",
560*4882a593Smuzhiyun RK312x_PGAL_AGC_MIN_L,
561*4882a593Smuzhiyun 0, 255, 0),
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAL AGC Max Gain",
564*4882a593Smuzhiyun RK312x_PGAL_AGC_CTL5,
565*4882a593Smuzhiyun RK312x_PGA_AGC_MAX_G_SFT, 7, 0,
566*4882a593Smuzhiyun pga_agc_max_vol_tlv),
567*4882a593Smuzhiyun /* AGC enable and 0x0a bit 5 is 1 */
568*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAL AGC Min Gain", RK312x_PGAL_AGC_CTL5,
569*4882a593Smuzhiyun RK312x_PGA_AGC_MIN_G_SFT, 7, 0, pga_agc_min_vol_tlv),
570*4882a593Smuzhiyun /* AGC enable and 0x0a bit 5 is 1 */
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Back Way", rk312x_agcr_enum[0]),
573*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Way", rk312x_agcr_enum[1]),
574*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Hold Time", rk312x_agcr_enum[2]),
575*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Ramp Up Time", rk312x_agcr_enum[3]),
576*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Ramp Down Time", rk312x_agcr_enum[4]),
577*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Mode", rk312x_agcr_enum[5]),
578*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Gain Update Zero Enable", rk312x_agcr_enum[6]),
579*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Gain Recovery LPGA VOL", rk312x_agcr_enum[7]),
580*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Fast Decrement Enable", rk312x_agcr_enum[8]),
581*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Noise Gate Enable", rk312x_agcr_enum[9]),
582*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Noise Gate Threhold", rk312x_agcr_enum[10]),
583*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Upate Gain", rk312x_agcr_enum[11]),
584*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Slow Clock Enable", rk312x_agcr_enum[12]),
585*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Approximate Sample Rate", rk312x_agcr_enum[13]),
586*4882a593Smuzhiyun SOC_ENUM("PGAR AGC Enable", rk312x_agcr_enum[14]),
587*4882a593Smuzhiyun /* AGC disable and 0x0a bit 4 is 1 */
588*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAR AGC Volume", RK312x_PGAR_AGC_CTL4,
589*4882a593Smuzhiyun RK312x_PGA_AGC_VOL_SFT, 31, 0, pga_vol_tlv),
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun SOC_SINGLE("PGAR AGC Max Level High 8 Bits", RK312x_PGAR_AGC_MAX_H,
592*4882a593Smuzhiyun 0, 255, 0),
593*4882a593Smuzhiyun SOC_SINGLE("PGAR AGC Max Level Low 8 Bits", RK312x_PGAR_AGC_MAX_L,
594*4882a593Smuzhiyun 0, 255, 0),
595*4882a593Smuzhiyun SOC_SINGLE("PGAR AGC Min Level High 8 Bits", RK312x_PGAR_AGC_MIN_H,
596*4882a593Smuzhiyun 0, 255, 0),
597*4882a593Smuzhiyun SOC_SINGLE("PGAR AGC Min Level Low 8 Bits", RK312x_PGAR_AGC_MIN_L,
598*4882a593Smuzhiyun 0, 255, 0),
599*4882a593Smuzhiyun /* AGC enable and 0x06 bit 4 is 1 */
600*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAR AGC Max Gain", RK312x_PGAR_AGC_CTL5,
601*4882a593Smuzhiyun RK312x_PGA_AGC_MAX_G_SFT, 7, 0, pga_agc_max_vol_tlv),
602*4882a593Smuzhiyun /* AGC enable and 0x06 bit 4 is 1 */
603*4882a593Smuzhiyun SOC_SINGLE_TLV("PGAR AGC Min Gain", RK312x_PGAR_AGC_CTL5,
604*4882a593Smuzhiyun RK312x_PGA_AGC_MIN_G_SFT, 7, 0, pga_agc_min_vol_tlv),
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun };
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /* For tiny alsa playback/capture/voice call path */
609*4882a593Smuzhiyun static const char *const rk312x_playback_path_mode[] = {
610*4882a593Smuzhiyun "OFF", "RCV", "SPK", "HP", "HP_NO_MIC",
611*4882a593Smuzhiyun "BT", "SPK_HP", "RING_SPK", "RING_HP",
612*4882a593Smuzhiyun "RING_HP_NO_MIC", "RING_SPK_HP"};
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun static const char *const rk312x_capture_path_mode[] = {
615*4882a593Smuzhiyun "MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"};
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun static const char *const rk312x_voice_call_path_mode[] = {
618*4882a593Smuzhiyun "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"};
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk312x_playback_path_type, 0, 0,
622*4882a593Smuzhiyun rk312x_playback_path_mode);
623*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk312x_capture_path_type, 0, 0,
624*4882a593Smuzhiyun rk312x_capture_path_mode);
625*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(rk312x_voice_call_path_type, 0, 0,
626*4882a593Smuzhiyun rk312x_voice_call_path_mode);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun /* static int rk312x_codec_power_up(int type); */
630*4882a593Smuzhiyun static int rk312x_codec_power_down(int type);
631*4882a593Smuzhiyun
rk312x_codec_mute_dac(int mute)632*4882a593Smuzhiyun int rk312x_codec_mute_dac(int mute)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun if (!rk312x_priv) {
635*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
636*4882a593Smuzhiyun return -EINVAL;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun if (mute) {
639*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component, 0xb4, 0x40);
640*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component, 0xb8, 0x40);
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun return 0;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun EXPORT_SYMBOL(rk312x_codec_mute_dac);
645*4882a593Smuzhiyun
rk312x_playback_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)646*4882a593Smuzhiyun static int rk312x_playback_path_get(struct snd_kcontrol *kcontrol,
647*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun if (!rk312x_priv) {
650*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
651*4882a593Smuzhiyun return -EINVAL;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun DBG("%s : playback_path = %ld\n",
655*4882a593Smuzhiyun __func__, ucontrol->value.integer.value[0]);
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk312x_priv->playback_path;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun return 0;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
rk312x_playback_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)662*4882a593Smuzhiyun static int rk312x_playback_path_put(struct snd_kcontrol *kcontrol,
663*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun long int pre_path;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (!rk312x_priv) {
668*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
669*4882a593Smuzhiyun return -EINVAL;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (rk312x_priv->playback_path ==
673*4882a593Smuzhiyun ucontrol->value.integer.value[0]) {
674*4882a593Smuzhiyun DBG("%s : playback_path is not changed!\n", __func__);
675*4882a593Smuzhiyun return 0;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun pre_path = rk312x_priv->playback_path;
679*4882a593Smuzhiyun rk312x_priv->playback_path = ucontrol->value.integer.value[0];
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun DBG("%s : set playback_path = %ld\n", __func__,
682*4882a593Smuzhiyun rk312x_priv->playback_path);
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun switch (rk312x_priv->playback_path) {
685*4882a593Smuzhiyun case OFF:
686*4882a593Smuzhiyun if (pre_path != OFF)
687*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_PLAYBACK);
688*4882a593Smuzhiyun break;
689*4882a593Smuzhiyun case RCV:
690*4882a593Smuzhiyun break;
691*4882a593Smuzhiyun case SPK_PATH:
692*4882a593Smuzhiyun case RING_SPK:
693*4882a593Smuzhiyun if (pre_path == OFF) {
694*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
695*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
696*4882a593Smuzhiyun 0xb4, rk312x_priv->spk_volume);
697*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
698*4882a593Smuzhiyun 0xb8, rk312x_priv->spk_volume);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun break;
701*4882a593Smuzhiyun case HP_PATH:
702*4882a593Smuzhiyun case HP_NO_MIC:
703*4882a593Smuzhiyun case RING_HP:
704*4882a593Smuzhiyun case RING_HP_NO_MIC:
705*4882a593Smuzhiyun if (pre_path == OFF) {
706*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
707*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
708*4882a593Smuzhiyun 0xb4, rk312x_priv->hp_volume);
709*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
710*4882a593Smuzhiyun 0xb8, rk312x_priv->hp_volume);
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun break;
713*4882a593Smuzhiyun case BT:
714*4882a593Smuzhiyun break;
715*4882a593Smuzhiyun case SPK_HP:
716*4882a593Smuzhiyun case RING_SPK_HP:
717*4882a593Smuzhiyun if (pre_path == OFF) {
718*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
719*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
720*4882a593Smuzhiyun 0xb4, rk312x_priv->spk_volume);
721*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
722*4882a593Smuzhiyun 0xb8, rk312x_priv->spk_volume);
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun break;
725*4882a593Smuzhiyun default:
726*4882a593Smuzhiyun return -EINVAL;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun return 0;
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun
rk312x_capture_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)732*4882a593Smuzhiyun static int rk312x_capture_path_get(struct snd_kcontrol *kcontrol,
733*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
734*4882a593Smuzhiyun {
735*4882a593Smuzhiyun if (!rk312x_priv) {
736*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
737*4882a593Smuzhiyun return -EINVAL;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun DBG("%s : capture_path = %ld\n", __func__,
741*4882a593Smuzhiyun ucontrol->value.integer.value[0]);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk312x_priv->capture_path;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun return 0;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
rk312x_capture_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)748*4882a593Smuzhiyun static int rk312x_capture_path_put(struct snd_kcontrol *kcontrol,
749*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun long int pre_path;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (!rk312x_priv) {
754*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
755*4882a593Smuzhiyun return -EINVAL;
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun if (rk312x_priv->capture_path == ucontrol->value.integer.value[0])
759*4882a593Smuzhiyun DBG("%s : capture_path is not changed!\n", __func__);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun pre_path = rk312x_priv->capture_path;
762*4882a593Smuzhiyun rk312x_priv->capture_path = ucontrol->value.integer.value[0];
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun DBG("%s : set capture_path = %ld\n", __func__,
765*4882a593Smuzhiyun rk312x_priv->capture_path);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun switch (rk312x_priv->capture_path) {
768*4882a593Smuzhiyun case MIC_OFF:
769*4882a593Smuzhiyun if (pre_path != MIC_OFF)
770*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_CAPTURE);
771*4882a593Smuzhiyun break;
772*4882a593Smuzhiyun case Main_Mic:
773*4882a593Smuzhiyun if (pre_path == MIC_OFF) {
774*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_CAPTURE);
775*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component, 0x10c,
776*4882a593Smuzhiyun 0x20 | rk312x_priv->capture_volume);
777*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component, 0x14c,
778*4882a593Smuzhiyun 0x20 | rk312x_priv->capture_volume);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun break;
781*4882a593Smuzhiyun case Hands_Free_Mic:
782*4882a593Smuzhiyun if (pre_path == MIC_OFF) {
783*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_CAPTURE);
784*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
785*4882a593Smuzhiyun 0x10c, 0x20 | rk312x_priv->capture_volume);
786*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
787*4882a593Smuzhiyun 0x14c, 0x20 | rk312x_priv->capture_volume);
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun break;
790*4882a593Smuzhiyun case BT_Sco_Mic:
791*4882a593Smuzhiyun break;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun default:
794*4882a593Smuzhiyun return -EINVAL;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun return 0;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
rk312x_voice_call_path_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)800*4882a593Smuzhiyun static int rk312x_voice_call_path_get(struct snd_kcontrol *kcontrol,
801*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun if (!rk312x_priv) {
804*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
805*4882a593Smuzhiyun return -EINVAL;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun DBG("%s : playback_path = %ld\n", __func__,
809*4882a593Smuzhiyun ucontrol->value.integer.value[0]);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun ucontrol->value.integer.value[0] = rk312x_priv->voice_call_path;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun return 0;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
rk312x_voice_call_path_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)816*4882a593Smuzhiyun static int rk312x_voice_call_path_put(struct snd_kcontrol *kcontrol,
817*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun long int pre_path;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun if (!rk312x_priv) {
822*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
823*4882a593Smuzhiyun return -EINVAL;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun if (rk312x_priv->voice_call_path == ucontrol->value.integer.value[0])
827*4882a593Smuzhiyun DBG("%s : playback_path is not changed!\n", __func__);
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun pre_path = rk312x_priv->voice_call_path;
830*4882a593Smuzhiyun rk312x_priv->voice_call_path = ucontrol->value.integer.value[0];
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun DBG("%s : set playback_path = %ld\n", __func__,
833*4882a593Smuzhiyun rk312x_priv->voice_call_path);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun /* open playback route for incall route and keytone */
836*4882a593Smuzhiyun if (pre_path == OFF) {
837*4882a593Smuzhiyun if (rk312x_priv->playback_path != OFF) {
838*4882a593Smuzhiyun /* mute output for incall route pop nosie */
839*4882a593Smuzhiyun mdelay(100);
840*4882a593Smuzhiyun } else {
841*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
842*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
843*4882a593Smuzhiyun 0xb4, rk312x_priv->spk_volume);
844*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
845*4882a593Smuzhiyun 0xb8, rk312x_priv->spk_volume);
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun switch (rk312x_priv->voice_call_path) {
850*4882a593Smuzhiyun case OFF:
851*4882a593Smuzhiyun if (pre_path != MIC_OFF)
852*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_CAPTURE);
853*4882a593Smuzhiyun break;
854*4882a593Smuzhiyun case RCV:
855*4882a593Smuzhiyun break;
856*4882a593Smuzhiyun case SPK_PATH:
857*4882a593Smuzhiyun /* open incall route */
858*4882a593Smuzhiyun if (pre_path == OFF || pre_path == RCV || pre_path == BT)
859*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_INCALL);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun break;
862*4882a593Smuzhiyun case HP_PATH:
863*4882a593Smuzhiyun case HP_NO_MIC:
864*4882a593Smuzhiyun /* open incall route */
865*4882a593Smuzhiyun if (pre_path == OFF || pre_path == RCV || pre_path == BT)
866*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_INCALL);
867*4882a593Smuzhiyun break;
868*4882a593Smuzhiyun case BT:
869*4882a593Smuzhiyun break;
870*4882a593Smuzhiyun default:
871*4882a593Smuzhiyun return -EINVAL;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun return 0;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun static const struct snd_kcontrol_new rk312x_snd_path_controls[] = {
878*4882a593Smuzhiyun SOC_ENUM_EXT("Playback Path", rk312x_playback_path_type,
879*4882a593Smuzhiyun rk312x_playback_path_get, rk312x_playback_path_put),
880*4882a593Smuzhiyun SOC_ENUM_EXT("Capture MIC Path", rk312x_capture_path_type,
881*4882a593Smuzhiyun rk312x_capture_path_get, rk312x_capture_path_put),
882*4882a593Smuzhiyun SOC_ENUM_EXT("Voice Call Path", rk312x_voice_call_path_type,
883*4882a593Smuzhiyun rk312x_voice_call_path_get, rk312x_voice_call_path_put),
884*4882a593Smuzhiyun };
885*4882a593Smuzhiyun
rk312x_dacl_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)886*4882a593Smuzhiyun static int rk312x_dacl_event(struct snd_soc_dapm_widget *w,
887*4882a593Smuzhiyun struct snd_kcontrol *kcontrol,
888*4882a593Smuzhiyun int event)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun switch (event) {
893*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
894*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
895*4882a593Smuzhiyun RK312x_DACL_WORK, 0);
896*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
897*4882a593Smuzhiyun RK312x_DACL_EN | RK312x_DACL_CLK_EN,
898*4882a593Smuzhiyun RK312x_DACL_EN | RK312x_DACL_CLK_EN);
899*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
900*4882a593Smuzhiyun RK312x_DACL_WORK, RK312x_DACL_WORK);
901*4882a593Smuzhiyun break;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMD:
904*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
905*4882a593Smuzhiyun RK312x_DACL_EN | RK312x_DACL_CLK_EN, 0);
906*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
907*4882a593Smuzhiyun RK312x_DACL_WORK, 0);
908*4882a593Smuzhiyun break;
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun default:
911*4882a593Smuzhiyun return 0;
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun return 0;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
rk312x_dacr_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)917*4882a593Smuzhiyun static int rk312x_dacr_event(struct snd_soc_dapm_widget *w,
918*4882a593Smuzhiyun struct snd_kcontrol *kcontrol,
919*4882a593Smuzhiyun int event)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun switch (event) {
924*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
925*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
926*4882a593Smuzhiyun RK312x_DACR_WORK, 0);
927*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
928*4882a593Smuzhiyun RK312x_DACR_EN
929*4882a593Smuzhiyun | RK312x_DACR_CLK_EN,
930*4882a593Smuzhiyun RK312x_DACR_EN
931*4882a593Smuzhiyun | RK312x_DACR_CLK_EN);
932*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
933*4882a593Smuzhiyun RK312x_DACR_WORK,
934*4882a593Smuzhiyun RK312x_DACR_WORK);
935*4882a593Smuzhiyun break;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMD:
938*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
939*4882a593Smuzhiyun RK312x_DACR_EN
940*4882a593Smuzhiyun | RK312x_DACR_CLK_EN, 0);
941*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
942*4882a593Smuzhiyun RK312x_DACR_WORK, 0);
943*4882a593Smuzhiyun break;
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun default:
946*4882a593Smuzhiyun return 0;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun return 0;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun
rk312x_adcl_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)952*4882a593Smuzhiyun static int rk312x_adcl_event(struct snd_soc_dapm_widget *w,
953*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun switch (event) {
958*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
959*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
960*4882a593Smuzhiyun RK312x_ADCL_CLK_EN_SFT
961*4882a593Smuzhiyun | RK312x_ADCL_AMP_EN_SFT,
962*4882a593Smuzhiyun RK312x_ADCL_CLK_EN
963*4882a593Smuzhiyun | RK312x_ADCL_AMP_EN);
964*4882a593Smuzhiyun break;
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMD:
967*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
968*4882a593Smuzhiyun RK312x_ADCL_CLK_EN_SFT
969*4882a593Smuzhiyun | RK312x_ADCL_AMP_EN_SFT, 0);
970*4882a593Smuzhiyun break;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun default:
973*4882a593Smuzhiyun return 0;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun return 0;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
rk312x_adcr_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)979*4882a593Smuzhiyun static int rk312x_adcr_event(struct snd_soc_dapm_widget *w,
980*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun switch (event) {
985*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
986*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
987*4882a593Smuzhiyun RK312x_ADCR_CLK_EN_SFT
988*4882a593Smuzhiyun | RK312x_ADCR_AMP_EN_SFT,
989*4882a593Smuzhiyun RK312x_ADCR_CLK_EN
990*4882a593Smuzhiyun | RK312x_ADCR_AMP_EN);
991*4882a593Smuzhiyun break;
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMD:
994*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
995*4882a593Smuzhiyun RK312x_ADCR_CLK_EN_SFT
996*4882a593Smuzhiyun | RK312x_ADCR_AMP_EN_SFT, 0);
997*4882a593Smuzhiyun break;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun default:
1000*4882a593Smuzhiyun return 0;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun return 0;
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun /* HPmix */
1007*4882a593Smuzhiyun static const struct snd_kcontrol_new rk312x_hpmixl[] = {
1008*4882a593Smuzhiyun SOC_DAPM_SINGLE("ALCR Switch", RK312x_HPMIX_S_SELECT,
1009*4882a593Smuzhiyun RK312x_HPMIXL_SEL_ALCR_SFT, 1, 0),
1010*4882a593Smuzhiyun SOC_DAPM_SINGLE("ALCL Switch", RK312x_HPMIX_S_SELECT,
1011*4882a593Smuzhiyun RK312x_HPMIXL_SEL_ALCL_SFT, 1, 0),
1012*4882a593Smuzhiyun SOC_DAPM_SINGLE("DACL Switch", RK312x_HPMIX_S_SELECT,
1013*4882a593Smuzhiyun RK312x_HPMIXL_SEL_DACL_SFT, 1, 0),
1014*4882a593Smuzhiyun };
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun static const struct snd_kcontrol_new rk312x_hpmixr[] = {
1017*4882a593Smuzhiyun SOC_DAPM_SINGLE("ALCR Switch", RK312x_HPMIX_S_SELECT,
1018*4882a593Smuzhiyun RK312x_HPMIXR_SEL_ALCR_SFT, 1, 0),
1019*4882a593Smuzhiyun SOC_DAPM_SINGLE("ALCL Switch", RK312x_HPMIX_S_SELECT,
1020*4882a593Smuzhiyun RK312x_HPMIXR_SEL_ALCL_SFT, 1, 0),
1021*4882a593Smuzhiyun SOC_DAPM_SINGLE("DACR Switch", RK312x_HPMIX_S_SELECT,
1022*4882a593Smuzhiyun RK312x_HPMIXR_SEL_DACR_SFT, 1, 0),
1023*4882a593Smuzhiyun };
1024*4882a593Smuzhiyun
rk312x_hpmixl_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)1025*4882a593Smuzhiyun static int rk312x_hpmixl_event(struct snd_soc_dapm_widget *w,
1026*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun switch (event) {
1031*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
1032*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1033*4882a593Smuzhiyun RK312x_ZO_DET_VOUTR_SFT,
1034*4882a593Smuzhiyun RK312x_ZO_DET_VOUTR_EN);
1035*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1036*4882a593Smuzhiyun RK312x_ZO_DET_VOUTL_SFT,
1037*4882a593Smuzhiyun RK312x_ZO_DET_VOUTL_EN);
1038*4882a593Smuzhiyun break;
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMD:
1041*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1042*4882a593Smuzhiyun RK312x_ZO_DET_VOUTR_SFT,
1043*4882a593Smuzhiyun RK312x_ZO_DET_VOUTR_DIS);
1044*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1045*4882a593Smuzhiyun RK312x_ZO_DET_VOUTL_SFT,
1046*4882a593Smuzhiyun RK312x_ZO_DET_VOUTL_DIS);
1047*4882a593Smuzhiyun break;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun default:
1050*4882a593Smuzhiyun return 0;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun return 0;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun
rk312x_hpmixr_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)1056*4882a593Smuzhiyun static int rk312x_hpmixr_event(struct snd_soc_dapm_widget *w,
1057*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
1058*4882a593Smuzhiyun {
1059*4882a593Smuzhiyun #if 0
1060*4882a593Smuzhiyun switch (event) {
1061*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
1062*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_HPMIX_CTL,
1063*4882a593Smuzhiyun RK312x_HPMIXR_WORK2, RK312x_HPMIXR_WORK2);
1064*4882a593Smuzhiyun break;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMD:
1067*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_HPMIX_CTL,
1068*4882a593Smuzhiyun RK312x_HPMIXR_WORK2, 0);
1069*4882a593Smuzhiyun break;
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun default:
1072*4882a593Smuzhiyun return 0;
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun #endif
1075*4882a593Smuzhiyun return 0;
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun /* HP MUX */
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun static const char *const hpl_sel[] = {"HPMIXL", "DACL"};
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun static const struct soc_enum hpl_sel_enum =
1083*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_HPMIX_S_SELECT, RK312x_HPMIXL_BYPASS_SFT,
1084*4882a593Smuzhiyun ARRAY_SIZE(hpl_sel), hpl_sel);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun static const struct snd_kcontrol_new hpl_sel_mux =
1087*4882a593Smuzhiyun SOC_DAPM_ENUM("HPL select Mux", hpl_sel_enum);
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun static const char *const hpr_sel[] = {"HPMIXR", "DACR"};
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun static const struct soc_enum hpr_sel_enum =
1092*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_HPMIX_S_SELECT, RK312x_HPMIXR_BYPASS_SFT,
1093*4882a593Smuzhiyun ARRAY_SIZE(hpr_sel), hpr_sel);
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun static const struct snd_kcontrol_new hpr_sel_mux =
1096*4882a593Smuzhiyun SOC_DAPM_ENUM("HPR select Mux", hpr_sel_enum);
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun /* IN_L MUX */
1099*4882a593Smuzhiyun static const char *const lnl_sel[] = {"NO", "BSTL", "LINEL", "NOUSE"};
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun static const struct soc_enum lnl_sel_enum =
1102*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_ALC_MUNIN_CTL, RK312x_MUXINL_F_SHT,
1103*4882a593Smuzhiyun ARRAY_SIZE(lnl_sel), lnl_sel);
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun static const struct snd_kcontrol_new lnl_sel_mux =
1106*4882a593Smuzhiyun SOC_DAPM_ENUM("MUXIN_L select", lnl_sel_enum);
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun /* IN_R MUX */
1109*4882a593Smuzhiyun static const char *const lnr_sel[] = {"NO", "BSTR", "LINER", "NOUSE"};
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun static const struct soc_enum lnr_sel_enum =
1112*4882a593Smuzhiyun SOC_ENUM_SINGLE(RK312x_ALC_MUNIN_CTL, RK312x_MUXINR_F_SHT,
1113*4882a593Smuzhiyun ARRAY_SIZE(lnr_sel), lnr_sel);
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun static const struct snd_kcontrol_new lnr_sel_mux =
1116*4882a593Smuzhiyun SOC_DAPM_ENUM("MUXIN_R select", lnr_sel_enum);
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun static const struct snd_soc_dapm_widget rk312x_dapm_widgets[] = {
1120*4882a593Smuzhiyun /* microphone bias */
1121*4882a593Smuzhiyun SND_SOC_DAPM_MICBIAS("Mic Bias", RK312x_ADC_MIC_CTL,
1122*4882a593Smuzhiyun RK312x_MICBIAS_VOL_ENABLE, 0),
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun /* DACs */
1125*4882a593Smuzhiyun SND_SOC_DAPM_DAC_E("DACL", NULL, SND_SOC_NOPM,
1126*4882a593Smuzhiyun 0, 0, rk312x_dacl_event,
1127*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMD
1128*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1129*4882a593Smuzhiyun SND_SOC_DAPM_DAC_E("DACR", NULL, SND_SOC_NOPM,
1130*4882a593Smuzhiyun 0, 0, rk312x_dacr_event,
1131*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMD
1132*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun /* ADCs */
1135*4882a593Smuzhiyun SND_SOC_DAPM_ADC_E("ADCL", NULL, SND_SOC_NOPM,
1136*4882a593Smuzhiyun 0, 0, rk312x_adcl_event,
1137*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMD
1138*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1139*4882a593Smuzhiyun SND_SOC_DAPM_ADC_E("ADCR", NULL, SND_SOC_NOPM,
1140*4882a593Smuzhiyun 0, 0, rk312x_adcr_event,
1141*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMD
1142*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun /* PGA */
1145*4882a593Smuzhiyun SND_SOC_DAPM_PGA("BSTL", RK312x_BST_CTL,
1146*4882a593Smuzhiyun RK312x_BSTL_PWRD_SFT, 0, NULL, 0),
1147*4882a593Smuzhiyun SND_SOC_DAPM_PGA("BSTR", RK312x_BST_CTL,
1148*4882a593Smuzhiyun RK312x_BSTR_PWRD_SFT, 0, NULL, 0),
1149*4882a593Smuzhiyun SND_SOC_DAPM_PGA("ALCL", RK312x_ALC_MUNIN_CTL,
1150*4882a593Smuzhiyun RK312x_ALCL_PWR_SHT , 0, NULL, 0),
1151*4882a593Smuzhiyun SND_SOC_DAPM_PGA("ALCR", RK312x_ALC_MUNIN_CTL,
1152*4882a593Smuzhiyun RK312x_ALCR_PWR_SHT , 0, NULL, 0),
1153*4882a593Smuzhiyun SND_SOC_DAPM_PGA("HPL", RK312x_HPOUT_CTL,
1154*4882a593Smuzhiyun RK312x_HPOUTL_PWR_SHT, 0, NULL, 0),
1155*4882a593Smuzhiyun SND_SOC_DAPM_PGA("HPR", RK312x_HPOUT_CTL,
1156*4882a593Smuzhiyun RK312x_HPOUTR_PWR_SHT, 0, NULL, 0),
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun /* MIXER */
1159*4882a593Smuzhiyun SND_SOC_DAPM_MIXER_E("HPMIXL", RK312x_HPMIX_CTL,
1160*4882a593Smuzhiyun RK312x_HPMIXL_SFT, 0,
1161*4882a593Smuzhiyun rk312x_hpmixl,
1162*4882a593Smuzhiyun ARRAY_SIZE(rk312x_hpmixl),
1163*4882a593Smuzhiyun rk312x_hpmixl_event,
1164*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMD
1165*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1166*4882a593Smuzhiyun SND_SOC_DAPM_MIXER_E("HPMIXR", RK312x_HPMIX_CTL,
1167*4882a593Smuzhiyun RK312x_HPMIXR_SFT, 0,
1168*4882a593Smuzhiyun rk312x_hpmixr,
1169*4882a593Smuzhiyun ARRAY_SIZE(rk312x_hpmixr),
1170*4882a593Smuzhiyun rk312x_hpmixr_event,
1171*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMD
1172*4882a593Smuzhiyun | SND_SOC_DAPM_POST_PMU),
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun /* MUX */
1175*4882a593Smuzhiyun SND_SOC_DAPM_MUX("IN_R Mux", SND_SOC_NOPM, 0, 0,
1176*4882a593Smuzhiyun &lnr_sel_mux),
1177*4882a593Smuzhiyun SND_SOC_DAPM_MUX("IN_L Mux", SND_SOC_NOPM, 0, 0,
1178*4882a593Smuzhiyun &lnl_sel_mux),
1179*4882a593Smuzhiyun SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0,
1180*4882a593Smuzhiyun &hpl_sel_mux),
1181*4882a593Smuzhiyun SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0,
1182*4882a593Smuzhiyun &hpr_sel_mux),
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun /* Audio Interface */
1185*4882a593Smuzhiyun SND_SOC_DAPM_AIF_IN("I2S DAC", "HiFi Playback", 0,
1186*4882a593Smuzhiyun SND_SOC_NOPM, 0, 0),
1187*4882a593Smuzhiyun SND_SOC_DAPM_AIF_OUT("I2S ADC", "HiFi Capture", 0,
1188*4882a593Smuzhiyun SND_SOC_NOPM, 0, 0),
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun /* Input */
1191*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("LINEL"),
1192*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("LINER"),
1193*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("MICP"),
1194*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("MICN"),
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun /* Output */
1197*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("HPOUTL"),
1198*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("HPOUTR"),
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun };
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun static const struct snd_soc_dapm_route rk312x_dapm_routes[] = {
1203*4882a593Smuzhiyun /* Input */
1204*4882a593Smuzhiyun {"BSTR", NULL, "MICP"},
1205*4882a593Smuzhiyun {"BSTL", NULL, "MICP"},
1206*4882a593Smuzhiyun {"BSTL", NULL, "MICN"},
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun {"IN_R Mux", "LINER", "LINER"},
1209*4882a593Smuzhiyun {"IN_R Mux", "BSTR", "BSTR"},
1210*4882a593Smuzhiyun {"IN_L Mux", "LINEL", "LINEL"},
1211*4882a593Smuzhiyun {"IN_L Mux", "BSTL", "BSTL"},
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun {"ALCL", NULL, "IN_L Mux"},
1214*4882a593Smuzhiyun {"ALCR", NULL, "IN_R Mux"},
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun {"ADCR", NULL, "ALCR"},
1218*4882a593Smuzhiyun {"ADCL", NULL, "ALCL"},
1219*4882a593Smuzhiyun
1220*4882a593Smuzhiyun {"I2S ADC", NULL, "ADCR"},
1221*4882a593Smuzhiyun {"I2S ADC", NULL, "ADCL"},
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun /* Output */
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun {"DACR", NULL, "I2S DAC"},
1226*4882a593Smuzhiyun {"DACL", NULL, "I2S DAC"},
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun {"HPMIXR", "ALCR Switch", "ALCR"},
1229*4882a593Smuzhiyun {"HPMIXR", "ALCL Switch", "ALCL"},
1230*4882a593Smuzhiyun {"HPMIXR", "DACR Switch", "DACR"},
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun {"HPMIXL", "ALCR Switch", "ALCR"},
1233*4882a593Smuzhiyun {"HPMIXL", "ALCL Switch", "ALCL"},
1234*4882a593Smuzhiyun {"HPMIXL", "DACL Switch", "DACL"},
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun {"HPR Mux", "DACR", "DACR"},
1238*4882a593Smuzhiyun {"HPR Mux", "HPMIXR", "HPMIXR"},
1239*4882a593Smuzhiyun {"HPL Mux", "DACL", "DACL"},
1240*4882a593Smuzhiyun {"HPL Mux", "HPMIXL", "HPMIXL"},
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun {"HPR", NULL, "HPR Mux"},
1243*4882a593Smuzhiyun {"HPL", NULL, "HPL Mux"},
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun {"HPOUTR", NULL, "HPR"},
1246*4882a593Smuzhiyun {"HPOUTL", NULL, "HPL"},
1247*4882a593Smuzhiyun };
1248*4882a593Smuzhiyun
rk312x_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)1249*4882a593Smuzhiyun static int rk312x_set_bias_level(struct snd_soc_component *component,
1250*4882a593Smuzhiyun enum snd_soc_bias_level level)
1251*4882a593Smuzhiyun {
1252*4882a593Smuzhiyun DBG("%s level=%d\n", __func__, level);
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun switch (level) {
1255*4882a593Smuzhiyun case SND_SOC_BIAS_ON:
1256*4882a593Smuzhiyun break;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
1259*4882a593Smuzhiyun break;
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
1262*4882a593Smuzhiyun if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
1263*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_DAC_INT_CTL3, 0x32);
1264*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_MIC_CTL,
1265*4882a593Smuzhiyun RK312x_ADC_CURRENT_ENABLE,
1266*4882a593Smuzhiyun RK312x_ADC_CURRENT_ENABLE);
1267*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1268*4882a593Smuzhiyun RK312x_CURRENT_EN,
1269*4882a593Smuzhiyun RK312x_CURRENT_EN);
1270*4882a593Smuzhiyun /* set power */
1271*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
1272*4882a593Smuzhiyun RK312x_ADCL_REF_VOL_EN_SFT
1273*4882a593Smuzhiyun | RK312x_ADCR_REF_VOL_EN_SFT,
1274*4882a593Smuzhiyun RK312x_ADCL_REF_VOL_EN
1275*4882a593Smuzhiyun | RK312x_ADCR_REF_VOL_EN);
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_MIC_CTL,
1278*4882a593Smuzhiyun RK312x_ADCL_ZERO_DET_EN_SFT
1279*4882a593Smuzhiyun | RK312x_ADCR_ZERO_DET_EN_SFT,
1280*4882a593Smuzhiyun RK312x_ADCL_ZERO_DET_EN
1281*4882a593Smuzhiyun | RK312x_ADCR_ZERO_DET_EN);
1282*4882a593Smuzhiyun
1283*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1284*4882a593Smuzhiyun RK312x_REF_VOL_DACL_EN_SFT
1285*4882a593Smuzhiyun | RK312x_REF_VOL_DACR_EN_SFT,
1286*4882a593Smuzhiyun RK312x_REF_VOL_DACL_EN
1287*4882a593Smuzhiyun | RK312x_REF_VOL_DACR_EN);
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
1290*4882a593Smuzhiyun RK312x_DACL_REF_VOL_EN_SFT
1291*4882a593Smuzhiyun | RK312x_DACR_REF_VOL_EN_SFT,
1292*4882a593Smuzhiyun RK312x_DACL_REF_VOL_EN
1293*4882a593Smuzhiyun | RK312x_DACR_REF_VOL_EN);
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun break;
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
1298*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_ENABLE,
1299*4882a593Smuzhiyun RK312x_DACL_REF_VOL_EN_SFT
1300*4882a593Smuzhiyun | RK312x_DACR_REF_VOL_EN_SFT, 0);
1301*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1302*4882a593Smuzhiyun RK312x_REF_VOL_DACL_EN_SFT
1303*4882a593Smuzhiyun | RK312x_REF_VOL_DACR_EN_SFT, 0);
1304*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_MIC_CTL,
1305*4882a593Smuzhiyun RK312x_ADCL_ZERO_DET_EN_SFT
1306*4882a593Smuzhiyun | RK312x_ADCR_ZERO_DET_EN_SFT, 0);
1307*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_ENABLE,
1308*4882a593Smuzhiyun RK312x_ADCL_REF_VOL_EN_SFT
1309*4882a593Smuzhiyun | RK312x_ADCR_REF_VOL_EN_SFT, 0);
1310*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_MIC_CTL,
1311*4882a593Smuzhiyun RK312x_ADC_CURRENT_ENABLE, 0);
1312*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_CTL,
1313*4882a593Smuzhiyun RK312x_CURRENT_EN, 0);
1314*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_DAC_INT_CTL3, 0x22);
1315*4882a593Smuzhiyun break;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun return 0;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
rk312x_set_dai_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)1321*4882a593Smuzhiyun static int rk312x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1322*4882a593Smuzhiyun int clk_id, unsigned int freq, int dir)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x = rk312x_priv;
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun if (!rk312x) {
1327*4882a593Smuzhiyun DBG("%s : rk312x is NULL\n", __func__);
1328*4882a593Smuzhiyun return -EINVAL;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun
1331*4882a593Smuzhiyun rk312x->stereo_sysclk = freq;
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun return 0;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun
rk312x_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)1336*4882a593Smuzhiyun static int rk312x_set_dai_fmt(struct snd_soc_dai *codec_dai,
1337*4882a593Smuzhiyun unsigned int fmt)
1338*4882a593Smuzhiyun {
1339*4882a593Smuzhiyun struct snd_soc_component *component = codec_dai->component;
1340*4882a593Smuzhiyun unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0;
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1343*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
1344*4882a593Smuzhiyun adc_aif2 |= RK312x_I2S_MODE_SLV;
1345*4882a593Smuzhiyun break;
1346*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
1347*4882a593Smuzhiyun adc_aif2 |= RK312x_I2S_MODE_MST;
1348*4882a593Smuzhiyun break;
1349*4882a593Smuzhiyun default:
1350*4882a593Smuzhiyun DBG("%s : set master mask failed!\n", __func__);
1351*4882a593Smuzhiyun return -EINVAL;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1355*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_A:
1356*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_DF_PCM;
1357*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_DF_PCM;
1358*4882a593Smuzhiyun break;
1359*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_B:
1360*4882a593Smuzhiyun break;
1361*4882a593Smuzhiyun case SND_SOC_DAIFMT_I2S:
1362*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_DF_I2S;
1363*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_DF_I2S;
1364*4882a593Smuzhiyun break;
1365*4882a593Smuzhiyun case SND_SOC_DAIFMT_RIGHT_J:
1366*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_DF_RJ;
1367*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_DF_RJ;
1368*4882a593Smuzhiyun break;
1369*4882a593Smuzhiyun case SND_SOC_DAIFMT_LEFT_J:
1370*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_DF_LJ;
1371*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_DF_LJ;
1372*4882a593Smuzhiyun break;
1373*4882a593Smuzhiyun default:
1374*4882a593Smuzhiyun DBG("%s : set format failed!\n", __func__);
1375*4882a593Smuzhiyun return -EINVAL;
1376*4882a593Smuzhiyun }
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1379*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_NF:
1380*4882a593Smuzhiyun adc_aif1 |= RK312x_ALRCK_POL_DIS;
1381*4882a593Smuzhiyun adc_aif2 |= RK312x_ABCLK_POL_DIS;
1382*4882a593Smuzhiyun dac_aif1 |= RK312x_DLRCK_POL_DIS;
1383*4882a593Smuzhiyun dac_aif2 |= RK312x_DBCLK_POL_DIS;
1384*4882a593Smuzhiyun break;
1385*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_IF:
1386*4882a593Smuzhiyun adc_aif1 |= RK312x_ALRCK_POL_EN;
1387*4882a593Smuzhiyun adc_aif2 |= RK312x_ABCLK_POL_EN;
1388*4882a593Smuzhiyun dac_aif1 |= RK312x_DLRCK_POL_EN;
1389*4882a593Smuzhiyun dac_aif2 |= RK312x_DBCLK_POL_EN;
1390*4882a593Smuzhiyun break;
1391*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_NF:
1392*4882a593Smuzhiyun adc_aif1 |= RK312x_ALRCK_POL_DIS;
1393*4882a593Smuzhiyun adc_aif2 |= RK312x_ABCLK_POL_EN;
1394*4882a593Smuzhiyun dac_aif1 |= RK312x_DLRCK_POL_DIS;
1395*4882a593Smuzhiyun dac_aif2 |= RK312x_DBCLK_POL_EN;
1396*4882a593Smuzhiyun break;
1397*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_IF:
1398*4882a593Smuzhiyun adc_aif1 |= RK312x_ALRCK_POL_EN;
1399*4882a593Smuzhiyun adc_aif2 |= RK312x_ABCLK_POL_DIS;
1400*4882a593Smuzhiyun dac_aif1 |= RK312x_DLRCK_POL_EN;
1401*4882a593Smuzhiyun dac_aif2 |= RK312x_DBCLK_POL_DIS;
1402*4882a593Smuzhiyun break;
1403*4882a593Smuzhiyun default:
1404*4882a593Smuzhiyun DBG("%s : set dai format failed!\n", __func__);
1405*4882a593Smuzhiyun return -EINVAL;
1406*4882a593Smuzhiyun }
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_INT_CTL1,
1409*4882a593Smuzhiyun RK312x_ALRCK_POL_MASK
1410*4882a593Smuzhiyun | RK312x_ADC_DF_MASK, adc_aif1);
1411*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_INT_CTL2,
1412*4882a593Smuzhiyun RK312x_ABCLK_POL_MASK
1413*4882a593Smuzhiyun | RK312x_I2S_MODE_MASK, adc_aif2);
1414*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_INT_CTL1,
1415*4882a593Smuzhiyun RK312x_DLRCK_POL_MASK
1416*4882a593Smuzhiyun | RK312x_DAC_DF_MASK, dac_aif1);
1417*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_INT_CTL2,
1418*4882a593Smuzhiyun RK312x_DBCLK_POL_MASK, dac_aif2);
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun return 0;
1421*4882a593Smuzhiyun }
1422*4882a593Smuzhiyun
rk312x_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)1423*4882a593Smuzhiyun static int rk312x_hw_params(struct snd_pcm_substream *substream,
1424*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
1425*4882a593Smuzhiyun struct snd_soc_dai *dai)
1426*4882a593Smuzhiyun {
1427*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1428*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x = rk312x_priv;
1429*4882a593Smuzhiyun unsigned int rate = params_rate(params);
1430*4882a593Smuzhiyun unsigned int div;
1431*4882a593Smuzhiyun unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun if (!rk312x) {
1434*4882a593Smuzhiyun DBG("%s : rk312x is NULL\n", __func__);
1435*4882a593Smuzhiyun return -EINVAL;
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun /* bclk = codec_clk / 4 */
1439*4882a593Smuzhiyun /* lrck = bclk / (wl * 2) */
1440*4882a593Smuzhiyun div = (((rk312x->stereo_sysclk / 4) / rate) / 2);
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun if ((rk312x->stereo_sysclk % (4 * rate * 2) > 0) ||
1443*4882a593Smuzhiyun (div != 16 && div != 20 && div != 24 && div != 32)) {
1444*4882a593Smuzhiyun DBG("%s : need PLL\n", __func__);
1445*4882a593Smuzhiyun return -EINVAL;
1446*4882a593Smuzhiyun }
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun switch (div) {
1449*4882a593Smuzhiyun case 16:
1450*4882a593Smuzhiyun adc_aif2 |= RK312x_ADC_WL_16;
1451*4882a593Smuzhiyun dac_aif2 |= RK312x_DAC_WL_16;
1452*4882a593Smuzhiyun break;
1453*4882a593Smuzhiyun case 20:
1454*4882a593Smuzhiyun adc_aif2 |= RK312x_ADC_WL_20;
1455*4882a593Smuzhiyun dac_aif2 |= RK312x_DAC_WL_20;
1456*4882a593Smuzhiyun break;
1457*4882a593Smuzhiyun case 24:
1458*4882a593Smuzhiyun adc_aif2 |= RK312x_ADC_WL_24;
1459*4882a593Smuzhiyun dac_aif2 |= RK312x_DAC_WL_24;
1460*4882a593Smuzhiyun break;
1461*4882a593Smuzhiyun case 32:
1462*4882a593Smuzhiyun adc_aif2 |= RK312x_ADC_WL_32;
1463*4882a593Smuzhiyun dac_aif2 |= RK312x_DAC_WL_32;
1464*4882a593Smuzhiyun break;
1465*4882a593Smuzhiyun default:
1466*4882a593Smuzhiyun return -EINVAL;
1467*4882a593Smuzhiyun }
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun DBG("%s : MCLK = %dHz, sample rate = %dHz, div = %d\n",
1471*4882a593Smuzhiyun __func__, rk312x->stereo_sysclk, rate, div);
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun switch (params_format(params)) {
1474*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S16_LE:
1475*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_VWL_16;
1476*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_VWL_16;
1477*4882a593Smuzhiyun break;
1478*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S20_3LE:
1479*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_VWL_20;
1480*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_VWL_20;
1481*4882a593Smuzhiyun break;
1482*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S24_LE:
1483*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_VWL_24;
1484*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_VWL_24;
1485*4882a593Smuzhiyun break;
1486*4882a593Smuzhiyun case SNDRV_PCM_FORMAT_S32_LE:
1487*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_VWL_32;
1488*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_VWL_32;
1489*4882a593Smuzhiyun break;
1490*4882a593Smuzhiyun default:
1491*4882a593Smuzhiyun return -EINVAL;
1492*4882a593Smuzhiyun }
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun switch (params_channels(params)) {
1495*4882a593Smuzhiyun case RK312x_MONO:
1496*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_TYPE_MONO;
1497*4882a593Smuzhiyun DBG("mono\n");
1498*4882a593Smuzhiyun break;
1499*4882a593Smuzhiyun case RK312x_STEREO:
1500*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_TYPE_STEREO;
1501*4882a593Smuzhiyun DBG("stero\n");
1502*4882a593Smuzhiyun break;
1503*4882a593Smuzhiyun default:
1504*4882a593Smuzhiyun return -EINVAL;
1505*4882a593Smuzhiyun }
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun adc_aif1 |= RK312x_ADC_SWAP_DIS;
1508*4882a593Smuzhiyun adc_aif2 |= RK312x_ADC_RST_DIS;
1509*4882a593Smuzhiyun dac_aif1 |= RK312x_DAC_SWAP_DIS;
1510*4882a593Smuzhiyun dac_aif2 |= RK312x_DAC_RST_DIS;
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun rk312x->rate = rate;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_INT_CTL1,
1515*4882a593Smuzhiyun RK312x_ADC_VWL_MASK
1516*4882a593Smuzhiyun | RK312x_ADC_SWAP_MASK
1517*4882a593Smuzhiyun | RK312x_ADC_TYPE_MASK, adc_aif1);
1518*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ADC_INT_CTL2,
1519*4882a593Smuzhiyun RK312x_ADC_WL_MASK
1520*4882a593Smuzhiyun | RK312x_ADC_RST_MASK, adc_aif2);
1521*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_INT_CTL1,
1522*4882a593Smuzhiyun RK312x_DAC_VWL_MASK
1523*4882a593Smuzhiyun | RK312x_DAC_SWAP_MASK, dac_aif1);
1524*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_DAC_INT_CTL2,
1525*4882a593Smuzhiyun RK312x_DAC_WL_MASK
1526*4882a593Smuzhiyun | RK312x_DAC_RST_MASK, dac_aif2);
1527*4882a593Smuzhiyun
1528*4882a593Smuzhiyun return 0;
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun
rk312x_codec_unpop(struct work_struct * work)1531*4882a593Smuzhiyun static void rk312x_codec_unpop(struct work_struct *work)
1532*4882a593Smuzhiyun {
1533*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_SPK, 1);
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun
rk312x_digital_mute(struct snd_soc_dai * dai,int mute,int stream)1536*4882a593Smuzhiyun static int rk312x_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
1537*4882a593Smuzhiyun {
1538*4882a593Smuzhiyun
1539*4882a593Smuzhiyun if (mute) {
1540*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_SPK, 0);
1541*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_HP, 0);
1542*4882a593Smuzhiyun } else {
1543*4882a593Smuzhiyun if (!rk312x_priv->rk312x_for_mid) {
1544*4882a593Smuzhiyun schedule_delayed_work(&rk312x_priv->mute_delayed_work,
1545*4882a593Smuzhiyun msecs_to_jiffies(rk312x_priv->spk_mute_delay));
1546*4882a593Smuzhiyun } else {
1547*4882a593Smuzhiyun switch (rk312x_priv->playback_path) {
1548*4882a593Smuzhiyun case SPK_PATH:
1549*4882a593Smuzhiyun case RING_SPK:
1550*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_SPK, 1);
1551*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_HP, 0);
1552*4882a593Smuzhiyun break;
1553*4882a593Smuzhiyun case HP_PATH:
1554*4882a593Smuzhiyun case HP_NO_MIC:
1555*4882a593Smuzhiyun case RING_HP:
1556*4882a593Smuzhiyun case RING_HP_NO_MIC:
1557*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_SPK, 0);
1558*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_HP, 1);
1559*4882a593Smuzhiyun break;
1560*4882a593Smuzhiyun case SPK_HP:
1561*4882a593Smuzhiyun case RING_SPK_HP:
1562*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_SPK, 1);
1563*4882a593Smuzhiyun rk312x_codec_ctl_gpio(CODEC_SET_HP, 1);
1564*4882a593Smuzhiyun break;
1565*4882a593Smuzhiyun default:
1566*4882a593Smuzhiyun break;
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun }
1570*4882a593Smuzhiyun return 0;
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun static struct rk312x_reg_val_typ playback_power_up_list[] = {
1574*4882a593Smuzhiyun {0x18, 0x32},
1575*4882a593Smuzhiyun {0xa0, 0x40|0x08},
1576*4882a593Smuzhiyun {0xa0, 0x62|0x08},
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun {0xb4, 0x80},
1579*4882a593Smuzhiyun {0xb8, 0x80},
1580*4882a593Smuzhiyun {0xa8, 0x44},
1581*4882a593Smuzhiyun {0xa8, 0x55},
1582*4882a593Smuzhiyun
1583*4882a593Smuzhiyun {0xb0, 0x90},
1584*4882a593Smuzhiyun {0xb0, 0xd8},
1585*4882a593Smuzhiyun
1586*4882a593Smuzhiyun {0xa4, 0x88},
1587*4882a593Smuzhiyun {0xa4, 0xcc},
1588*4882a593Smuzhiyun {0xa4, 0xee},
1589*4882a593Smuzhiyun {0xa4, 0xff},
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun {0xac, 0x11}, /*DAC*/
1592*4882a593Smuzhiyun {0xa8, 0x77},
1593*4882a593Smuzhiyun {0xb0, 0xfc},
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun {0xb4, OUT_VOLUME},
1596*4882a593Smuzhiyun {0xb8, OUT_VOLUME},
1597*4882a593Smuzhiyun {0xb0, 0xff},
1598*4882a593Smuzhiyun {0xa0, 0x73|0x08},
1599*4882a593Smuzhiyun };
1600*4882a593Smuzhiyun #define RK312x_CODEC_PLAYBACK_POWER_UP_LIST_LEN ARRAY_SIZE( \
1601*4882a593Smuzhiyun playback_power_up_list)
1602*4882a593Smuzhiyun
1603*4882a593Smuzhiyun static struct rk312x_reg_val_typ playback_power_down_list[] = {
1604*4882a593Smuzhiyun {0xb0, 0xdb},
1605*4882a593Smuzhiyun {0xa8, 0x44},
1606*4882a593Smuzhiyun {0xac, 0x00},
1607*4882a593Smuzhiyun {0xb0, 0x92},
1608*4882a593Smuzhiyun {0xa0, 0x22|0x08},
1609*4882a593Smuzhiyun {0xb0, 0x00},
1610*4882a593Smuzhiyun {0xa8, 0x00},
1611*4882a593Smuzhiyun {0xa4, 0x00},
1612*4882a593Smuzhiyun {0xa0, 0x00|0x08},
1613*4882a593Smuzhiyun {0x18, 0x22},
1614*4882a593Smuzhiyun #ifdef WITH_CAP
1615*4882a593Smuzhiyun /* {0xbc, 0x08},*/
1616*4882a593Smuzhiyun #endif
1617*4882a593Smuzhiyun {0xb4, 0x0},
1618*4882a593Smuzhiyun {0xb8, 0x0},
1619*4882a593Smuzhiyun {0x18, 0x22},
1620*4882a593Smuzhiyun };
1621*4882a593Smuzhiyun #define RK312x_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN ARRAY_SIZE( \
1622*4882a593Smuzhiyun playback_power_down_list)
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun static struct rk312x_reg_val_typ capture_power_up_list[] = {
1625*4882a593Smuzhiyun {0x88, 0x80},
1626*4882a593Smuzhiyun {0x88, 0xc0},
1627*4882a593Smuzhiyun {0x88, 0xc7},
1628*4882a593Smuzhiyun {0x9c, 0x88},
1629*4882a593Smuzhiyun {0x8c, 0x04},
1630*4882a593Smuzhiyun {0x90, 0x66},
1631*4882a593Smuzhiyun {0x9c, 0xcc},
1632*4882a593Smuzhiyun {0x9c, 0xee},
1633*4882a593Smuzhiyun {0x8c, 0x07},
1634*4882a593Smuzhiyun {0x90, 0x77},
1635*4882a593Smuzhiyun {0x94, 0x20 | CAP_VOL},
1636*4882a593Smuzhiyun {0x98, CAP_VOL},
1637*4882a593Smuzhiyun {0x88, 0xf7},
1638*4882a593Smuzhiyun {0x28, 0x3c},
1639*4882a593Smuzhiyun /* {0x124, 0x78}, */
1640*4882a593Smuzhiyun /* {0x164, 0x78}, */
1641*4882a593Smuzhiyun {0x10c, 0x20 | CAP_VOL},
1642*4882a593Smuzhiyun {0x14c, 0x20 | CAP_VOL},
1643*4882a593Smuzhiyun /*close left channel*/
1644*4882a593Smuzhiyun {0x90, 0x07},
1645*4882a593Smuzhiyun {0x88, 0xd7},
1646*4882a593Smuzhiyun {0x8c, 0x07},
1647*4882a593Smuzhiyun {0x9c, 0x0e},
1648*4882a593Smuzhiyun
1649*4882a593Smuzhiyun };
1650*4882a593Smuzhiyun #define RK312x_CODEC_CAPTURE_POWER_UP_LIST_LEN ARRAY_SIZE(capture_power_up_list)
1651*4882a593Smuzhiyun
1652*4882a593Smuzhiyun static struct rk312x_reg_val_typ capture_power_down_list[] = {
1653*4882a593Smuzhiyun {0x9c, 0xcc},
1654*4882a593Smuzhiyun {0x90, 0x66},
1655*4882a593Smuzhiyun {0x8c, 0x44},
1656*4882a593Smuzhiyun {0x9c, 0x88},
1657*4882a593Smuzhiyun {0x88, 0xc7},
1658*4882a593Smuzhiyun {0x88, 0xc0},
1659*4882a593Smuzhiyun {0x88, 0x80},
1660*4882a593Smuzhiyun {0x8c, 0x00},
1661*4882a593Smuzhiyun {0X94, 0x0c},
1662*4882a593Smuzhiyun {0X98, 0x0c},
1663*4882a593Smuzhiyun {0x9c, 0x00},
1664*4882a593Smuzhiyun {0x88, 0x00},
1665*4882a593Smuzhiyun {0x90, 0x44},
1666*4882a593Smuzhiyun {0x28, 0x0c},
1667*4882a593Smuzhiyun {0x10c, 0x2c},
1668*4882a593Smuzhiyun {0x14c, 0x2c},
1669*4882a593Smuzhiyun /* {0x124, 0x38}, */
1670*4882a593Smuzhiyun /* {0x164, 0x38}, */
1671*4882a593Smuzhiyun };
1672*4882a593Smuzhiyun #define RK312x_CODEC_CAPTURE_POWER_DOWN_LIST_LEN ARRAY_SIZE(\
1673*4882a593Smuzhiyun capture_power_down_list)
1674*4882a593Smuzhiyun
rk312x_codec_power_up(int type)1675*4882a593Smuzhiyun static int rk312x_codec_power_up(int type)
1676*4882a593Smuzhiyun {
1677*4882a593Smuzhiyun struct snd_soc_component *component;
1678*4882a593Smuzhiyun int i;
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun if (!rk312x_priv || !rk312x_priv->component) {
1681*4882a593Smuzhiyun DBG("%s : rk312x_priv or rk312x_priv->codec is NULL\n",
1682*4882a593Smuzhiyun __func__);
1683*4882a593Smuzhiyun return -EINVAL;
1684*4882a593Smuzhiyun }
1685*4882a593Smuzhiyun component = rk312x_priv->component;
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun DBG("%s : power up %s%s\n", __func__,
1688*4882a593Smuzhiyun type == RK312x_CODEC_PLAYBACK ? "playback" : "",
1689*4882a593Smuzhiyun type == RK312x_CODEC_CAPTURE ? "capture" : "");
1690*4882a593Smuzhiyun
1691*4882a593Smuzhiyun if (type == RK312x_CODEC_PLAYBACK) {
1692*4882a593Smuzhiyun for (i = 0; i < RK312x_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) {
1693*4882a593Smuzhiyun snd_soc_component_write(component,
1694*4882a593Smuzhiyun playback_power_up_list[i].reg,
1695*4882a593Smuzhiyun playback_power_up_list[i].value);
1696*4882a593Smuzhiyun usleep_range(1000, 1100);
1697*4882a593Smuzhiyun }
1698*4882a593Smuzhiyun } else if (type == RK312x_CODEC_CAPTURE) {
1699*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid == 1) {
1700*4882a593Smuzhiyun for (i = 0;
1701*4882a593Smuzhiyun i < RK312x_CODEC_CAPTURE_POWER_UP_LIST_LEN;
1702*4882a593Smuzhiyun i++) {
1703*4882a593Smuzhiyun snd_soc_component_write(component,
1704*4882a593Smuzhiyun capture_power_up_list[i].reg,
1705*4882a593Smuzhiyun capture_power_up_list[i].value);
1706*4882a593Smuzhiyun }
1707*4882a593Smuzhiyun } else {
1708*4882a593Smuzhiyun for (i = 0;
1709*4882a593Smuzhiyun i < RK312x_CODEC_CAPTURE_POWER_UP_LIST_LEN - 4;
1710*4882a593Smuzhiyun i++) {
1711*4882a593Smuzhiyun snd_soc_component_write(component,
1712*4882a593Smuzhiyun capture_power_up_list[i].reg,
1713*4882a593Smuzhiyun capture_power_up_list[i].value);
1714*4882a593Smuzhiyun }
1715*4882a593Smuzhiyun }
1716*4882a593Smuzhiyun } else if (type == RK312x_CODEC_INCALL) {
1717*4882a593Smuzhiyun snd_soc_component_update_bits(component, RK312x_ALC_MUNIN_CTL,
1718*4882a593Smuzhiyun RK312x_MUXINL_F_MSK | RK312x_MUXINR_F_MSK,
1719*4882a593Smuzhiyun RK312x_MUXINR_F_INR | RK312x_MUXINL_F_INL);
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun return 0;
1723*4882a593Smuzhiyun }
1724*4882a593Smuzhiyun
rk312x_codec_power_down(int type)1725*4882a593Smuzhiyun static int rk312x_codec_power_down(int type)
1726*4882a593Smuzhiyun {
1727*4882a593Smuzhiyun struct snd_soc_component *component;
1728*4882a593Smuzhiyun int i;
1729*4882a593Smuzhiyun
1730*4882a593Smuzhiyun if (!rk312x_priv || !rk312x_priv->component) {
1731*4882a593Smuzhiyun DBG("%s : rk312x_priv or rk312x_priv->component is NULL\n",
1732*4882a593Smuzhiyun __func__);
1733*4882a593Smuzhiyun return -EINVAL;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun component = rk312x_priv->component;
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun DBG("%s : power down %s%s%s\n", __func__,
1738*4882a593Smuzhiyun type == RK312x_CODEC_PLAYBACK ? "playback" : "",
1739*4882a593Smuzhiyun type == RK312x_CODEC_CAPTURE ? "capture" : "",
1740*4882a593Smuzhiyun type == RK312x_CODEC_ALL ? "all" : "");
1741*4882a593Smuzhiyun
1742*4882a593Smuzhiyun if ((type == RK312x_CODEC_CAPTURE) || (type == RK312x_CODEC_INCALL)) {
1743*4882a593Smuzhiyun for (i = 0; i < RK312x_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) {
1744*4882a593Smuzhiyun snd_soc_component_write(component,
1745*4882a593Smuzhiyun capture_power_down_list[i].reg,
1746*4882a593Smuzhiyun capture_power_down_list[i].value);
1747*4882a593Smuzhiyun }
1748*4882a593Smuzhiyun } else if (type == RK312x_CODEC_PLAYBACK) {
1749*4882a593Smuzhiyun for (i = 0;
1750*4882a593Smuzhiyun i < RK312x_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN;
1751*4882a593Smuzhiyun i++) {
1752*4882a593Smuzhiyun snd_soc_component_write(component,
1753*4882a593Smuzhiyun playback_power_down_list[i].reg,
1754*4882a593Smuzhiyun playback_power_down_list[i].value);
1755*4882a593Smuzhiyun }
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun } else if (type == RK312x_CODEC_ALL) {
1758*4882a593Smuzhiyun rk312x_reset(component);
1759*4882a593Smuzhiyun }
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun return 0;
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun
rk312x_codec_capture_work(struct work_struct * work)1764*4882a593Smuzhiyun static void rk312x_codec_capture_work(struct work_struct *work)
1765*4882a593Smuzhiyun {
1766*4882a593Smuzhiyun DBG("%s : rk312x_codec_work_capture_type = %d\n", __func__,
1767*4882a593Smuzhiyun rk312x_codec_work_capture_type);
1768*4882a593Smuzhiyun
1769*4882a593Smuzhiyun switch (rk312x_codec_work_capture_type) {
1770*4882a593Smuzhiyun case RK312x_CODEC_WORK_POWER_DOWN:
1771*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_CAPTURE);
1772*4882a593Smuzhiyun break;
1773*4882a593Smuzhiyun case RK312x_CODEC_WORK_POWER_UP:
1774*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_CAPTURE);
1775*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
1776*4882a593Smuzhiyun 0x10c, 0x20 | rk312x_priv->capture_volume);
1777*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
1778*4882a593Smuzhiyun 0x14c, 0x20 | rk312x_priv->capture_volume);
1779*4882a593Smuzhiyun break;
1780*4882a593Smuzhiyun default:
1781*4882a593Smuzhiyun break;
1782*4882a593Smuzhiyun }
1783*4882a593Smuzhiyun
1784*4882a593Smuzhiyun rk312x_codec_work_capture_type = RK312x_CODEC_WORK_NULL;
1785*4882a593Smuzhiyun }
1786*4882a593Smuzhiyun
rk312x_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1787*4882a593Smuzhiyun static int rk312x_startup(struct snd_pcm_substream *substream,
1788*4882a593Smuzhiyun struct snd_soc_dai *dai)
1789*4882a593Smuzhiyun {
1790*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x = rk312x_priv;
1791*4882a593Smuzhiyun bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
1792*4882a593Smuzhiyun bool is_codec_playback_running;
1793*4882a593Smuzhiyun bool is_codec_capture_running;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid) {
1796*4882a593Smuzhiyun return 0;
1797*4882a593Smuzhiyun }
1798*4882a593Smuzhiyun if (!rk312x) {
1799*4882a593Smuzhiyun DBG("%s : rk312x is NULL\n", __func__);
1800*4882a593Smuzhiyun return -EINVAL;
1801*4882a593Smuzhiyun }
1802*4882a593Smuzhiyun is_codec_playback_running = rk312x->playback_active > 0;
1803*4882a593Smuzhiyun is_codec_capture_running = rk312x->capture_active > 0;
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun if (playback)
1806*4882a593Smuzhiyun rk312x->playback_active++;
1807*4882a593Smuzhiyun else
1808*4882a593Smuzhiyun rk312x->capture_active++;
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun if (playback) {
1811*4882a593Smuzhiyun if (rk312x->playback_active > 0)
1812*4882a593Smuzhiyun if (!is_codec_playback_running) {
1813*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
1814*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
1815*4882a593Smuzhiyun 0xb4, rk312x_priv->spk_volume);
1816*4882a593Smuzhiyun snd_soc_component_write(rk312x_priv->component,
1817*4882a593Smuzhiyun 0xb8, rk312x_priv->spk_volume);
1818*4882a593Smuzhiyun }
1819*4882a593Smuzhiyun } else {
1820*4882a593Smuzhiyun if (rk312x->capture_active > 0 && !is_codec_capture_running) {
1821*4882a593Smuzhiyun if (rk312x_codec_work_capture_type != RK312x_CODEC_WORK_POWER_UP) {
1822*4882a593Smuzhiyun //cancel_delayed_work_sync(&capture_delayed_work);
1823*4882a593Smuzhiyun if (rk312x_codec_work_capture_type == RK312x_CODEC_WORK_NULL)
1824*4882a593Smuzhiyun rk312x_codec_power_up(RK312x_CODEC_CAPTURE);
1825*4882a593Smuzhiyun else
1826*4882a593Smuzhiyun rk312x_codec_work_capture_type = RK312x_CODEC_WORK_NULL;
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun }
1829*4882a593Smuzhiyun }
1830*4882a593Smuzhiyun
1831*4882a593Smuzhiyun return 0;
1832*4882a593Smuzhiyun }
1833*4882a593Smuzhiyun
rk312x_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1834*4882a593Smuzhiyun static void rk312x_shutdown(struct snd_pcm_substream *substream,
1835*4882a593Smuzhiyun struct snd_soc_dai *dai)
1836*4882a593Smuzhiyun {
1837*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x = rk312x_priv;
1838*4882a593Smuzhiyun bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
1839*4882a593Smuzhiyun bool is_codec_playback_running;
1840*4882a593Smuzhiyun bool is_codec_capture_running;
1841*4882a593Smuzhiyun
1842*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid) {
1843*4882a593Smuzhiyun return;
1844*4882a593Smuzhiyun }
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun if (!rk312x) {
1847*4882a593Smuzhiyun DBG("%s : rk312x is NULL\n", __func__);
1848*4882a593Smuzhiyun return;
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun is_codec_playback_running = rk312x->playback_active > 0;
1851*4882a593Smuzhiyun is_codec_capture_running = rk312x->capture_active > 0;
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun if (playback)
1854*4882a593Smuzhiyun rk312x->playback_active--;
1855*4882a593Smuzhiyun else
1856*4882a593Smuzhiyun rk312x->capture_active--;
1857*4882a593Smuzhiyun
1858*4882a593Smuzhiyun if (playback) {
1859*4882a593Smuzhiyun if (rk312x->playback_active <= 0) {
1860*4882a593Smuzhiyun if (is_codec_playback_running)
1861*4882a593Smuzhiyun rk312x_codec_power_down(
1862*4882a593Smuzhiyun RK312x_CODEC_PLAYBACK);
1863*4882a593Smuzhiyun else
1864*4882a593Smuzhiyun DBG(" Warning:playback closed! return !\n");
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun } else {
1867*4882a593Smuzhiyun if (rk312x->capture_active <= 0) {
1868*4882a593Smuzhiyun if ((rk312x_codec_work_capture_type !=
1869*4882a593Smuzhiyun RK312x_CODEC_WORK_POWER_DOWN) &&
1870*4882a593Smuzhiyun is_codec_capture_running) {
1871*4882a593Smuzhiyun cancel_delayed_work_sync(&capture_delayed_work);
1872*4882a593Smuzhiyun /*
1873*4882a593Smuzhiyun * If rk312x_codec_work_capture_type is NULL
1874*4882a593Smuzhiyun * means codec already power down,
1875*4882a593Smuzhiyun * so power up codec.
1876*4882a593Smuzhiyun * If rk312x_codec_work_capture_type is
1877*4882a593Smuzhiyun * RK312x_CODEC_WORK_POWER_UP it means
1878*4882a593Smuzhiyun * codec haven't be powered up, so we don't
1879*4882a593Smuzhiyun * need to power down codec.
1880*4882a593Smuzhiyun * If is playback call power down,
1881*4882a593Smuzhiyun * power down immediatly, because audioflinger
1882*4882a593Smuzhiyun * already has delay 3s.
1883*4882a593Smuzhiyun */
1884*4882a593Smuzhiyun if (rk312x_codec_work_capture_type ==
1885*4882a593Smuzhiyun RK312x_CODEC_WORK_NULL) {
1886*4882a593Smuzhiyun rk312x_codec_work_capture_type =
1887*4882a593Smuzhiyun RK312x_CODEC_WORK_POWER_DOWN;
1888*4882a593Smuzhiyun queue_delayed_work(rk312x_codec_workq,
1889*4882a593Smuzhiyun &capture_delayed_work,
1890*4882a593Smuzhiyun msecs_to_jiffies(3000));
1891*4882a593Smuzhiyun } else {
1892*4882a593Smuzhiyun rk312x_codec_work_capture_type =
1893*4882a593Smuzhiyun RK312x_CODEC_WORK_NULL;
1894*4882a593Smuzhiyun }
1895*4882a593Smuzhiyun }
1896*4882a593Smuzhiyun }
1897*4882a593Smuzhiyun }
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun
1900*4882a593Smuzhiyun #define RK312x_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
1901*4882a593Smuzhiyun SNDRV_PCM_RATE_16000 | \
1902*4882a593Smuzhiyun SNDRV_PCM_RATE_32000 | \
1903*4882a593Smuzhiyun SNDRV_PCM_RATE_44100 | \
1904*4882a593Smuzhiyun SNDRV_PCM_RATE_48000 | \
1905*4882a593Smuzhiyun SNDRV_PCM_RATE_96000 | \
1906*4882a593Smuzhiyun SNDRV_PCM_RATE_192000)
1907*4882a593Smuzhiyun
1908*4882a593Smuzhiyun #define RK312x_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
1909*4882a593Smuzhiyun SNDRV_PCM_RATE_16000 | \
1910*4882a593Smuzhiyun SNDRV_PCM_RATE_32000 | \
1911*4882a593Smuzhiyun SNDRV_PCM_RATE_44100 | \
1912*4882a593Smuzhiyun SNDRV_PCM_RATE_48000 | \
1913*4882a593Smuzhiyun SNDRV_PCM_RATE_96000)
1914*4882a593Smuzhiyun
1915*4882a593Smuzhiyun #define RK312x_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1916*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_3LE |\
1917*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |\
1918*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE)
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun static struct snd_soc_dai_ops rk312x_dai_ops = {
1921*4882a593Smuzhiyun .hw_params = rk312x_hw_params,
1922*4882a593Smuzhiyun .set_fmt = rk312x_set_dai_fmt,
1923*4882a593Smuzhiyun .set_sysclk = rk312x_set_dai_sysclk,
1924*4882a593Smuzhiyun .mute_stream = rk312x_digital_mute,
1925*4882a593Smuzhiyun .startup = rk312x_startup,
1926*4882a593Smuzhiyun .shutdown = rk312x_shutdown,
1927*4882a593Smuzhiyun .no_capture_mute = 1,
1928*4882a593Smuzhiyun };
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun static struct snd_soc_dai_driver rk312x_dai[] = {
1931*4882a593Smuzhiyun {
1932*4882a593Smuzhiyun .name = "rk312x-hifi",
1933*4882a593Smuzhiyun .id = RK312x_HIFI,
1934*4882a593Smuzhiyun .playback = {
1935*4882a593Smuzhiyun .stream_name = "HiFi Playback",
1936*4882a593Smuzhiyun .channels_min = 2,
1937*4882a593Smuzhiyun .channels_max = 2,
1938*4882a593Smuzhiyun .rates = RK312x_PLAYBACK_RATES,
1939*4882a593Smuzhiyun .formats = RK312x_FORMATS,
1940*4882a593Smuzhiyun },
1941*4882a593Smuzhiyun .capture = {
1942*4882a593Smuzhiyun .stream_name = "HiFi Capture",
1943*4882a593Smuzhiyun .channels_min = 2,
1944*4882a593Smuzhiyun .channels_max = 2,
1945*4882a593Smuzhiyun .rates = RK312x_CAPTURE_RATES,
1946*4882a593Smuzhiyun .formats = RK312x_FORMATS,
1947*4882a593Smuzhiyun },
1948*4882a593Smuzhiyun .ops = &rk312x_dai_ops,
1949*4882a593Smuzhiyun },
1950*4882a593Smuzhiyun {
1951*4882a593Smuzhiyun .name = "rk312x-voice",
1952*4882a593Smuzhiyun .id = RK312x_VOICE,
1953*4882a593Smuzhiyun .playback = {
1954*4882a593Smuzhiyun .stream_name = "Voice Playback",
1955*4882a593Smuzhiyun .channels_min = 1,
1956*4882a593Smuzhiyun .channels_max = 2,
1957*4882a593Smuzhiyun .rates = RK312x_PLAYBACK_RATES,
1958*4882a593Smuzhiyun .formats = RK312x_FORMATS,
1959*4882a593Smuzhiyun },
1960*4882a593Smuzhiyun .capture = {
1961*4882a593Smuzhiyun .stream_name = "Voice Capture",
1962*4882a593Smuzhiyun .channels_min = 1,
1963*4882a593Smuzhiyun .channels_max = 2,
1964*4882a593Smuzhiyun .rates = RK312x_CAPTURE_RATES,
1965*4882a593Smuzhiyun .formats = RK312x_FORMATS,
1966*4882a593Smuzhiyun },
1967*4882a593Smuzhiyun .ops = &rk312x_dai_ops,
1968*4882a593Smuzhiyun },
1969*4882a593Smuzhiyun
1970*4882a593Smuzhiyun };
1971*4882a593Smuzhiyun
rk312x_suspend(struct snd_soc_component * component)1972*4882a593Smuzhiyun static int rk312x_suspend(struct snd_soc_component *component)
1973*4882a593Smuzhiyun {
1974*4882a593Smuzhiyun unsigned int val=0;
1975*4882a593Smuzhiyun DBG("%s\n", __func__);
1976*4882a593Smuzhiyun if (rk312x_priv->codec_hp_det) {
1977*4882a593Smuzhiyun /* disable hp det interrupt */
1978*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
1979*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, 0x1f0013);
1980*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
1981*4882a593Smuzhiyun cancel_delayed_work_sync(&rk312x_priv->hpdet_work);
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun }
1984*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid) {
1985*4882a593Smuzhiyun cancel_delayed_work_sync(&capture_delayed_work);
1986*4882a593Smuzhiyun
1987*4882a593Smuzhiyun if (rk312x_codec_work_capture_type != RK312x_CODEC_WORK_NULL)
1988*4882a593Smuzhiyun rk312x_codec_work_capture_type = RK312x_CODEC_WORK_NULL;
1989*4882a593Smuzhiyun
1990*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_PLAYBACK);
1991*4882a593Smuzhiyun rk312x_codec_power_down(RK312x_CODEC_ALL);
1992*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_SELECT_CURRENT, 0x1e);
1993*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_SELECT_CURRENT, 0x3e);
1994*4882a593Smuzhiyun } else {
1995*4882a593Smuzhiyun snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
1996*4882a593Smuzhiyun }
1997*4882a593Smuzhiyun return 0;
1998*4882a593Smuzhiyun }
1999*4882a593Smuzhiyun
gpio_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)2000*4882a593Smuzhiyun static ssize_t gpio_show(struct kobject *kobj, struct kobj_attribute *attr,
2001*4882a593Smuzhiyun char *buf)
2002*4882a593Smuzhiyun {
2003*4882a593Smuzhiyun return 0;
2004*4882a593Smuzhiyun }
2005*4882a593Smuzhiyun
gpio_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t n)2006*4882a593Smuzhiyun static ssize_t gpio_store(struct kobject *kobj, struct kobj_attribute *attr,
2007*4882a593Smuzhiyun const char *buf, size_t n)
2008*4882a593Smuzhiyun {
2009*4882a593Smuzhiyun const char *buftmp = buf;
2010*4882a593Smuzhiyun char cmd;
2011*4882a593Smuzhiyun int ret;
2012*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x =
2013*4882a593Smuzhiyun snd_soc_component_get_drvdata(rk312x_priv->component);
2014*4882a593Smuzhiyun
2015*4882a593Smuzhiyun ret = sscanf(buftmp, "%c ", &cmd);
2016*4882a593Smuzhiyun if (ret == 0)
2017*4882a593Smuzhiyun return ret;
2018*4882a593Smuzhiyun switch (cmd) {
2019*4882a593Smuzhiyun case 'd':
2020*4882a593Smuzhiyun if (rk312x->spk_ctl_gpio) {
2021*4882a593Smuzhiyun gpiod_set_value(rk312x->spk_ctl_gpio, 0);
2022*4882a593Smuzhiyun DBG(KERN_INFO"%s : spk gpio disable\n",__func__);
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun
2025*4882a593Smuzhiyun if (rk312x->hp_ctl_gpio) {
2026*4882a593Smuzhiyun gpiod_set_value(rk312x->hp_ctl_gpio, 0);
2027*4882a593Smuzhiyun DBG(KERN_INFO"%s : disable hp gpio \n",__func__);
2028*4882a593Smuzhiyun }
2029*4882a593Smuzhiyun break;
2030*4882a593Smuzhiyun case 'e':
2031*4882a593Smuzhiyun if (rk312x->spk_ctl_gpio) {
2032*4882a593Smuzhiyun gpiod_set_value(rk312x->spk_ctl_gpio, 1);
2033*4882a593Smuzhiyun DBG(KERN_INFO"%s : spk gpio enable\n",__func__);
2034*4882a593Smuzhiyun }
2035*4882a593Smuzhiyun
2036*4882a593Smuzhiyun if (rk312x->hp_ctl_gpio) {
2037*4882a593Smuzhiyun gpiod_set_value(rk312x->hp_ctl_gpio, 1);
2038*4882a593Smuzhiyun DBG("%s : enable hp gpio \n",__func__);
2039*4882a593Smuzhiyun }
2040*4882a593Smuzhiyun break;
2041*4882a593Smuzhiyun default:
2042*4882a593Smuzhiyun DBG(KERN_ERR"--rk312x codec %s-- unknown cmd\n", __func__);
2043*4882a593Smuzhiyun break;
2044*4882a593Smuzhiyun }
2045*4882a593Smuzhiyun return n;
2046*4882a593Smuzhiyun }
2047*4882a593Smuzhiyun static struct kobject *gpio_kobj;
2048*4882a593Smuzhiyun struct gpio_attribute {
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun struct attribute attr;
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
2053*4882a593Smuzhiyun char *buf);
2054*4882a593Smuzhiyun ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
2055*4882a593Smuzhiyun const char *buf, size_t n);
2056*4882a593Smuzhiyun };
2057*4882a593Smuzhiyun
2058*4882a593Smuzhiyun static struct gpio_attribute gpio_attrs[] = {
2059*4882a593Smuzhiyun /* node_name permision show_func store_func */
2060*4882a593Smuzhiyun __ATTR(spk-ctl, S_IRUGO | S_IWUSR, gpio_show, gpio_store),
2061*4882a593Smuzhiyun };
2062*4882a593Smuzhiyun
rk312x_resume(struct snd_soc_component * component)2063*4882a593Smuzhiyun static int rk312x_resume(struct snd_soc_component *component)
2064*4882a593Smuzhiyun {
2065*4882a593Smuzhiyun unsigned int val = 0;
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun if (rk312x_priv->codec_hp_det) {
2068*4882a593Smuzhiyun /* enable hp det interrupt */
2069*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_DAC_CTL, 0x08);
2070*4882a593Smuzhiyun val = snd_soc_component_read(component, RK312x_DAC_CTL);
2071*4882a593Smuzhiyun printk("0xa0 -- 0x%x\n", val);
2072*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2073*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, 0x1f001f);
2074*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2075*4882a593Smuzhiyun printk("GRF_ACODEC_CON is 0x%x\n", val);
2076*4882a593Smuzhiyun schedule_delayed_work(&rk312x_priv->hpdet_work, msecs_to_jiffies(20));
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun if (!rk312x_priv->rk312x_for_mid)
2079*4882a593Smuzhiyun snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
2080*4882a593Smuzhiyun
2081*4882a593Smuzhiyun return 0;
2082*4882a593Smuzhiyun }
2083*4882a593Smuzhiyun
codec_hp_det_isr(int irq,void * data)2084*4882a593Smuzhiyun static irqreturn_t codec_hp_det_isr(int irq, void *data)
2085*4882a593Smuzhiyun {
2086*4882a593Smuzhiyun unsigned int val = 0;
2087*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2088*4882a593Smuzhiyun DBG("%s GRF_ACODEC_CON -- 0x%x\n", __func__, val);
2089*4882a593Smuzhiyun if (val & 0x1) {
2090*4882a593Smuzhiyun DBG("%s hp det rising\n", __func__);
2091*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, val | 0x10001);
2092*4882a593Smuzhiyun } else if (val & 0x2) {
2093*4882a593Smuzhiyun DBG("%s hp det falling\n", __func__);
2094*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, val | 0x20002);
2095*4882a593Smuzhiyun }
2096*4882a593Smuzhiyun cancel_delayed_work(&rk312x_priv->hpdet_work);
2097*4882a593Smuzhiyun schedule_delayed_work(&rk312x_priv->hpdet_work, msecs_to_jiffies(20));
2098*4882a593Smuzhiyun return IRQ_HANDLED;
2099*4882a593Smuzhiyun }
hpdet_work_func(struct work_struct * work)2100*4882a593Smuzhiyun static void hpdet_work_func(struct work_struct *work)
2101*4882a593Smuzhiyun {
2102*4882a593Smuzhiyun unsigned int val = 0;
2103*4882a593Smuzhiyun
2104*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_SOC_STATUS0, &val);
2105*4882a593Smuzhiyun DBG("%s GRF_SOC_STATUS0 -- 0x%x\n", __func__, val);
2106*4882a593Smuzhiyun if (val & 0x80000000) {
2107*4882a593Smuzhiyun DBG("%s hp det high\n", __func__);
2108*4882a593Smuzhiyun DBG("%s no headset\n", __func__);
2109*4882a593Smuzhiyun extcon_set_state_sync(rk312x_priv->edev,
2110*4882a593Smuzhiyun EXTCON_JACK_HEADPHONE, false);
2111*4882a593Smuzhiyun } else {
2112*4882a593Smuzhiyun DBG("%s hp det low\n", __func__);
2113*4882a593Smuzhiyun DBG("%s headset inserted\n", __func__);
2114*4882a593Smuzhiyun extcon_set_state_sync(rk312x_priv->edev,
2115*4882a593Smuzhiyun EXTCON_JACK_HEADPHONE, true);
2116*4882a593Smuzhiyun }
2117*4882a593Smuzhiyun return;
2118*4882a593Smuzhiyun }
2119*4882a593Smuzhiyun
rk312x_delay_workq(struct work_struct * work)2120*4882a593Smuzhiyun static void rk312x_delay_workq(struct work_struct *work)
2121*4882a593Smuzhiyun {
2122*4882a593Smuzhiyun
2123*4882a593Smuzhiyun int ret;
2124*4882a593Smuzhiyun unsigned int val;
2125*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x_codec;
2126*4882a593Smuzhiyun struct snd_soc_component *component;
2127*4882a593Smuzhiyun
2128*4882a593Smuzhiyun printk("%s\n", __func__);
2129*4882a593Smuzhiyun if (!rk312x_priv || !rk312x_priv->component) {
2130*4882a593Smuzhiyun DBG("%s : rk312x_priv or rk312x_priv->component is NULL\n",
2131*4882a593Smuzhiyun __func__);
2132*4882a593Smuzhiyun return;
2133*4882a593Smuzhiyun }
2134*4882a593Smuzhiyun rk312x_codec = snd_soc_component_get_drvdata(rk312x_priv->component);
2135*4882a593Smuzhiyun component = rk312x_codec->component;
2136*4882a593Smuzhiyun rk312x_reset(component);
2137*4882a593Smuzhiyun if (!rk312x_priv->rk312x_for_mid) {
2138*4882a593Smuzhiyun snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
2139*4882a593Smuzhiyun snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
2140*4882a593Smuzhiyun }
2141*4882a593Smuzhiyun #ifdef WITH_CAP
2142*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_SELECT_CURRENT, 0x1e);
2143*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_SELECT_CURRENT, 0x3e);
2144*4882a593Smuzhiyun #endif
2145*4882a593Smuzhiyun
2146*4882a593Smuzhiyun if (rk312x_codec->codec_hp_det) {
2147*4882a593Smuzhiyun /*init codec_hp_det interrupt only for rk3128 */
2148*4882a593Smuzhiyun ret = devm_request_irq(rk312x_priv->dev, rk312x_priv->irq, codec_hp_det_isr,
2149*4882a593Smuzhiyun IRQF_TRIGGER_RISING, "codec_hp_det", NULL);
2150*4882a593Smuzhiyun if (ret < 0)
2151*4882a593Smuzhiyun DBG(" codec_hp_det request_irq failed %d\n", ret);
2152*4882a593Smuzhiyun
2153*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2154*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, 0x1f001f);
2155*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2156*4882a593Smuzhiyun DBG("GRF_ACODEC_CON 3334is 0x%x\n", val);
2157*4882a593Smuzhiyun /* enable rk 3128 codec_hp_det */
2158*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_DAC_CTL, 0x08);
2159*4882a593Smuzhiyun val = snd_soc_component_read(component, RK312x_DAC_CTL);
2160*4882a593Smuzhiyun DBG("0xa0 -- 0x%x\n", val);
2161*4882a593Smuzhiyun /* codec hp det once */
2162*4882a593Smuzhiyun schedule_delayed_work(&rk312x_priv->hpdet_work, msecs_to_jiffies(100));
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun
2166*4882a593Smuzhiyun }
rk312x_probe(struct snd_soc_component * component)2167*4882a593Smuzhiyun static int rk312x_probe(struct snd_soc_component *component)
2168*4882a593Smuzhiyun {
2169*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x_codec =
2170*4882a593Smuzhiyun snd_soc_component_get_drvdata(component);
2171*4882a593Smuzhiyun unsigned int val;
2172*4882a593Smuzhiyun int ret;
2173*4882a593Smuzhiyun int i = 0;
2174*4882a593Smuzhiyun
2175*4882a593Smuzhiyun rk312x_codec->component = component;
2176*4882a593Smuzhiyun snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
2177*4882a593Smuzhiyun clk_prepare_enable(rk312x_codec->pclk);
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun rk312x_codec->playback_active = 0;
2180*4882a593Smuzhiyun rk312x_codec->capture_active = 0;
2181*4882a593Smuzhiyun
2182*4882a593Smuzhiyun rk312x_codec_workq = create_freezable_workqueue("rk312x-codec");
2183*4882a593Smuzhiyun
2184*4882a593Smuzhiyun if (rk312x_codec_workq == NULL) {
2185*4882a593Smuzhiyun DBG("%s : rk312x_codec_workq is NULL!\n", __func__);
2186*4882a593Smuzhiyun ret = -ENOMEM;
2187*4882a593Smuzhiyun goto err__;
2188*4882a593Smuzhiyun }
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun val = snd_soc_component_read(component, RK312x_RESET);
2191*4882a593Smuzhiyun
2192*4882a593Smuzhiyun if (val != rk312x_reg_defaults[RK312x_RESET]) {
2193*4882a593Smuzhiyun DBG("%s : codec register 0: %x is not a 0x00000003\n",
2194*4882a593Smuzhiyun __func__, val);
2195*4882a593Smuzhiyun ret = -ENODEV;
2196*4882a593Smuzhiyun goto err__;
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun
2199*4882a593Smuzhiyun snd_soc_add_component_controls(component, rk312x_snd_path_controls,
2200*4882a593Smuzhiyun ARRAY_SIZE(rk312x_snd_path_controls));
2201*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk312x_priv->init_delayed_work, rk312x_delay_workq);
2202*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk312x_priv->mute_delayed_work, rk312x_codec_unpop);
2203*4882a593Smuzhiyun INIT_DELAYED_WORK(&rk312x_priv->hpdet_work, hpdet_work_func);
2204*4882a593Smuzhiyun
2205*4882a593Smuzhiyun schedule_delayed_work(&rk312x_priv->init_delayed_work, msecs_to_jiffies(3000));
2206*4882a593Smuzhiyun if (rk312x_codec->gpio_debug) {
2207*4882a593Smuzhiyun gpio_kobj = kobject_create_and_add("codec-spk-ctl", NULL);
2208*4882a593Smuzhiyun
2209*4882a593Smuzhiyun if (!gpio_kobj)
2210*4882a593Smuzhiyun return -ENOMEM;
2211*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(gpio_attrs); i++) {
2212*4882a593Smuzhiyun ret = sysfs_create_file(gpio_kobj, &gpio_attrs[i].attr);
2213*4882a593Smuzhiyun if (ret != 0) {
2214*4882a593Smuzhiyun DBG(KERN_ERR"create codec-spk-ctl sysfs %d error\n", i);
2215*4882a593Smuzhiyun /* return ret; */
2216*4882a593Smuzhiyun }
2217*4882a593Smuzhiyun }
2218*4882a593Smuzhiyun }
2219*4882a593Smuzhiyun return 0;
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun err__:
2222*4882a593Smuzhiyun dbg_codec(2, "%s err ret=%d\n", __func__, ret);
2223*4882a593Smuzhiyun return ret;
2224*4882a593Smuzhiyun }
2225*4882a593Smuzhiyun
2226*4882a593Smuzhiyun /* power down chip */
rk312x_remove(struct snd_soc_component * component)2227*4882a593Smuzhiyun static void rk312x_remove(struct snd_soc_component *component)
2228*4882a593Smuzhiyun {
2229*4882a593Smuzhiyun
2230*4882a593Smuzhiyun DBG("%s\n", __func__);
2231*4882a593Smuzhiyun if (!rk312x_priv) {
2232*4882a593Smuzhiyun DBG("%s : rk312x_priv is NULL\n", __func__);
2233*4882a593Smuzhiyun return;
2234*4882a593Smuzhiyun }
2235*4882a593Smuzhiyun
2236*4882a593Smuzhiyun if (rk312x_priv->spk_ctl_gpio)
2237*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->spk_ctl_gpio, 0);
2238*4882a593Smuzhiyun
2239*4882a593Smuzhiyun if (rk312x_priv->hp_ctl_gpio)
2240*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->hp_ctl_gpio, 0);
2241*4882a593Smuzhiyun
2242*4882a593Smuzhiyun mdelay(10);
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid) {
2245*4882a593Smuzhiyun cancel_delayed_work_sync(&capture_delayed_work);
2246*4882a593Smuzhiyun
2247*4882a593Smuzhiyun if (rk312x_codec_work_capture_type != RK312x_CODEC_WORK_NULL)
2248*4882a593Smuzhiyun rk312x_codec_work_capture_type = RK312x_CODEC_WORK_NULL;
2249*4882a593Smuzhiyun }
2250*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_RESET, 0xfc);
2251*4882a593Smuzhiyun mdelay(10);
2252*4882a593Smuzhiyun snd_soc_component_write(component, RK312x_RESET, 0x3);
2253*4882a593Smuzhiyun mdelay(10);
2254*4882a593Smuzhiyun }
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun
2257*4882a593Smuzhiyun static struct snd_soc_component_driver soc_codec_dev_rk312x = {
2258*4882a593Smuzhiyun .probe = rk312x_probe,
2259*4882a593Smuzhiyun .remove = rk312x_remove,
2260*4882a593Smuzhiyun .suspend = rk312x_suspend,
2261*4882a593Smuzhiyun .resume = rk312x_resume,
2262*4882a593Smuzhiyun .set_bias_level = rk312x_set_bias_level,
2263*4882a593Smuzhiyun };
2264*4882a593Smuzhiyun
2265*4882a593Smuzhiyun static const struct regmap_config rk312x_codec_regmap_config = {
2266*4882a593Smuzhiyun .reg_bits = 32,
2267*4882a593Smuzhiyun .reg_stride = 4,
2268*4882a593Smuzhiyun .val_bits = 32,
2269*4882a593Smuzhiyun .max_register = RK312x_PGAR_AGC_CTL5,
2270*4882a593Smuzhiyun .writeable_reg = rk312x_codec_register,
2271*4882a593Smuzhiyun .readable_reg = rk312x_codec_register,
2272*4882a593Smuzhiyun .volatile_reg = rk312x_volatile_register,
2273*4882a593Smuzhiyun };
2274*4882a593Smuzhiyun
2275*4882a593Smuzhiyun #define GRF_SOC_CON0 0x00140
2276*4882a593Smuzhiyun #define GRF_ACODEC_SEL (BIT(10) | BIT(16 + 10))
2277*4882a593Smuzhiyun
rk312x_platform_probe(struct platform_device * pdev)2278*4882a593Smuzhiyun static int rk312x_platform_probe(struct platform_device *pdev)
2279*4882a593Smuzhiyun {
2280*4882a593Smuzhiyun struct device_node *rk312x_np = pdev->dev.of_node;
2281*4882a593Smuzhiyun struct rk312x_codec_priv *rk312x;
2282*4882a593Smuzhiyun struct resource *res;
2283*4882a593Smuzhiyun int ret;
2284*4882a593Smuzhiyun
2285*4882a593Smuzhiyun rk312x = devm_kzalloc(&pdev->dev, sizeof(*rk312x), GFP_KERNEL);
2286*4882a593Smuzhiyun if (!rk312x) {
2287*4882a593Smuzhiyun dbg_codec(2, "%s : rk312x priv kzalloc failed!\n",
2288*4882a593Smuzhiyun __func__);
2289*4882a593Smuzhiyun return -ENOMEM;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun rk312x_priv = rk312x;
2292*4882a593Smuzhiyun platform_set_drvdata(pdev, rk312x);
2293*4882a593Smuzhiyun rk312x->dev = &pdev->dev;
2294*4882a593Smuzhiyun
2295*4882a593Smuzhiyun #if 0
2296*4882a593Smuzhiyun rk312x->spk_hp_switch_gpio = of_get_named_gpio_flags(rk312x_np,
2297*4882a593Smuzhiyun "spk_hp_switch_gpio", 0, &rk312x->spk_io);
2298*4882a593Smuzhiyun rk312x->spk_io = !rk312x->spk_io;
2299*4882a593Smuzhiyun if (!gpio_is_valid(rk312x->spk_hp_switch_gpio)) {
2300*4882a593Smuzhiyun dbg_codec(2, "invalid spk hp switch_gpio : %d\n",
2301*4882a593Smuzhiyun rk312x->spk_hp_switch_gpio);
2302*4882a593Smuzhiyun rk312x->spk_hp_switch_gpio = INVALID_GPIO;
2303*4882a593Smuzhiyun /* ret = -ENOENT; */
2304*4882a593Smuzhiyun /* goto err__; */
2305*4882a593Smuzhiyun }
2306*4882a593Smuzhiyun DBG("%s : spk_hp_switch_gpio %d spk active_level %d \n", __func__,
2307*4882a593Smuzhiyun rk312x->spk_hp_switch_gpio, rk312x->spk_io);
2308*4882a593Smuzhiyun
2309*4882a593Smuzhiyun if(rk312x->spk_hp_switch_gpio != INVALID_GPIO) {
2310*4882a593Smuzhiyun ret = devm_gpio_request(&pdev->dev, rk312x->spk_hp_switch_gpio, "spk_hp_switch");
2311*4882a593Smuzhiyun if (ret < 0) {
2312*4882a593Smuzhiyun dbg_codec(2, "rk312x_platform_probe spk_hp_switch_gpio fail\n");
2313*4882a593Smuzhiyun /* goto err__; */
2314*4882a593Smuzhiyun rk312x->spk_hp_switch_gpio = INVALID_GPIO;
2315*4882a593Smuzhiyun }
2316*4882a593Smuzhiyun }
2317*4882a593Smuzhiyun #endif
2318*4882a593Smuzhiyun rk312x->edev = devm_extcon_dev_allocate(&pdev->dev, headset_extcon_cable);
2319*4882a593Smuzhiyun if (IS_ERR(rk312x->edev)) {
2320*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate extcon device\n");
2321*4882a593Smuzhiyun return -ENOMEM;
2322*4882a593Smuzhiyun }
2323*4882a593Smuzhiyun
2324*4882a593Smuzhiyun ret = devm_extcon_dev_register(&pdev->dev, rk312x->edev);
2325*4882a593Smuzhiyun if (ret < 0) {
2326*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to register extcon device\n");
2327*4882a593Smuzhiyun return ret;
2328*4882a593Smuzhiyun }
2329*4882a593Smuzhiyun
2330*4882a593Smuzhiyun rk312x->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-ctl",
2331*4882a593Smuzhiyun GPIOD_OUT_LOW);
2332*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(rk312x->hp_ctl_gpio)) {
2333*4882a593Smuzhiyun DBG("%s : hp-ctl-gpio %d\n", __func__,
2334*4882a593Smuzhiyun desc_to_gpio(rk312x->hp_ctl_gpio));
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun
2337*4882a593Smuzhiyun rk312x->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl",
2338*4882a593Smuzhiyun GPIOD_OUT_LOW);
2339*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(rk312x->spk_ctl_gpio)) {
2340*4882a593Smuzhiyun DBG(KERN_INFO "%s : spk-ctl-gpio %d\n", __func__,
2341*4882a593Smuzhiyun desc_to_gpio(rk312x->spk_ctl_gpio));
2342*4882a593Smuzhiyun }
2343*4882a593Smuzhiyun
2344*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "spk-mute-delay",
2345*4882a593Smuzhiyun &rk312x->spk_mute_delay);
2346*4882a593Smuzhiyun if (ret < 0) {
2347*4882a593Smuzhiyun DBG(KERN_ERR "%s() Can not read property spk-mute-delay\n",
2348*4882a593Smuzhiyun __func__);
2349*4882a593Smuzhiyun rk312x->spk_mute_delay = 0;
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "hp-mute-delay",
2353*4882a593Smuzhiyun &rk312x->hp_mute_delay);
2354*4882a593Smuzhiyun if (ret < 0) {
2355*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property hp-mute-delay\n",
2356*4882a593Smuzhiyun __func__);
2357*4882a593Smuzhiyun rk312x->hp_mute_delay = 0;
2358*4882a593Smuzhiyun }
2359*4882a593Smuzhiyun DBG("spk mute delay %dms --- hp mute delay %dms\n",rk312x->spk_mute_delay,rk312x->hp_mute_delay);
2360*4882a593Smuzhiyun
2361*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "rk312x_for_mid",
2362*4882a593Smuzhiyun &rk312x->rk312x_for_mid);
2363*4882a593Smuzhiyun if (ret < 0) {
2364*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property rk312x_for_mid, default for mid\n",
2365*4882a593Smuzhiyun __func__);
2366*4882a593Smuzhiyun rk312x->rk312x_for_mid = 1;
2367*4882a593Smuzhiyun }
2368*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "is_rk3128",
2369*4882a593Smuzhiyun &rk312x->is_rk3128);
2370*4882a593Smuzhiyun if (ret < 0) {
2371*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property is_rk3128, default rk3126\n",
2372*4882a593Smuzhiyun __func__);
2373*4882a593Smuzhiyun rk312x->is_rk3128 = 0;
2374*4882a593Smuzhiyun }
2375*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "spk_volume",
2376*4882a593Smuzhiyun &rk312x->spk_volume);
2377*4882a593Smuzhiyun if (ret < 0) {
2378*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property spk_volume, default 25\n",
2379*4882a593Smuzhiyun __func__);
2380*4882a593Smuzhiyun rk312x->spk_volume = 25;
2381*4882a593Smuzhiyun }
2382*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "hp_volume",
2383*4882a593Smuzhiyun &rk312x->hp_volume);
2384*4882a593Smuzhiyun if (ret < 0) {
2385*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property hp_volume, default 25\n",
2386*4882a593Smuzhiyun __func__);
2387*4882a593Smuzhiyun rk312x->hp_volume = 25;
2388*4882a593Smuzhiyun }
2389*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "capture_volume",
2390*4882a593Smuzhiyun &rk312x->capture_volume);
2391*4882a593Smuzhiyun if (ret < 0) {
2392*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property capture_volume, default 26\n",
2393*4882a593Smuzhiyun __func__);
2394*4882a593Smuzhiyun rk312x->capture_volume = 26;
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "gpio_debug", &rk312x->gpio_debug);
2397*4882a593Smuzhiyun if (ret < 0) {
2398*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property gpio_debug\n", __func__);
2399*4882a593Smuzhiyun rk312x->gpio_debug = 0;
2400*4882a593Smuzhiyun }
2401*4882a593Smuzhiyun ret = of_property_read_u32(rk312x_np, "codec_hp_det", &rk312x->codec_hp_det);
2402*4882a593Smuzhiyun
2403*4882a593Smuzhiyun if (ret < 0) {
2404*4882a593Smuzhiyun DBG(KERN_ERR"%s() Can not read property gpio_debug\n", __func__);
2405*4882a593Smuzhiyun rk312x->codec_hp_det = 0;
2406*4882a593Smuzhiyun }
2407*4882a593Smuzhiyun
2408*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2409*4882a593Smuzhiyun rk312x->regbase = devm_ioremap_resource(&pdev->dev, res);
2410*4882a593Smuzhiyun if (IS_ERR(rk312x->regbase))
2411*4882a593Smuzhiyun return PTR_ERR(rk312x->regbase);
2412*4882a593Smuzhiyun rk312x->regmap = devm_regmap_init_mmio(&pdev->dev, rk312x->regbase,
2413*4882a593Smuzhiyun &rk312x_codec_regmap_config);
2414*4882a593Smuzhiyun if (IS_ERR(rk312x->regmap))
2415*4882a593Smuzhiyun return PTR_ERR(rk312x->regmap);
2416*4882a593Smuzhiyun
2417*4882a593Smuzhiyun rk312x->grf = syscon_regmap_lookup_by_phandle(rk312x_np, "rockchip,grf");
2418*4882a593Smuzhiyun if (IS_ERR(rk312x->grf)) {
2419*4882a593Smuzhiyun dev_err(&pdev->dev, "needs 'rockchip,grf' property\n");
2420*4882a593Smuzhiyun return PTR_ERR(rk312x->grf);
2421*4882a593Smuzhiyun }
2422*4882a593Smuzhiyun ret = regmap_write(rk312x->grf, GRF_SOC_CON0, GRF_ACODEC_SEL);
2423*4882a593Smuzhiyun if (ret) {
2424*4882a593Smuzhiyun dev_err(&pdev->dev, "Could not write to GRF: %d\n", ret);
2425*4882a593Smuzhiyun return ret;
2426*4882a593Smuzhiyun }
2427*4882a593Smuzhiyun
2428*4882a593Smuzhiyun if (rk312x->codec_hp_det)
2429*4882a593Smuzhiyun rk312x->irq = platform_get_irq(pdev, 0);
2430*4882a593Smuzhiyun
2431*4882a593Smuzhiyun rk312x->pclk = devm_clk_get(&pdev->dev, "g_pclk_acodec");
2432*4882a593Smuzhiyun if (IS_ERR(rk312x->pclk)) {
2433*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to get acodec pclk\n");
2434*4882a593Smuzhiyun ret = -ENXIO;
2435*4882a593Smuzhiyun goto err__;
2436*4882a593Smuzhiyun }
2437*4882a593Smuzhiyun rk312x->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
2438*4882a593Smuzhiyun if (IS_ERR(rk312x->mclk)) {
2439*4882a593Smuzhiyun dev_err(&pdev->dev, "Unable to get mclk\n");
2440*4882a593Smuzhiyun ret = -ENXIO;
2441*4882a593Smuzhiyun goto err__;
2442*4882a593Smuzhiyun }
2443*4882a593Smuzhiyun
2444*4882a593Smuzhiyun clk_prepare_enable(rk312x->mclk);
2445*4882a593Smuzhiyun clk_set_rate(rk312x->mclk, 11289600);
2446*4882a593Smuzhiyun
2447*4882a593Smuzhiyun return devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk312x,
2448*4882a593Smuzhiyun rk312x_dai, ARRAY_SIZE(rk312x_dai));
2449*4882a593Smuzhiyun
2450*4882a593Smuzhiyun err__:
2451*4882a593Smuzhiyun platform_set_drvdata(pdev, NULL);
2452*4882a593Smuzhiyun rk312x_priv = NULL;
2453*4882a593Smuzhiyun return ret;
2454*4882a593Smuzhiyun }
2455*4882a593Smuzhiyun
rk312x_platform_remove(struct platform_device * pdev)2456*4882a593Smuzhiyun static int rk312x_platform_remove(struct platform_device *pdev)
2457*4882a593Smuzhiyun {
2458*4882a593Smuzhiyun DBG("%s\n", __func__);
2459*4882a593Smuzhiyun rk312x_priv = NULL;
2460*4882a593Smuzhiyun return 0;
2461*4882a593Smuzhiyun }
2462*4882a593Smuzhiyun
rk312x_platform_shutdown(struct platform_device * pdev)2463*4882a593Smuzhiyun void rk312x_platform_shutdown(struct platform_device *pdev)
2464*4882a593Smuzhiyun {
2465*4882a593Smuzhiyun unsigned int val = 0;
2466*4882a593Smuzhiyun DBG("%s\n", __func__);
2467*4882a593Smuzhiyun if (!rk312x_priv || !rk312x_priv->component) {
2468*4882a593Smuzhiyun DBG("%s : rk312x_priv or rk312x_priv->component is NULL\n",
2469*4882a593Smuzhiyun __func__);
2470*4882a593Smuzhiyun return;
2471*4882a593Smuzhiyun }
2472*4882a593Smuzhiyun if (rk312x_priv->codec_hp_det) {
2473*4882a593Smuzhiyun /* disable hp det interrupt */
2474*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2475*4882a593Smuzhiyun regmap_write(rk312x_priv->grf, GRF_ACODEC_CON, 0x1f0013);
2476*4882a593Smuzhiyun regmap_read(rk312x_priv->grf, GRF_ACODEC_CON, &val);
2477*4882a593Smuzhiyun DBG("disable codec_hp_det GRF_ACODEC_CON is 0x%x\n", val);
2478*4882a593Smuzhiyun cancel_delayed_work_sync(&rk312x_priv->hpdet_work);
2479*4882a593Smuzhiyun }
2480*4882a593Smuzhiyun
2481*4882a593Smuzhiyun if (rk312x_priv->spk_ctl_gpio)
2482*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->spk_ctl_gpio, 0);
2483*4882a593Smuzhiyun
2484*4882a593Smuzhiyun if (rk312x_priv->hp_ctl_gpio)
2485*4882a593Smuzhiyun gpiod_set_value(rk312x_priv->hp_ctl_gpio, 0);
2486*4882a593Smuzhiyun
2487*4882a593Smuzhiyun mdelay(10);
2488*4882a593Smuzhiyun
2489*4882a593Smuzhiyun if (rk312x_priv->rk312x_for_mid) {
2490*4882a593Smuzhiyun cancel_delayed_work_sync(&capture_delayed_work);
2491*4882a593Smuzhiyun if (rk312x_codec_work_capture_type !=
2492*4882a593Smuzhiyun RK312x_CODEC_WORK_NULL)
2493*4882a593Smuzhiyun rk312x_codec_work_capture_type =
2494*4882a593Smuzhiyun RK312x_CODEC_WORK_NULL;
2495*4882a593Smuzhiyun }
2496*4882a593Smuzhiyun
2497*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_RESET, 0xfc);
2498*4882a593Smuzhiyun mdelay(10);
2499*4882a593Smuzhiyun regmap_write(rk312x_priv->regmap, RK312x_RESET, 0x03);
2500*4882a593Smuzhiyun
2501*4882a593Smuzhiyun }
2502*4882a593Smuzhiyun
2503*4882a593Smuzhiyun #ifdef CONFIG_OF
2504*4882a593Smuzhiyun static const struct of_device_id rk312x_codec_of_match[] = {
2505*4882a593Smuzhiyun { .compatible = "rockchip,rk3128-codec" },
2506*4882a593Smuzhiyun {},
2507*4882a593Smuzhiyun };
2508*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk312x_codec_of_match);
2509*4882a593Smuzhiyun #endif
2510*4882a593Smuzhiyun
2511*4882a593Smuzhiyun static struct platform_driver rk312x_codec_driver = {
2512*4882a593Smuzhiyun .driver = {
2513*4882a593Smuzhiyun .name = "rk312x-codec",
2514*4882a593Smuzhiyun .of_match_table = of_match_ptr(rk312x_codec_of_match),
2515*4882a593Smuzhiyun },
2516*4882a593Smuzhiyun .probe = rk312x_platform_probe,
2517*4882a593Smuzhiyun .remove = rk312x_platform_remove,
2518*4882a593Smuzhiyun .shutdown = rk312x_platform_shutdown,
2519*4882a593Smuzhiyun };
2520*4882a593Smuzhiyun module_platform_driver(rk312x_codec_driver);
2521*4882a593Smuzhiyun
2522*4882a593Smuzhiyun /* Module information */
2523*4882a593Smuzhiyun MODULE_AUTHOR("rockchip");
2524*4882a593Smuzhiyun MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
2525*4882a593Smuzhiyun MODULE_LICENSE("GPL");
2526