1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // rt711.c -- rt711 ALSA SoC audio driver
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright(c) 2019 Realtek Semiconductor Corp.
6*4882a593Smuzhiyun //
7*4882a593Smuzhiyun //
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/moduleparam.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/pm_runtime.h>
15*4882a593Smuzhiyun #include <linux/pm.h>
16*4882a593Smuzhiyun #include <linux/soundwire/sdw.h>
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <sound/core.h>
20*4882a593Smuzhiyun #include <sound/pcm.h>
21*4882a593Smuzhiyun #include <sound/pcm_params.h>
22*4882a593Smuzhiyun #include <sound/soc.h>
23*4882a593Smuzhiyun #include <sound/soc-dapm.h>
24*4882a593Smuzhiyun #include <sound/initval.h>
25*4882a593Smuzhiyun #include <sound/tlv.h>
26*4882a593Smuzhiyun #include <sound/hda_verbs.h>
27*4882a593Smuzhiyun #include <sound/jack.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include "rt711.h"
30*4882a593Smuzhiyun
rt711_index_write(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int value)31*4882a593Smuzhiyun static int rt711_index_write(struct regmap *regmap,
32*4882a593Smuzhiyun unsigned int nid, unsigned int reg, unsigned int value)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun int ret;
35*4882a593Smuzhiyun unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun ret = regmap_write(regmap, addr, value);
38*4882a593Smuzhiyun if (ret < 0)
39*4882a593Smuzhiyun pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
40*4882a593Smuzhiyun addr, value, ret);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return ret;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
rt711_index_read(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int * value)45*4882a593Smuzhiyun static int rt711_index_read(struct regmap *regmap,
46*4882a593Smuzhiyun unsigned int nid, unsigned int reg, unsigned int *value)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun int ret;
49*4882a593Smuzhiyun unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun *value = 0;
52*4882a593Smuzhiyun ret = regmap_read(regmap, addr, value);
53*4882a593Smuzhiyun if (ret < 0)
54*4882a593Smuzhiyun pr_err("Failed to get private value: %06x => %04x ret=%d\n",
55*4882a593Smuzhiyun addr, *value, ret);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return ret;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
rt711_index_update_bits(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int mask,unsigned int val)60*4882a593Smuzhiyun static int rt711_index_update_bits(struct regmap *regmap, unsigned int nid,
61*4882a593Smuzhiyun unsigned int reg, unsigned int mask, unsigned int val)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun unsigned int tmp, orig;
64*4882a593Smuzhiyun int ret;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun ret = rt711_index_read(regmap, nid, reg, &orig);
67*4882a593Smuzhiyun if (ret < 0)
68*4882a593Smuzhiyun return ret;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun tmp = orig & ~mask;
71*4882a593Smuzhiyun tmp |= val & mask;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun return rt711_index_write(regmap, nid, reg, tmp);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
rt711_reset(struct regmap * regmap)76*4882a593Smuzhiyun static void rt711_reset(struct regmap *regmap)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun regmap_write(regmap, RT711_FUNC_RESET, 0);
79*4882a593Smuzhiyun rt711_index_update_bits(regmap, RT711_VENDOR_REG,
80*4882a593Smuzhiyun RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET,
81*4882a593Smuzhiyun RT711_HIDDEN_REG_SW_RESET);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
rt711_calibration(struct rt711_priv * rt711)84*4882a593Smuzhiyun static int rt711_calibration(struct rt711_priv *rt711)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun unsigned int val, loop = 0;
87*4882a593Smuzhiyun struct device *dev;
88*4882a593Smuzhiyun struct regmap *regmap = rt711->regmap;
89*4882a593Smuzhiyun int ret = 0;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun mutex_lock(&rt711->calibrate_mutex);
92*4882a593Smuzhiyun regmap_write(rt711->regmap,
93*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun dev = regmap_get_device(regmap);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* Calibration manual mode */
98*4882a593Smuzhiyun rt711_index_update_bits(regmap, RT711_VENDOR_REG, RT711_FSM_CTL,
99*4882a593Smuzhiyun 0xf, 0x0);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /* trigger */
102*4882a593Smuzhiyun rt711_index_update_bits(regmap, RT711_VENDOR_CALI,
103*4882a593Smuzhiyun RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER,
104*4882a593Smuzhiyun RT711_DAC_DC_CALI_TRIGGER);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* wait for calibration process */
107*4882a593Smuzhiyun rt711_index_read(regmap, RT711_VENDOR_CALI,
108*4882a593Smuzhiyun RT711_DAC_DC_CALI_CTL1, &val);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun while (val & RT711_DAC_DC_CALI_TRIGGER) {
111*4882a593Smuzhiyun if (loop >= 500) {
112*4882a593Smuzhiyun pr_err("%s, calibration time-out!\n",
113*4882a593Smuzhiyun __func__);
114*4882a593Smuzhiyun ret = -ETIMEDOUT;
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun loop++;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun usleep_range(10000, 11000);
120*4882a593Smuzhiyun rt711_index_read(regmap, RT711_VENDOR_CALI,
121*4882a593Smuzhiyun RT711_DAC_DC_CALI_CTL1, &val);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* depop mode */
125*4882a593Smuzhiyun rt711_index_update_bits(regmap, RT711_VENDOR_REG,
126*4882a593Smuzhiyun RT711_FSM_CTL, 0xf, RT711_DEPOP_CTL);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun regmap_write(rt711->regmap,
129*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
130*4882a593Smuzhiyun mutex_unlock(&rt711->calibrate_mutex);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun dev_dbg(dev, "%s calibration complete, ret=%d\n", __func__, ret);
133*4882a593Smuzhiyun return ret;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
rt711_button_detect(struct rt711_priv * rt711)136*4882a593Smuzhiyun static unsigned int rt711_button_detect(struct rt711_priv *rt711)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun unsigned int btn_type = 0, val80, val81;
139*4882a593Smuzhiyun int ret;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
142*4882a593Smuzhiyun RT711_IRQ_FLAG_TABLE1, &val80);
143*4882a593Smuzhiyun if (ret < 0)
144*4882a593Smuzhiyun goto read_error;
145*4882a593Smuzhiyun ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
146*4882a593Smuzhiyun RT711_IRQ_FLAG_TABLE2, &val81);
147*4882a593Smuzhiyun if (ret < 0)
148*4882a593Smuzhiyun goto read_error;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun val80 &= 0x0381;
151*4882a593Smuzhiyun val81 &= 0xff00;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun switch (val80) {
154*4882a593Smuzhiyun case 0x0200:
155*4882a593Smuzhiyun case 0x0100:
156*4882a593Smuzhiyun case 0x0080:
157*4882a593Smuzhiyun btn_type |= SND_JACK_BTN_0;
158*4882a593Smuzhiyun break;
159*4882a593Smuzhiyun case 0x0001:
160*4882a593Smuzhiyun btn_type |= SND_JACK_BTN_3;
161*4882a593Smuzhiyun break;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun switch (val81) {
164*4882a593Smuzhiyun case 0x8000:
165*4882a593Smuzhiyun case 0x4000:
166*4882a593Smuzhiyun case 0x2000:
167*4882a593Smuzhiyun btn_type |= SND_JACK_BTN_1;
168*4882a593Smuzhiyun break;
169*4882a593Smuzhiyun case 0x1000:
170*4882a593Smuzhiyun case 0x0800:
171*4882a593Smuzhiyun case 0x0400:
172*4882a593Smuzhiyun btn_type |= SND_JACK_BTN_2;
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun case 0x0200:
175*4882a593Smuzhiyun case 0x0100:
176*4882a593Smuzhiyun btn_type |= SND_JACK_BTN_3;
177*4882a593Smuzhiyun break;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun read_error:
180*4882a593Smuzhiyun return btn_type;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
rt711_headset_detect(struct rt711_priv * rt711)183*4882a593Smuzhiyun static int rt711_headset_detect(struct rt711_priv *rt711)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun unsigned int buf, loop = 0;
186*4882a593Smuzhiyun int ret;
187*4882a593Smuzhiyun unsigned int jack_status = 0, reg;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
190*4882a593Smuzhiyun RT711_COMBO_JACK_AUTO_CTL2, &buf);
191*4882a593Smuzhiyun if (ret < 0)
192*4882a593Smuzhiyun goto io_error;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun while (loop < 500 &&
195*4882a593Smuzhiyun (buf & RT711_COMBOJACK_AUTO_DET_STATUS) == 0) {
196*4882a593Smuzhiyun loop++;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun usleep_range(9000, 10000);
199*4882a593Smuzhiyun ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
200*4882a593Smuzhiyun RT711_COMBO_JACK_AUTO_CTL2, &buf);
201*4882a593Smuzhiyun if (ret < 0)
202*4882a593Smuzhiyun goto io_error;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
205*4882a593Smuzhiyun ret = regmap_read(rt711->regmap, reg, &jack_status);
206*4882a593Smuzhiyun if (ret < 0)
207*4882a593Smuzhiyun goto io_error;
208*4882a593Smuzhiyun if ((jack_status & (1 << 31)) == 0)
209*4882a593Smuzhiyun goto remove_error;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (loop >= 500)
213*4882a593Smuzhiyun goto to_error;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (buf & RT711_COMBOJACK_AUTO_DET_TRS)
216*4882a593Smuzhiyun rt711->jack_type = SND_JACK_HEADPHONE;
217*4882a593Smuzhiyun else if ((buf & RT711_COMBOJACK_AUTO_DET_CTIA) ||
218*4882a593Smuzhiyun (buf & RT711_COMBOJACK_AUTO_DET_OMTP))
219*4882a593Smuzhiyun rt711->jack_type = SND_JACK_HEADSET;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return 0;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun to_error:
224*4882a593Smuzhiyun ret = -ETIMEDOUT;
225*4882a593Smuzhiyun pr_err_ratelimited("Time-out error in %s\n", __func__);
226*4882a593Smuzhiyun return ret;
227*4882a593Smuzhiyun io_error:
228*4882a593Smuzhiyun pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
229*4882a593Smuzhiyun return ret;
230*4882a593Smuzhiyun remove_error:
231*4882a593Smuzhiyun pr_err_ratelimited("Jack removal in %s\n", __func__);
232*4882a593Smuzhiyun return -ENODEV;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
rt711_jack_detect_handler(struct work_struct * work)235*4882a593Smuzhiyun static void rt711_jack_detect_handler(struct work_struct *work)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct rt711_priv *rt711 =
238*4882a593Smuzhiyun container_of(work, struct rt711_priv, jack_detect_work.work);
239*4882a593Smuzhiyun int btn_type = 0, ret;
240*4882a593Smuzhiyun unsigned int jack_status = 0, reg;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun if (!rt711->hs_jack)
243*4882a593Smuzhiyun return;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (!rt711->component->card->instantiated)
246*4882a593Smuzhiyun return;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
249*4882a593Smuzhiyun ret = regmap_read(rt711->regmap, reg, &jack_status);
250*4882a593Smuzhiyun if (ret < 0)
251*4882a593Smuzhiyun goto io_error;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /* pin attached */
254*4882a593Smuzhiyun if (jack_status & (1 << 31)) {
255*4882a593Smuzhiyun /* jack in */
256*4882a593Smuzhiyun if (rt711->jack_type == 0) {
257*4882a593Smuzhiyun ret = rt711_headset_detect(rt711);
258*4882a593Smuzhiyun if (ret < 0)
259*4882a593Smuzhiyun return;
260*4882a593Smuzhiyun if (rt711->jack_type == SND_JACK_HEADSET)
261*4882a593Smuzhiyun btn_type = rt711_button_detect(rt711);
262*4882a593Smuzhiyun } else if (rt711->jack_type == SND_JACK_HEADSET) {
263*4882a593Smuzhiyun /* jack is already in, report button event */
264*4882a593Smuzhiyun btn_type = rt711_button_detect(rt711);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun } else {
267*4882a593Smuzhiyun /* jack out */
268*4882a593Smuzhiyun rt711->jack_type = 0;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev,
272*4882a593Smuzhiyun "in %s, jack_type=0x%x\n", __func__, rt711->jack_type);
273*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev,
274*4882a593Smuzhiyun "in %s, btn_type=0x%x\n", __func__, btn_type);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
277*4882a593Smuzhiyun SND_JACK_HEADSET |
278*4882a593Smuzhiyun SND_JACK_BTN_0 | SND_JACK_BTN_1 |
279*4882a593Smuzhiyun SND_JACK_BTN_2 | SND_JACK_BTN_3);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (btn_type) {
282*4882a593Smuzhiyun /* button released */
283*4882a593Smuzhiyun snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
284*4882a593Smuzhiyun SND_JACK_HEADSET |
285*4882a593Smuzhiyun SND_JACK_BTN_0 | SND_JACK_BTN_1 |
286*4882a593Smuzhiyun SND_JACK_BTN_2 | SND_JACK_BTN_3);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun mod_delayed_work(system_power_efficient_wq,
289*4882a593Smuzhiyun &rt711->jack_btn_check_work, msecs_to_jiffies(200));
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun return;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun io_error:
295*4882a593Smuzhiyun pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
rt711_btn_check_handler(struct work_struct * work)298*4882a593Smuzhiyun static void rt711_btn_check_handler(struct work_struct *work)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun struct rt711_priv *rt711 = container_of(work, struct rt711_priv,
301*4882a593Smuzhiyun jack_btn_check_work.work);
302*4882a593Smuzhiyun int btn_type = 0, ret;
303*4882a593Smuzhiyun unsigned int jack_status = 0, reg;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
306*4882a593Smuzhiyun ret = regmap_read(rt711->regmap, reg, &jack_status);
307*4882a593Smuzhiyun if (ret < 0)
308*4882a593Smuzhiyun goto io_error;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /* pin attached */
311*4882a593Smuzhiyun if (jack_status & (1 << 31)) {
312*4882a593Smuzhiyun if (rt711->jack_type == SND_JACK_HEADSET) {
313*4882a593Smuzhiyun /* jack is already in, report button event */
314*4882a593Smuzhiyun btn_type = rt711_button_detect(rt711);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun } else {
317*4882a593Smuzhiyun rt711->jack_type = 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /* cbj comparator */
321*4882a593Smuzhiyun ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
322*4882a593Smuzhiyun RT711_COMBO_JACK_AUTO_CTL2, ®);
323*4882a593Smuzhiyun if (ret < 0)
324*4882a593Smuzhiyun goto io_error;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if ((reg & 0xf0) == 0xf0)
327*4882a593Smuzhiyun btn_type = 0;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev,
330*4882a593Smuzhiyun "%s, btn_type=0x%x\n", __func__, btn_type);
331*4882a593Smuzhiyun snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
332*4882a593Smuzhiyun SND_JACK_HEADSET |
333*4882a593Smuzhiyun SND_JACK_BTN_0 | SND_JACK_BTN_1 |
334*4882a593Smuzhiyun SND_JACK_BTN_2 | SND_JACK_BTN_3);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (btn_type) {
337*4882a593Smuzhiyun /* button released */
338*4882a593Smuzhiyun snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
339*4882a593Smuzhiyun SND_JACK_HEADSET |
340*4882a593Smuzhiyun SND_JACK_BTN_0 | SND_JACK_BTN_1 |
341*4882a593Smuzhiyun SND_JACK_BTN_2 | SND_JACK_BTN_3);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun mod_delayed_work(system_power_efficient_wq,
344*4882a593Smuzhiyun &rt711->jack_btn_check_work, msecs_to_jiffies(200));
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun return;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun io_error:
350*4882a593Smuzhiyun pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
rt711_jack_init(struct rt711_priv * rt711)353*4882a593Smuzhiyun static void rt711_jack_init(struct rt711_priv *rt711)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm =
356*4882a593Smuzhiyun snd_soc_component_get_dapm(rt711->component);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun mutex_lock(&rt711->calibrate_mutex);
359*4882a593Smuzhiyun /* power on */
360*4882a593Smuzhiyun if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
361*4882a593Smuzhiyun regmap_write(rt711->regmap,
362*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun if (rt711->hs_jack) {
365*4882a593Smuzhiyun /* unsolicited response & IRQ control */
366*4882a593Smuzhiyun regmap_write(rt711->regmap,
367*4882a593Smuzhiyun RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x82);
368*4882a593Smuzhiyun regmap_write(rt711->regmap,
369*4882a593Smuzhiyun RT711_SET_HP_UNSOLICITED_ENABLE, 0x81);
370*4882a593Smuzhiyun regmap_write(rt711->regmap,
371*4882a593Smuzhiyun RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x83);
372*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
373*4882a593Smuzhiyun 0x10, 0x2420);
374*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
375*4882a593Smuzhiyun 0x19, 0x2e11);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun switch (rt711->jd_src) {
378*4882a593Smuzhiyun case RT711_JD1:
379*4882a593Smuzhiyun /* default settings was already for JD1 */
380*4882a593Smuzhiyun break;
381*4882a593Smuzhiyun case RT711_JD2:
382*4882a593Smuzhiyun rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
383*4882a593Smuzhiyun RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP |
384*4882a593Smuzhiyun RT711_HP_JD_SEL_JD2,
385*4882a593Smuzhiyun RT711_JD2_2PORT_200K_DECODE_HP |
386*4882a593Smuzhiyun RT711_HP_JD_SEL_JD2);
387*4882a593Smuzhiyun rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
388*4882a593Smuzhiyun RT711_CC_DET1,
389*4882a593Smuzhiyun RT711_HP_JD_FINAL_RESULT_CTL_JD12,
390*4882a593Smuzhiyun RT711_HP_JD_FINAL_RESULT_CTL_JD12);
391*4882a593Smuzhiyun break;
392*4882a593Smuzhiyun default:
393*4882a593Smuzhiyun dev_warn(rt711->component->dev, "Wrong JD source\n");
394*4882a593Smuzhiyun break;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev, "in %s enable\n", __func__);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun mod_delayed_work(system_power_efficient_wq,
400*4882a593Smuzhiyun &rt711->jack_detect_work, msecs_to_jiffies(250));
401*4882a593Smuzhiyun } else {
402*4882a593Smuzhiyun regmap_write(rt711->regmap,
403*4882a593Smuzhiyun RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x00);
404*4882a593Smuzhiyun regmap_write(rt711->regmap,
405*4882a593Smuzhiyun RT711_SET_HP_UNSOLICITED_ENABLE, 0x00);
406*4882a593Smuzhiyun regmap_write(rt711->regmap,
407*4882a593Smuzhiyun RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x00);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev, "in %s disable\n", __func__);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* power off */
413*4882a593Smuzhiyun if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
414*4882a593Smuzhiyun regmap_write(rt711->regmap,
415*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
416*4882a593Smuzhiyun mutex_unlock(&rt711->calibrate_mutex);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
rt711_set_jack_detect(struct snd_soc_component * component,struct snd_soc_jack * hs_jack,void * data)419*4882a593Smuzhiyun static int rt711_set_jack_detect(struct snd_soc_component *component,
420*4882a593Smuzhiyun struct snd_soc_jack *hs_jack, void *data)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun rt711->hs_jack = hs_jack;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (!rt711->hw_init) {
427*4882a593Smuzhiyun dev_dbg(&rt711->slave->dev,
428*4882a593Smuzhiyun "%s hw_init not ready yet\n", __func__);
429*4882a593Smuzhiyun return 0;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun rt711_jack_init(rt711);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun return 0;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
rt711_get_gain(struct rt711_priv * rt711,unsigned int addr_h,unsigned int addr_l,unsigned int val_h,unsigned int * r_val,unsigned int * l_val)437*4882a593Smuzhiyun static void rt711_get_gain(struct rt711_priv *rt711, unsigned int addr_h,
438*4882a593Smuzhiyun unsigned int addr_l, unsigned int val_h,
439*4882a593Smuzhiyun unsigned int *r_val, unsigned int *l_val)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun /* R Channel */
442*4882a593Smuzhiyun *r_val = (val_h << 8);
443*4882a593Smuzhiyun regmap_read(rt711->regmap, addr_l, r_val);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* L Channel */
446*4882a593Smuzhiyun val_h |= 0x20;
447*4882a593Smuzhiyun *l_val = (val_h << 8);
448*4882a593Smuzhiyun regmap_read(rt711->regmap, addr_h, l_val);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* For Verb-Set Amplifier Gain (Verb ID = 3h) */
rt711_set_amp_gain_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)452*4882a593Smuzhiyun static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol,
453*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
456*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm =
457*4882a593Smuzhiyun snd_soc_component_get_dapm(component);
458*4882a593Smuzhiyun struct soc_mixer_control *mc =
459*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
460*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
461*4882a593Smuzhiyun unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
462*4882a593Smuzhiyun unsigned int read_ll, read_rl;
463*4882a593Smuzhiyun int i;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun mutex_lock(&rt711->calibrate_mutex);
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun /* Can't use update bit function, so read the original value first */
468*4882a593Smuzhiyun addr_h = mc->reg;
469*4882a593Smuzhiyun addr_l = mc->rreg;
470*4882a593Smuzhiyun if (mc->shift == RT711_DIR_OUT_SFT) /* output */
471*4882a593Smuzhiyun val_h = 0x80;
472*4882a593Smuzhiyun else /* input */
473*4882a593Smuzhiyun val_h = 0x0;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /* L Channel */
478*4882a593Smuzhiyun if (mc->invert) {
479*4882a593Smuzhiyun /* for mute/unmute */
480*4882a593Smuzhiyun val_ll = (mc->max - ucontrol->value.integer.value[0])
481*4882a593Smuzhiyun << RT711_MUTE_SFT;
482*4882a593Smuzhiyun /* keep gain */
483*4882a593Smuzhiyun read_ll = read_ll & 0x7f;
484*4882a593Smuzhiyun val_ll |= read_ll;
485*4882a593Smuzhiyun } else {
486*4882a593Smuzhiyun /* for gain */
487*4882a593Smuzhiyun val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
488*4882a593Smuzhiyun if (val_ll > mc->max)
489*4882a593Smuzhiyun val_ll = mc->max;
490*4882a593Smuzhiyun /* keep mute status */
491*4882a593Smuzhiyun read_ll = read_ll & (1 << RT711_MUTE_SFT);
492*4882a593Smuzhiyun val_ll |= read_ll;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
496*4882a593Smuzhiyun regmap_write(rt711->regmap,
497*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* R Channel */
500*4882a593Smuzhiyun if (mc->invert) {
501*4882a593Smuzhiyun /* for mute/unmute */
502*4882a593Smuzhiyun val_lr = (mc->max - ucontrol->value.integer.value[1])
503*4882a593Smuzhiyun << RT711_MUTE_SFT;
504*4882a593Smuzhiyun /* keep gain */
505*4882a593Smuzhiyun read_rl = read_rl & 0x7f;
506*4882a593Smuzhiyun val_lr |= read_rl;
507*4882a593Smuzhiyun } else {
508*4882a593Smuzhiyun /* for gain */
509*4882a593Smuzhiyun val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
510*4882a593Smuzhiyun if (val_lr > mc->max)
511*4882a593Smuzhiyun val_lr = mc->max;
512*4882a593Smuzhiyun /* keep mute status */
513*4882a593Smuzhiyun read_rl = read_rl & (1 << RT711_MUTE_SFT);
514*4882a593Smuzhiyun val_lr |= read_rl;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun for (i = 0; i < 3; i++) { /* retry 3 times at most */
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun if (val_ll == val_lr) {
520*4882a593Smuzhiyun /* Set both L/R channels at the same time */
521*4882a593Smuzhiyun val_h = (1 << mc->shift) | (3 << 4);
522*4882a593Smuzhiyun regmap_write(rt711->regmap,
523*4882a593Smuzhiyun addr_h, (val_h << 8 | val_ll));
524*4882a593Smuzhiyun regmap_write(rt711->regmap,
525*4882a593Smuzhiyun addr_l, (val_h << 8 | val_ll));
526*4882a593Smuzhiyun } else {
527*4882a593Smuzhiyun /* Lch*/
528*4882a593Smuzhiyun val_h = (1 << mc->shift) | (1 << 5);
529*4882a593Smuzhiyun regmap_write(rt711->regmap,
530*4882a593Smuzhiyun addr_h, (val_h << 8 | val_ll));
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun /* Rch */
533*4882a593Smuzhiyun val_h = (1 << mc->shift) | (1 << 4);
534*4882a593Smuzhiyun regmap_write(rt711->regmap,
535*4882a593Smuzhiyun addr_l, (val_h << 8 | val_lr));
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun /* check result */
538*4882a593Smuzhiyun if (mc->shift == RT711_DIR_OUT_SFT) /* output */
539*4882a593Smuzhiyun val_h = 0x80;
540*4882a593Smuzhiyun else /* input */
541*4882a593Smuzhiyun val_h = 0x0;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun rt711_get_gain(rt711, addr_h, addr_l, val_h,
544*4882a593Smuzhiyun &read_rl, &read_ll);
545*4882a593Smuzhiyun if (read_rl == val_lr && read_ll == val_ll)
546*4882a593Smuzhiyun break;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
550*4882a593Smuzhiyun regmap_write(rt711->regmap,
551*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun mutex_unlock(&rt711->calibrate_mutex);
554*4882a593Smuzhiyun return 0;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
rt711_set_amp_gain_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)557*4882a593Smuzhiyun static int rt711_set_amp_gain_get(struct snd_kcontrol *kcontrol,
558*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
561*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
562*4882a593Smuzhiyun struct soc_mixer_control *mc =
563*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
564*4882a593Smuzhiyun unsigned int addr_h, addr_l, val_h;
565*4882a593Smuzhiyun unsigned int read_ll, read_rl;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* switch to get command */
568*4882a593Smuzhiyun addr_h = mc->reg;
569*4882a593Smuzhiyun addr_l = mc->rreg;
570*4882a593Smuzhiyun if (mc->shift == RT711_DIR_OUT_SFT) /* output */
571*4882a593Smuzhiyun val_h = 0x80;
572*4882a593Smuzhiyun else /* input */
573*4882a593Smuzhiyun val_h = 0x0;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (mc->invert) {
578*4882a593Smuzhiyun /* mute/unmute for switch controls */
579*4882a593Smuzhiyun read_ll = !((read_ll & 0x80) >> RT711_MUTE_SFT);
580*4882a593Smuzhiyun read_rl = !((read_rl & 0x80) >> RT711_MUTE_SFT);
581*4882a593Smuzhiyun } else {
582*4882a593Smuzhiyun /* for gain volume controls */
583*4882a593Smuzhiyun read_ll = read_ll & 0x7f;
584*4882a593Smuzhiyun read_rl = read_rl & 0x7f;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun ucontrol->value.integer.value[0] = read_ll;
587*4882a593Smuzhiyun ucontrol->value.integer.value[1] = read_rl;
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun return 0;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
593*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
594*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun static const struct snd_kcontrol_new rt711_snd_controls[] = {
597*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("DAC Surr Playback Volume",
598*4882a593Smuzhiyun RT711_SET_GAIN_DAC2_H, RT711_SET_GAIN_DAC2_L,
599*4882a593Smuzhiyun RT711_DIR_OUT_SFT, 0x57, 0,
600*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, out_vol_tlv),
601*4882a593Smuzhiyun SOC_DOUBLE_R_EXT("ADC 08 Capture Switch",
602*4882a593Smuzhiyun RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
603*4882a593Smuzhiyun RT711_DIR_IN_SFT, 1, 1,
604*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put),
605*4882a593Smuzhiyun SOC_DOUBLE_R_EXT("ADC 09 Capture Switch",
606*4882a593Smuzhiyun RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
607*4882a593Smuzhiyun RT711_DIR_IN_SFT, 1, 1,
608*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put),
609*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume",
610*4882a593Smuzhiyun RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
611*4882a593Smuzhiyun RT711_DIR_IN_SFT, 0x3f, 0,
612*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
613*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume",
614*4882a593Smuzhiyun RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
615*4882a593Smuzhiyun RT711_DIR_IN_SFT, 0x3f, 0,
616*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
617*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("AMIC Volume",
618*4882a593Smuzhiyun RT711_SET_GAIN_AMIC_H, RT711_SET_GAIN_AMIC_L,
619*4882a593Smuzhiyun RT711_DIR_IN_SFT, 3, 0,
620*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
621*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("DMIC1 Volume",
622*4882a593Smuzhiyun RT711_SET_GAIN_DMIC1_H, RT711_SET_GAIN_DMIC1_L,
623*4882a593Smuzhiyun RT711_DIR_IN_SFT, 3, 0,
624*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
625*4882a593Smuzhiyun SOC_DOUBLE_R_EXT_TLV("DMIC2 Volume",
626*4882a593Smuzhiyun RT711_SET_GAIN_DMIC2_H, RT711_SET_GAIN_DMIC2_L,
627*4882a593Smuzhiyun RT711_DIR_IN_SFT, 3, 0,
628*4882a593Smuzhiyun rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
629*4882a593Smuzhiyun };
630*4882a593Smuzhiyun
rt711_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)631*4882a593Smuzhiyun static int rt711_mux_get(struct snd_kcontrol *kcontrol,
632*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun struct snd_soc_component *component =
635*4882a593Smuzhiyun snd_soc_dapm_kcontrol_component(kcontrol);
636*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
637*4882a593Smuzhiyun unsigned int reg, val = 0, nid;
638*4882a593Smuzhiyun int ret;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun if (strstr(ucontrol->id.name, "ADC 22 Mux"))
641*4882a593Smuzhiyun nid = RT711_MIXER_IN1;
642*4882a593Smuzhiyun else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
643*4882a593Smuzhiyun nid = RT711_MIXER_IN2;
644*4882a593Smuzhiyun else
645*4882a593Smuzhiyun return -EINVAL;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun /* vid = 0xf01 */
648*4882a593Smuzhiyun reg = RT711_VERB_SET_CONNECT_SEL | nid;
649*4882a593Smuzhiyun ret = regmap_read(rt711->regmap, reg, &val);
650*4882a593Smuzhiyun if (ret < 0) {
651*4882a593Smuzhiyun dev_err(component->dev, "%s: sdw read failed: %d\n",
652*4882a593Smuzhiyun __func__, ret);
653*4882a593Smuzhiyun return ret;
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun ucontrol->value.enumerated.item[0] = val;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun return 0;
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun
rt711_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)661*4882a593Smuzhiyun static int rt711_mux_put(struct snd_kcontrol *kcontrol,
662*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun struct snd_soc_component *component =
665*4882a593Smuzhiyun snd_soc_dapm_kcontrol_component(kcontrol);
666*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm =
667*4882a593Smuzhiyun snd_soc_dapm_kcontrol_dapm(kcontrol);
668*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
669*4882a593Smuzhiyun struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
670*4882a593Smuzhiyun unsigned int *item = ucontrol->value.enumerated.item;
671*4882a593Smuzhiyun unsigned int val, val2 = 0, change, reg, nid;
672*4882a593Smuzhiyun int ret;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if (item[0] >= e->items)
675*4882a593Smuzhiyun return -EINVAL;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun if (strstr(ucontrol->id.name, "ADC 22 Mux"))
678*4882a593Smuzhiyun nid = RT711_MIXER_IN1;
679*4882a593Smuzhiyun else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
680*4882a593Smuzhiyun nid = RT711_MIXER_IN2;
681*4882a593Smuzhiyun else
682*4882a593Smuzhiyun return -EINVAL;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /* Verb ID = 0x701h */
685*4882a593Smuzhiyun val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun reg = RT711_VERB_SET_CONNECT_SEL | nid;
688*4882a593Smuzhiyun ret = regmap_read(rt711->regmap, reg, &val2);
689*4882a593Smuzhiyun if (ret < 0) {
690*4882a593Smuzhiyun dev_err(component->dev, "%s: sdw read failed: %d\n",
691*4882a593Smuzhiyun __func__, ret);
692*4882a593Smuzhiyun return ret;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun if (val == val2)
696*4882a593Smuzhiyun change = 0;
697*4882a593Smuzhiyun else
698*4882a593Smuzhiyun change = 1;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (change) {
701*4882a593Smuzhiyun reg = RT711_VERB_SET_CONNECT_SEL | nid;
702*4882a593Smuzhiyun regmap_write(rt711->regmap, reg, val);
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun snd_soc_dapm_mux_update_power(dapm, kcontrol,
706*4882a593Smuzhiyun item[0], e, NULL);
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun return change;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun static const char * const adc_mux_text[] = {
712*4882a593Smuzhiyun "MIC2",
713*4882a593Smuzhiyun "LINE1",
714*4882a593Smuzhiyun "LINE2",
715*4882a593Smuzhiyun "DMIC",
716*4882a593Smuzhiyun };
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(
719*4882a593Smuzhiyun rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(
722*4882a593Smuzhiyun rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text);
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun static const struct snd_kcontrol_new rt711_adc22_mux =
725*4882a593Smuzhiyun SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt711_adc22_enum,
726*4882a593Smuzhiyun rt711_mux_get, rt711_mux_put);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun static const struct snd_kcontrol_new rt711_adc23_mux =
729*4882a593Smuzhiyun SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt711_adc23_enum,
730*4882a593Smuzhiyun rt711_mux_get, rt711_mux_put);
731*4882a593Smuzhiyun
rt711_dac_surround_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)732*4882a593Smuzhiyun static int rt711_dac_surround_event(struct snd_soc_dapm_widget *w,
733*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
734*4882a593Smuzhiyun {
735*4882a593Smuzhiyun struct snd_soc_component *component =
736*4882a593Smuzhiyun snd_soc_dapm_to_component(w->dapm);
737*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
738*4882a593Smuzhiyun unsigned int val_h = (1 << RT711_DIR_OUT_SFT) | (0x3 << 4);
739*4882a593Smuzhiyun unsigned int val_l;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun switch (event) {
742*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
743*4882a593Smuzhiyun regmap_write(rt711->regmap,
744*4882a593Smuzhiyun RT711_SET_STREAMID_DAC2, 0x10);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun val_l = 0x00;
747*4882a593Smuzhiyun regmap_write(rt711->regmap,
748*4882a593Smuzhiyun RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
749*4882a593Smuzhiyun break;
750*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMD:
751*4882a593Smuzhiyun val_l = (1 << RT711_MUTE_SFT);
752*4882a593Smuzhiyun regmap_write(rt711->regmap,
753*4882a593Smuzhiyun RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
754*4882a593Smuzhiyun usleep_range(50000, 55000);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun regmap_write(rt711->regmap,
757*4882a593Smuzhiyun RT711_SET_STREAMID_DAC2, 0x00);
758*4882a593Smuzhiyun break;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun return 0;
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun
rt711_adc_09_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)763*4882a593Smuzhiyun static int rt711_adc_09_event(struct snd_soc_dapm_widget *w,
764*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun struct snd_soc_component *component =
767*4882a593Smuzhiyun snd_soc_dapm_to_component(w->dapm);
768*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun switch (event) {
771*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
772*4882a593Smuzhiyun regmap_write(rt711->regmap,
773*4882a593Smuzhiyun RT711_SET_STREAMID_ADC1, 0x10);
774*4882a593Smuzhiyun break;
775*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMD:
776*4882a593Smuzhiyun regmap_write(rt711->regmap,
777*4882a593Smuzhiyun RT711_SET_STREAMID_ADC1, 0x00);
778*4882a593Smuzhiyun break;
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun return 0;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun
rt711_adc_08_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)783*4882a593Smuzhiyun static int rt711_adc_08_event(struct snd_soc_dapm_widget *w,
784*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun struct snd_soc_component *component =
787*4882a593Smuzhiyun snd_soc_dapm_to_component(w->dapm);
788*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun switch (event) {
791*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
792*4882a593Smuzhiyun regmap_write(rt711->regmap,
793*4882a593Smuzhiyun RT711_SET_STREAMID_ADC2, 0x10);
794*4882a593Smuzhiyun break;
795*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMD:
796*4882a593Smuzhiyun regmap_write(rt711->regmap,
797*4882a593Smuzhiyun RT711_SET_STREAMID_ADC2, 0x00);
798*4882a593Smuzhiyun break;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun return 0;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun static const struct snd_soc_dapm_widget rt711_dapm_widgets[] = {
804*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("HP"),
805*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("MIC2"),
806*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("DMIC1"),
807*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("DMIC2"),
808*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("LINE1"),
809*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("LINE2"),
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun SND_SOC_DAPM_DAC_E("DAC Surround", NULL, SND_SOC_NOPM, 0, 0,
812*4882a593Smuzhiyun rt711_dac_surround_event,
813*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
814*4882a593Smuzhiyun SND_SOC_DAPM_ADC_E("ADC 09", NULL, SND_SOC_NOPM, 0, 0,
815*4882a593Smuzhiyun rt711_adc_09_event,
816*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
817*4882a593Smuzhiyun SND_SOC_DAPM_ADC_E("ADC 08", NULL, SND_SOC_NOPM, 0, 0,
818*4882a593Smuzhiyun rt711_adc_08_event,
819*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
820*4882a593Smuzhiyun SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0,
821*4882a593Smuzhiyun &rt711_adc22_mux),
822*4882a593Smuzhiyun SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0,
823*4882a593Smuzhiyun &rt711_adc23_mux),
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0),
826*4882a593Smuzhiyun SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0),
827*4882a593Smuzhiyun SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
828*4882a593Smuzhiyun };
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun static const struct snd_soc_dapm_route rt711_audio_map[] = {
831*4882a593Smuzhiyun {"DAC Surround", NULL, "DP3RX"},
832*4882a593Smuzhiyun {"DP2TX", NULL, "ADC 09"},
833*4882a593Smuzhiyun {"DP4TX", NULL, "ADC 08"},
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun {"ADC 09", NULL, "ADC 22 Mux"},
836*4882a593Smuzhiyun {"ADC 08", NULL, "ADC 23 Mux"},
837*4882a593Smuzhiyun {"ADC 22 Mux", "DMIC", "DMIC1"},
838*4882a593Smuzhiyun {"ADC 22 Mux", "LINE1", "LINE1"},
839*4882a593Smuzhiyun {"ADC 22 Mux", "LINE2", "LINE2"},
840*4882a593Smuzhiyun {"ADC 22 Mux", "MIC2", "MIC2"},
841*4882a593Smuzhiyun {"ADC 23 Mux", "DMIC", "DMIC2"},
842*4882a593Smuzhiyun {"ADC 23 Mux", "LINE1", "LINE1"},
843*4882a593Smuzhiyun {"ADC 23 Mux", "LINE2", "LINE2"},
844*4882a593Smuzhiyun {"ADC 23 Mux", "MIC2", "MIC2"},
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun {"HP", NULL, "DAC Surround"},
847*4882a593Smuzhiyun };
848*4882a593Smuzhiyun
rt711_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)849*4882a593Smuzhiyun static int rt711_set_bias_level(struct snd_soc_component *component,
850*4882a593Smuzhiyun enum snd_soc_bias_level level)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm =
853*4882a593Smuzhiyun snd_soc_component_get_dapm(component);
854*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun switch (level) {
857*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
858*4882a593Smuzhiyun if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
859*4882a593Smuzhiyun regmap_write(rt711->regmap,
860*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE,
861*4882a593Smuzhiyun AC_PWRST_D0);
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun break;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
866*4882a593Smuzhiyun mutex_lock(&rt711->calibrate_mutex);
867*4882a593Smuzhiyun regmap_write(rt711->regmap,
868*4882a593Smuzhiyun RT711_SET_AUDIO_POWER_STATE,
869*4882a593Smuzhiyun AC_PWRST_D3);
870*4882a593Smuzhiyun mutex_unlock(&rt711->calibrate_mutex);
871*4882a593Smuzhiyun break;
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun default:
874*4882a593Smuzhiyun break;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun return 0;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun
rt711_parse_dt(struct rt711_priv * rt711,struct device * dev)880*4882a593Smuzhiyun static int rt711_parse_dt(struct rt711_priv *rt711, struct device *dev)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun device_property_read_u32(dev, "realtek,jd-src",
883*4882a593Smuzhiyun &rt711->jd_src);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun return 0;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun
rt711_probe(struct snd_soc_component * component)888*4882a593Smuzhiyun static int rt711_probe(struct snd_soc_component *component)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun rt711_parse_dt(rt711, &rt711->slave->dev);
893*4882a593Smuzhiyun rt711->component = component;
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
rt711_remove(struct snd_soc_component * component)898*4882a593Smuzhiyun static void rt711_remove(struct snd_soc_component *component)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun regcache_cache_only(rt711->regmap, true);
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
906*4882a593Smuzhiyun .probe = rt711_probe,
907*4882a593Smuzhiyun .set_bias_level = rt711_set_bias_level,
908*4882a593Smuzhiyun .controls = rt711_snd_controls,
909*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(rt711_snd_controls),
910*4882a593Smuzhiyun .dapm_widgets = rt711_dapm_widgets,
911*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(rt711_dapm_widgets),
912*4882a593Smuzhiyun .dapm_routes = rt711_audio_map,
913*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
914*4882a593Smuzhiyun .set_jack = rt711_set_jack_detect,
915*4882a593Smuzhiyun .remove = rt711_remove,
916*4882a593Smuzhiyun };
917*4882a593Smuzhiyun
rt711_set_sdw_stream(struct snd_soc_dai * dai,void * sdw_stream,int direction)918*4882a593Smuzhiyun static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
919*4882a593Smuzhiyun int direction)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun struct sdw_stream_data *stream;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun if (!sdw_stream)
924*4882a593Smuzhiyun return 0;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun stream = kzalloc(sizeof(*stream), GFP_KERNEL);
927*4882a593Smuzhiyun if (!stream)
928*4882a593Smuzhiyun return -ENOMEM;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
933*4882a593Smuzhiyun if (direction == SNDRV_PCM_STREAM_PLAYBACK)
934*4882a593Smuzhiyun dai->playback_dma_data = stream;
935*4882a593Smuzhiyun else
936*4882a593Smuzhiyun dai->capture_dma_data = stream;
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun return 0;
939*4882a593Smuzhiyun }
940*4882a593Smuzhiyun
rt711_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)941*4882a593Smuzhiyun static void rt711_shutdown(struct snd_pcm_substream *substream,
942*4882a593Smuzhiyun struct snd_soc_dai *dai)
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun struct sdw_stream_data *stream;
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun stream = snd_soc_dai_get_dma_data(dai, substream);
947*4882a593Smuzhiyun snd_soc_dai_set_dma_data(dai, substream, NULL);
948*4882a593Smuzhiyun kfree(stream);
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun
rt711_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)951*4882a593Smuzhiyun static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
952*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
953*4882a593Smuzhiyun struct snd_soc_dai *dai)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
956*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
957*4882a593Smuzhiyun struct sdw_stream_config stream_config;
958*4882a593Smuzhiyun struct sdw_port_config port_config;
959*4882a593Smuzhiyun enum sdw_data_direction direction;
960*4882a593Smuzhiyun struct sdw_stream_data *stream;
961*4882a593Smuzhiyun int retval, port, num_channels;
962*4882a593Smuzhiyun unsigned int val = 0;
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun dev_dbg(dai->dev, "%s %s", __func__, dai->name);
965*4882a593Smuzhiyun stream = snd_soc_dai_get_dma_data(dai, substream);
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun if (!stream)
968*4882a593Smuzhiyun return -EINVAL;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun if (!rt711->slave)
971*4882a593Smuzhiyun return -EINVAL;
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun /* SoundWire specific configuration */
974*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
975*4882a593Smuzhiyun direction = SDW_DATA_DIR_RX;
976*4882a593Smuzhiyun port = 3;
977*4882a593Smuzhiyun } else {
978*4882a593Smuzhiyun direction = SDW_DATA_DIR_TX;
979*4882a593Smuzhiyun if (dai->id == RT711_AIF1)
980*4882a593Smuzhiyun port = 4;
981*4882a593Smuzhiyun else if (dai->id == RT711_AIF2)
982*4882a593Smuzhiyun port = 2;
983*4882a593Smuzhiyun else
984*4882a593Smuzhiyun return -EINVAL;
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun stream_config.frame_rate = params_rate(params);
988*4882a593Smuzhiyun stream_config.ch_count = params_channels(params);
989*4882a593Smuzhiyun stream_config.bps = snd_pcm_format_width(params_format(params));
990*4882a593Smuzhiyun stream_config.direction = direction;
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun num_channels = params_channels(params);
993*4882a593Smuzhiyun port_config.ch_mask = (1 << (num_channels)) - 1;
994*4882a593Smuzhiyun port_config.num = port;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun retval = sdw_stream_add_slave(rt711->slave, &stream_config,
997*4882a593Smuzhiyun &port_config, 1, stream->sdw_stream);
998*4882a593Smuzhiyun if (retval) {
999*4882a593Smuzhiyun dev_err(dai->dev, "Unable to configure port\n");
1000*4882a593Smuzhiyun return retval;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun if (params_channels(params) <= 16) {
1004*4882a593Smuzhiyun /* bit 3:0 Number of Channel */
1005*4882a593Smuzhiyun val |= (params_channels(params) - 1);
1006*4882a593Smuzhiyun } else {
1007*4882a593Smuzhiyun dev_err(component->dev, "Unsupported channels %d\n",
1008*4882a593Smuzhiyun params_channels(params));
1009*4882a593Smuzhiyun return -EINVAL;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun switch (params_width(params)) {
1013*4882a593Smuzhiyun /* bit 6:4 Bits per Sample */
1014*4882a593Smuzhiyun case 8:
1015*4882a593Smuzhiyun break;
1016*4882a593Smuzhiyun case 16:
1017*4882a593Smuzhiyun val |= (0x1 << 4);
1018*4882a593Smuzhiyun break;
1019*4882a593Smuzhiyun case 20:
1020*4882a593Smuzhiyun val |= (0x2 << 4);
1021*4882a593Smuzhiyun break;
1022*4882a593Smuzhiyun case 24:
1023*4882a593Smuzhiyun val |= (0x3 << 4);
1024*4882a593Smuzhiyun break;
1025*4882a593Smuzhiyun case 32:
1026*4882a593Smuzhiyun val |= (0x4 << 4);
1027*4882a593Smuzhiyun break;
1028*4882a593Smuzhiyun default:
1029*4882a593Smuzhiyun return -EINVAL;
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun /* 48Khz */
1033*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_DAC_FORMAT_H, val);
1034*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_ADC1_FORMAT_H, val);
1035*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_ADC2_FORMAT_H, val);
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun return retval;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun
rt711_pcm_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1040*4882a593Smuzhiyun static int rt711_pcm_hw_free(struct snd_pcm_substream *substream,
1041*4882a593Smuzhiyun struct snd_soc_dai *dai)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1044*4882a593Smuzhiyun struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
1045*4882a593Smuzhiyun struct sdw_stream_data *stream =
1046*4882a593Smuzhiyun snd_soc_dai_get_dma_data(dai, substream);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun if (!rt711->slave)
1049*4882a593Smuzhiyun return -EINVAL;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun sdw_stream_remove_slave(rt711->slave, stream->sdw_stream);
1052*4882a593Smuzhiyun return 0;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun #define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
1056*4882a593Smuzhiyun #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1057*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun static struct snd_soc_dai_ops rt711_ops = {
1060*4882a593Smuzhiyun .hw_params = rt711_pcm_hw_params,
1061*4882a593Smuzhiyun .hw_free = rt711_pcm_hw_free,
1062*4882a593Smuzhiyun .set_sdw_stream = rt711_set_sdw_stream,
1063*4882a593Smuzhiyun .shutdown = rt711_shutdown,
1064*4882a593Smuzhiyun };
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun static struct snd_soc_dai_driver rt711_dai[] = {
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun .name = "rt711-aif1",
1069*4882a593Smuzhiyun .id = RT711_AIF1,
1070*4882a593Smuzhiyun .playback = {
1071*4882a593Smuzhiyun .stream_name = "DP3 Playback",
1072*4882a593Smuzhiyun .channels_min = 1,
1073*4882a593Smuzhiyun .channels_max = 2,
1074*4882a593Smuzhiyun .rates = RT711_STEREO_RATES,
1075*4882a593Smuzhiyun .formats = RT711_FORMATS,
1076*4882a593Smuzhiyun },
1077*4882a593Smuzhiyun .capture = {
1078*4882a593Smuzhiyun .stream_name = "DP4 Capture",
1079*4882a593Smuzhiyun .channels_min = 1,
1080*4882a593Smuzhiyun .channels_max = 2,
1081*4882a593Smuzhiyun .rates = RT711_STEREO_RATES,
1082*4882a593Smuzhiyun .formats = RT711_FORMATS,
1083*4882a593Smuzhiyun },
1084*4882a593Smuzhiyun .ops = &rt711_ops,
1085*4882a593Smuzhiyun },
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun .name = "rt711-aif2",
1088*4882a593Smuzhiyun .id = RT711_AIF2,
1089*4882a593Smuzhiyun .capture = {
1090*4882a593Smuzhiyun .stream_name = "DP2 Capture",
1091*4882a593Smuzhiyun .channels_min = 1,
1092*4882a593Smuzhiyun .channels_max = 2,
1093*4882a593Smuzhiyun .rates = RT711_STEREO_RATES,
1094*4882a593Smuzhiyun .formats = RT711_FORMATS,
1095*4882a593Smuzhiyun },
1096*4882a593Smuzhiyun .ops = &rt711_ops,
1097*4882a593Smuzhiyun }
1098*4882a593Smuzhiyun };
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun /* Bus clock frequency */
1101*4882a593Smuzhiyun #define RT711_CLK_FREQ_9600000HZ 9600000
1102*4882a593Smuzhiyun #define RT711_CLK_FREQ_12000000HZ 12000000
1103*4882a593Smuzhiyun #define RT711_CLK_FREQ_6000000HZ 6000000
1104*4882a593Smuzhiyun #define RT711_CLK_FREQ_4800000HZ 4800000
1105*4882a593Smuzhiyun #define RT711_CLK_FREQ_2400000HZ 2400000
1106*4882a593Smuzhiyun #define RT711_CLK_FREQ_12288000HZ 12288000
1107*4882a593Smuzhiyun
rt711_clock_config(struct device * dev)1108*4882a593Smuzhiyun int rt711_clock_config(struct device *dev)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun struct rt711_priv *rt711 = dev_get_drvdata(dev);
1111*4882a593Smuzhiyun unsigned int clk_freq, value;
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun clk_freq = (rt711->params.curr_dr_freq >> 1);
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun switch (clk_freq) {
1116*4882a593Smuzhiyun case RT711_CLK_FREQ_12000000HZ:
1117*4882a593Smuzhiyun value = 0x0;
1118*4882a593Smuzhiyun break;
1119*4882a593Smuzhiyun case RT711_CLK_FREQ_6000000HZ:
1120*4882a593Smuzhiyun value = 0x1;
1121*4882a593Smuzhiyun break;
1122*4882a593Smuzhiyun case RT711_CLK_FREQ_9600000HZ:
1123*4882a593Smuzhiyun value = 0x2;
1124*4882a593Smuzhiyun break;
1125*4882a593Smuzhiyun case RT711_CLK_FREQ_4800000HZ:
1126*4882a593Smuzhiyun value = 0x3;
1127*4882a593Smuzhiyun break;
1128*4882a593Smuzhiyun case RT711_CLK_FREQ_2400000HZ:
1129*4882a593Smuzhiyun value = 0x4;
1130*4882a593Smuzhiyun break;
1131*4882a593Smuzhiyun case RT711_CLK_FREQ_12288000HZ:
1132*4882a593Smuzhiyun value = 0x5;
1133*4882a593Smuzhiyun break;
1134*4882a593Smuzhiyun default:
1135*4882a593Smuzhiyun return -EINVAL;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun regmap_write(rt711->regmap, 0xe0, value);
1139*4882a593Smuzhiyun regmap_write(rt711->regmap, 0xf0, value);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun return 0;
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun
rt711_calibration_work(struct work_struct * work)1146*4882a593Smuzhiyun static void rt711_calibration_work(struct work_struct *work)
1147*4882a593Smuzhiyun {
1148*4882a593Smuzhiyun struct rt711_priv *rt711 =
1149*4882a593Smuzhiyun container_of(work, struct rt711_priv, calibration_work);
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun rt711_calibration(rt711);
1152*4882a593Smuzhiyun }
1153*4882a593Smuzhiyun
rt711_init(struct device * dev,struct regmap * sdw_regmap,struct regmap * regmap,struct sdw_slave * slave)1154*4882a593Smuzhiyun int rt711_init(struct device *dev, struct regmap *sdw_regmap,
1155*4882a593Smuzhiyun struct regmap *regmap, struct sdw_slave *slave)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun struct rt711_priv *rt711;
1158*4882a593Smuzhiyun int ret;
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun rt711 = devm_kzalloc(dev, sizeof(*rt711), GFP_KERNEL);
1161*4882a593Smuzhiyun if (!rt711)
1162*4882a593Smuzhiyun return -ENOMEM;
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun dev_set_drvdata(dev, rt711);
1165*4882a593Smuzhiyun rt711->slave = slave;
1166*4882a593Smuzhiyun rt711->sdw_regmap = sdw_regmap;
1167*4882a593Smuzhiyun rt711->regmap = regmap;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun /*
1170*4882a593Smuzhiyun * Mark hw_init to false
1171*4882a593Smuzhiyun * HW init will be performed when device reports present
1172*4882a593Smuzhiyun */
1173*4882a593Smuzhiyun rt711->hw_init = false;
1174*4882a593Smuzhiyun rt711->first_hw_init = false;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun /* JD source uses JD2 in default */
1177*4882a593Smuzhiyun rt711->jd_src = RT711_JD2;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun ret = devm_snd_soc_register_component(dev,
1180*4882a593Smuzhiyun &soc_codec_dev_rt711,
1181*4882a593Smuzhiyun rt711_dai,
1182*4882a593Smuzhiyun ARRAY_SIZE(rt711_dai));
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun dev_dbg(&slave->dev, "%s\n", __func__);
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun return ret;
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun
rt711_io_init(struct device * dev,struct sdw_slave * slave)1189*4882a593Smuzhiyun int rt711_io_init(struct device *dev, struct sdw_slave *slave)
1190*4882a593Smuzhiyun {
1191*4882a593Smuzhiyun struct rt711_priv *rt711 = dev_get_drvdata(dev);
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun if (rt711->hw_init)
1194*4882a593Smuzhiyun return 0;
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun if (rt711->first_hw_init) {
1197*4882a593Smuzhiyun regcache_cache_only(rt711->regmap, false);
1198*4882a593Smuzhiyun regcache_cache_bypass(rt711->regmap, true);
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun /*
1202*4882a593Smuzhiyun * PM runtime is only enabled when a Slave reports as Attached
1203*4882a593Smuzhiyun */
1204*4882a593Smuzhiyun if (!rt711->first_hw_init) {
1205*4882a593Smuzhiyun /* set autosuspend parameters */
1206*4882a593Smuzhiyun pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
1207*4882a593Smuzhiyun pm_runtime_use_autosuspend(&slave->dev);
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun /* update count of parent 'active' children */
1210*4882a593Smuzhiyun pm_runtime_set_active(&slave->dev);
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun /* make sure the device does not suspend immediately */
1213*4882a593Smuzhiyun pm_runtime_mark_last_busy(&slave->dev);
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun pm_runtime_enable(&slave->dev);
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun pm_runtime_get_noresume(&slave->dev);
1219*4882a593Smuzhiyun
1220*4882a593Smuzhiyun rt711_reset(rt711->regmap);
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun /* power on */
1223*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun /* Set Pin Widget */
1226*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_MIC2, 0x25);
1227*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_HP, 0xc0);
1228*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_DMIC1, 0x20);
1229*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_DMIC2, 0x20);
1230*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_LINE1, 0x20);
1231*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_PIN_LINE2, 0x20);
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun /* Mute HP/ADC1/ADC2 */
1234*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0xa080);
1235*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0x9080);
1236*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x6080);
1237*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x5080);
1238*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x6080);
1239*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x5080);
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun /* Set Configuration Default */
1242*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4f12, 0x91);
1243*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4e12, 0xd6);
1244*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4d12, 0x11);
1245*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4c12, 0x20);
1246*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4f13, 0x91);
1247*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4e13, 0xd6);
1248*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4d13, 0x11);
1249*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4c13, 0x21);
1250*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4c21, 0xf0);
1251*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4d21, 0x11);
1252*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4e21, 0x11);
1253*4882a593Smuzhiyun regmap_write(rt711->regmap, 0x4f21, 0x01);
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun /* Data port arrangement */
1256*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1257*4882a593Smuzhiyun RT711_TX_RX_MUX_CTL, 0x0154);
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun /* Set index */
1260*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1261*4882a593Smuzhiyun RT711_DIGITAL_MISC_CTRL4, 0x201b);
1262*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1263*4882a593Smuzhiyun RT711_COMBO_JACK_AUTO_CTL1, 0x5089);
1264*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1265*4882a593Smuzhiyun RT711_VREFOUT_CTL, 0x5064);
1266*4882a593Smuzhiyun rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1267*4882a593Smuzhiyun RT711_INLINE_CMD_CTL, 0xd249);
1268*4882a593Smuzhiyun
1269*4882a593Smuzhiyun /* Finish Initial Settings, set power to D3 */
1270*4882a593Smuzhiyun regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun if (rt711->first_hw_init)
1273*4882a593Smuzhiyun rt711_calibration(rt711);
1274*4882a593Smuzhiyun else {
1275*4882a593Smuzhiyun INIT_DELAYED_WORK(&rt711->jack_detect_work,
1276*4882a593Smuzhiyun rt711_jack_detect_handler);
1277*4882a593Smuzhiyun INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
1278*4882a593Smuzhiyun rt711_btn_check_handler);
1279*4882a593Smuzhiyun mutex_init(&rt711->calibrate_mutex);
1280*4882a593Smuzhiyun INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
1281*4882a593Smuzhiyun schedule_work(&rt711->calibration_work);
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun /*
1285*4882a593Smuzhiyun * if set_jack callback occurred early than io_init,
1286*4882a593Smuzhiyun * we set up the jack detection function now
1287*4882a593Smuzhiyun */
1288*4882a593Smuzhiyun if (rt711->hs_jack)
1289*4882a593Smuzhiyun rt711_jack_init(rt711);
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun if (rt711->first_hw_init) {
1292*4882a593Smuzhiyun regcache_cache_bypass(rt711->regmap, false);
1293*4882a593Smuzhiyun regcache_mark_dirty(rt711->regmap);
1294*4882a593Smuzhiyun } else
1295*4882a593Smuzhiyun rt711->first_hw_init = true;
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun /* Mark Slave initialization complete */
1298*4882a593Smuzhiyun rt711->hw_init = true;
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun pm_runtime_mark_last_busy(&slave->dev);
1301*4882a593Smuzhiyun pm_runtime_put_autosuspend(&slave->dev);
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
1304*4882a593Smuzhiyun return 0;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC RT711 SDW driver");
1308*4882a593Smuzhiyun MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
1309*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1310