1320b8b0dSShuming Fan // SPDX-License-Identifier: GPL-2.0
2320b8b0dSShuming Fan //
3320b8b0dSShuming Fan // rt711.c -- rt711 ALSA SoC audio driver
4320b8b0dSShuming Fan //
5320b8b0dSShuming Fan // Copyright(c) 2019 Realtek Semiconductor Corp.
6320b8b0dSShuming Fan //
7320b8b0dSShuming Fan //
8320b8b0dSShuming Fan
9320b8b0dSShuming Fan #include <linux/module.h>
10320b8b0dSShuming Fan #include <linux/moduleparam.h>
11320b8b0dSShuming Fan #include <linux/kernel.h>
12320b8b0dSShuming Fan #include <linux/init.h>
13320b8b0dSShuming Fan #include <linux/delay.h>
14320b8b0dSShuming Fan #include <linux/pm_runtime.h>
15320b8b0dSShuming Fan #include <linux/pm.h>
16320b8b0dSShuming Fan #include <linux/soundwire/sdw.h>
17320b8b0dSShuming Fan #include <linux/regmap.h>
18320b8b0dSShuming Fan #include <linux/slab.h>
19320b8b0dSShuming Fan #include <sound/core.h>
20320b8b0dSShuming Fan #include <sound/pcm.h>
21320b8b0dSShuming Fan #include <sound/pcm_params.h>
22754bef67SCharles Keepax #include <sound/sdw.h>
23320b8b0dSShuming Fan #include <sound/soc.h>
24320b8b0dSShuming Fan #include <sound/soc-dapm.h>
25320b8b0dSShuming Fan #include <sound/initval.h>
26320b8b0dSShuming Fan #include <sound/tlv.h>
27320b8b0dSShuming Fan #include <sound/hda_verbs.h>
28320b8b0dSShuming Fan #include <sound/jack.h>
29320b8b0dSShuming Fan
30320b8b0dSShuming Fan #include "rt711.h"
31320b8b0dSShuming Fan
rt711_index_write(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int value)32320b8b0dSShuming Fan static int rt711_index_write(struct regmap *regmap,
33320b8b0dSShuming Fan unsigned int nid, unsigned int reg, unsigned int value)
34320b8b0dSShuming Fan {
35320b8b0dSShuming Fan int ret;
36320b8b0dSShuming Fan unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
37320b8b0dSShuming Fan
38320b8b0dSShuming Fan ret = regmap_write(regmap, addr, value);
39320b8b0dSShuming Fan if (ret < 0)
40320b8b0dSShuming Fan pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
41320b8b0dSShuming Fan addr, value, ret);
42320b8b0dSShuming Fan
43320b8b0dSShuming Fan return ret;
44320b8b0dSShuming Fan }
45320b8b0dSShuming Fan
rt711_index_read(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int * value)46320b8b0dSShuming Fan static int rt711_index_read(struct regmap *regmap,
47320b8b0dSShuming Fan unsigned int nid, unsigned int reg, unsigned int *value)
48320b8b0dSShuming Fan {
49320b8b0dSShuming Fan int ret;
50320b8b0dSShuming Fan unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
51320b8b0dSShuming Fan
52320b8b0dSShuming Fan *value = 0;
53320b8b0dSShuming Fan ret = regmap_read(regmap, addr, value);
54320b8b0dSShuming Fan if (ret < 0)
55320b8b0dSShuming Fan pr_err("Failed to get private value: %06x => %04x ret=%d\n",
56320b8b0dSShuming Fan addr, *value, ret);
57320b8b0dSShuming Fan
58320b8b0dSShuming Fan return ret;
59320b8b0dSShuming Fan }
60320b8b0dSShuming Fan
rt711_index_update_bits(struct regmap * regmap,unsigned int nid,unsigned int reg,unsigned int mask,unsigned int val)61320b8b0dSShuming Fan static int rt711_index_update_bits(struct regmap *regmap, unsigned int nid,
62320b8b0dSShuming Fan unsigned int reg, unsigned int mask, unsigned int val)
63320b8b0dSShuming Fan {
64320b8b0dSShuming Fan unsigned int tmp, orig;
65320b8b0dSShuming Fan int ret;
66320b8b0dSShuming Fan
67320b8b0dSShuming Fan ret = rt711_index_read(regmap, nid, reg, &orig);
68320b8b0dSShuming Fan if (ret < 0)
69320b8b0dSShuming Fan return ret;
70320b8b0dSShuming Fan
71320b8b0dSShuming Fan tmp = orig & ~mask;
72320b8b0dSShuming Fan tmp |= val & mask;
73320b8b0dSShuming Fan
74320b8b0dSShuming Fan return rt711_index_write(regmap, nid, reg, tmp);
75320b8b0dSShuming Fan }
76320b8b0dSShuming Fan
rt711_reset(struct regmap * regmap)77320b8b0dSShuming Fan static void rt711_reset(struct regmap *regmap)
78320b8b0dSShuming Fan {
79320b8b0dSShuming Fan regmap_write(regmap, RT711_FUNC_RESET, 0);
80320b8b0dSShuming Fan rt711_index_update_bits(regmap, RT711_VENDOR_REG,
81320b8b0dSShuming Fan RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET,
82320b8b0dSShuming Fan RT711_HIDDEN_REG_SW_RESET);
83320b8b0dSShuming Fan }
84320b8b0dSShuming Fan
rt711_calibration(struct rt711_priv * rt711)85320b8b0dSShuming Fan static int rt711_calibration(struct rt711_priv *rt711)
86320b8b0dSShuming Fan {
87320b8b0dSShuming Fan unsigned int val, loop = 0;
88320b8b0dSShuming Fan struct device *dev;
89320b8b0dSShuming Fan struct regmap *regmap = rt711->regmap;
90320b8b0dSShuming Fan int ret = 0;
91320b8b0dSShuming Fan
92320b8b0dSShuming Fan mutex_lock(&rt711->calibrate_mutex);
93320b8b0dSShuming Fan regmap_write(rt711->regmap,
94320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
95320b8b0dSShuming Fan
96320b8b0dSShuming Fan dev = regmap_get_device(regmap);
97320b8b0dSShuming Fan
98320b8b0dSShuming Fan /* Calibration manual mode */
99320b8b0dSShuming Fan rt711_index_update_bits(regmap, RT711_VENDOR_REG, RT711_FSM_CTL,
100320b8b0dSShuming Fan 0xf, 0x0);
101320b8b0dSShuming Fan
102320b8b0dSShuming Fan /* trigger */
103320b8b0dSShuming Fan rt711_index_update_bits(regmap, RT711_VENDOR_CALI,
104320b8b0dSShuming Fan RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER,
105320b8b0dSShuming Fan RT711_DAC_DC_CALI_TRIGGER);
106320b8b0dSShuming Fan
107320b8b0dSShuming Fan /* wait for calibration process */
108320b8b0dSShuming Fan rt711_index_read(regmap, RT711_VENDOR_CALI,
109320b8b0dSShuming Fan RT711_DAC_DC_CALI_CTL1, &val);
110320b8b0dSShuming Fan
111320b8b0dSShuming Fan while (val & RT711_DAC_DC_CALI_TRIGGER) {
112320b8b0dSShuming Fan if (loop >= 500) {
113320b8b0dSShuming Fan pr_err("%s, calibration time-out!\n",
114320b8b0dSShuming Fan __func__);
115320b8b0dSShuming Fan ret = -ETIMEDOUT;
116320b8b0dSShuming Fan break;
117320b8b0dSShuming Fan }
118320b8b0dSShuming Fan loop++;
119320b8b0dSShuming Fan
120320b8b0dSShuming Fan usleep_range(10000, 11000);
121320b8b0dSShuming Fan rt711_index_read(regmap, RT711_VENDOR_CALI,
122320b8b0dSShuming Fan RT711_DAC_DC_CALI_CTL1, &val);
123320b8b0dSShuming Fan }
124320b8b0dSShuming Fan
125320b8b0dSShuming Fan /* depop mode */
126320b8b0dSShuming Fan rt711_index_update_bits(regmap, RT711_VENDOR_REG,
127320b8b0dSShuming Fan RT711_FSM_CTL, 0xf, RT711_DEPOP_CTL);
128320b8b0dSShuming Fan
129320b8b0dSShuming Fan regmap_write(rt711->regmap,
130320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
131320b8b0dSShuming Fan mutex_unlock(&rt711->calibrate_mutex);
132320b8b0dSShuming Fan
133320b8b0dSShuming Fan dev_dbg(dev, "%s calibration complete, ret=%d\n", __func__, ret);
134320b8b0dSShuming Fan return ret;
135320b8b0dSShuming Fan }
136320b8b0dSShuming Fan
rt711_button_detect(struct rt711_priv * rt711)137320b8b0dSShuming Fan static unsigned int rt711_button_detect(struct rt711_priv *rt711)
138320b8b0dSShuming Fan {
139320b8b0dSShuming Fan unsigned int btn_type = 0, val80, val81;
140320b8b0dSShuming Fan int ret;
141320b8b0dSShuming Fan
142320b8b0dSShuming Fan ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
143320b8b0dSShuming Fan RT711_IRQ_FLAG_TABLE1, &val80);
144320b8b0dSShuming Fan if (ret < 0)
145320b8b0dSShuming Fan goto read_error;
146320b8b0dSShuming Fan ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
147320b8b0dSShuming Fan RT711_IRQ_FLAG_TABLE2, &val81);
148320b8b0dSShuming Fan if (ret < 0)
149320b8b0dSShuming Fan goto read_error;
150320b8b0dSShuming Fan
151320b8b0dSShuming Fan val80 &= 0x0381;
152320b8b0dSShuming Fan val81 &= 0xff00;
153320b8b0dSShuming Fan
154320b8b0dSShuming Fan switch (val80) {
155320b8b0dSShuming Fan case 0x0200:
156320b8b0dSShuming Fan case 0x0100:
157320b8b0dSShuming Fan case 0x0080:
158320b8b0dSShuming Fan btn_type |= SND_JACK_BTN_0;
159320b8b0dSShuming Fan break;
160320b8b0dSShuming Fan case 0x0001:
161320b8b0dSShuming Fan btn_type |= SND_JACK_BTN_3;
162320b8b0dSShuming Fan break;
163320b8b0dSShuming Fan }
164320b8b0dSShuming Fan switch (val81) {
165320b8b0dSShuming Fan case 0x8000:
166320b8b0dSShuming Fan case 0x4000:
167320b8b0dSShuming Fan case 0x2000:
168320b8b0dSShuming Fan btn_type |= SND_JACK_BTN_1;
169320b8b0dSShuming Fan break;
170320b8b0dSShuming Fan case 0x1000:
171320b8b0dSShuming Fan case 0x0800:
172320b8b0dSShuming Fan case 0x0400:
173320b8b0dSShuming Fan btn_type |= SND_JACK_BTN_2;
174320b8b0dSShuming Fan break;
175320b8b0dSShuming Fan case 0x0200:
176320b8b0dSShuming Fan case 0x0100:
177320b8b0dSShuming Fan btn_type |= SND_JACK_BTN_3;
178320b8b0dSShuming Fan break;
179320b8b0dSShuming Fan }
180320b8b0dSShuming Fan read_error:
181320b8b0dSShuming Fan return btn_type;
182320b8b0dSShuming Fan }
183320b8b0dSShuming Fan
rt711_headset_detect(struct rt711_priv * rt711)184320b8b0dSShuming Fan static int rt711_headset_detect(struct rt711_priv *rt711)
185320b8b0dSShuming Fan {
186320b8b0dSShuming Fan unsigned int buf, loop = 0;
187320b8b0dSShuming Fan int ret;
188320b8b0dSShuming Fan unsigned int jack_status = 0, reg;
189320b8b0dSShuming Fan
190320b8b0dSShuming Fan ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
191320b8b0dSShuming Fan RT711_COMBO_JACK_AUTO_CTL2, &buf);
192320b8b0dSShuming Fan if (ret < 0)
193320b8b0dSShuming Fan goto io_error;
194320b8b0dSShuming Fan
195320b8b0dSShuming Fan while (loop < 500 &&
196320b8b0dSShuming Fan (buf & RT711_COMBOJACK_AUTO_DET_STATUS) == 0) {
197320b8b0dSShuming Fan loop++;
198320b8b0dSShuming Fan
199320b8b0dSShuming Fan usleep_range(9000, 10000);
200320b8b0dSShuming Fan ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
201320b8b0dSShuming Fan RT711_COMBO_JACK_AUTO_CTL2, &buf);
202320b8b0dSShuming Fan if (ret < 0)
203320b8b0dSShuming Fan goto io_error;
204320b8b0dSShuming Fan
205320b8b0dSShuming Fan reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
206320b8b0dSShuming Fan ret = regmap_read(rt711->regmap, reg, &jack_status);
207320b8b0dSShuming Fan if (ret < 0)
208320b8b0dSShuming Fan goto io_error;
209320b8b0dSShuming Fan if ((jack_status & (1 << 31)) == 0)
210320b8b0dSShuming Fan goto remove_error;
211320b8b0dSShuming Fan }
212320b8b0dSShuming Fan
213320b8b0dSShuming Fan if (loop >= 500)
214320b8b0dSShuming Fan goto to_error;
215320b8b0dSShuming Fan
216320b8b0dSShuming Fan if (buf & RT711_COMBOJACK_AUTO_DET_TRS)
217320b8b0dSShuming Fan rt711->jack_type = SND_JACK_HEADPHONE;
218320b8b0dSShuming Fan else if ((buf & RT711_COMBOJACK_AUTO_DET_CTIA) ||
219320b8b0dSShuming Fan (buf & RT711_COMBOJACK_AUTO_DET_OMTP))
220320b8b0dSShuming Fan rt711->jack_type = SND_JACK_HEADSET;
221320b8b0dSShuming Fan
222320b8b0dSShuming Fan return 0;
223320b8b0dSShuming Fan
224320b8b0dSShuming Fan to_error:
225320b8b0dSShuming Fan ret = -ETIMEDOUT;
226320b8b0dSShuming Fan pr_err_ratelimited("Time-out error in %s\n", __func__);
227320b8b0dSShuming Fan return ret;
228320b8b0dSShuming Fan io_error:
229320b8b0dSShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
230320b8b0dSShuming Fan return ret;
231320b8b0dSShuming Fan remove_error:
232320b8b0dSShuming Fan pr_err_ratelimited("Jack removal in %s\n", __func__);
233320b8b0dSShuming Fan return -ENODEV;
234320b8b0dSShuming Fan }
235320b8b0dSShuming Fan
rt711_jack_detect_handler(struct work_struct * work)236320b8b0dSShuming Fan static void rt711_jack_detect_handler(struct work_struct *work)
237320b8b0dSShuming Fan {
238320b8b0dSShuming Fan struct rt711_priv *rt711 =
239320b8b0dSShuming Fan container_of(work, struct rt711_priv, jack_detect_work.work);
240320b8b0dSShuming Fan int btn_type = 0, ret;
241320b8b0dSShuming Fan unsigned int jack_status = 0, reg;
242320b8b0dSShuming Fan
243320b8b0dSShuming Fan if (!rt711->hs_jack)
244320b8b0dSShuming Fan return;
245320b8b0dSShuming Fan
2468ec35236SKuninori Morimoto if (!snd_soc_card_is_instantiated(rt711->component->card))
247320b8b0dSShuming Fan return;
248320b8b0dSShuming Fan
249770f3d99SPierre-Louis Bossart if (pm_runtime_status_suspended(rt711->slave->dev.parent)) {
250770f3d99SPierre-Louis Bossart dev_dbg(&rt711->slave->dev,
251770f3d99SPierre-Louis Bossart "%s: parent device is pm_runtime_status_suspended, skipping jack detection\n",
252770f3d99SPierre-Louis Bossart __func__);
253770f3d99SPierre-Louis Bossart return;
254770f3d99SPierre-Louis Bossart }
255770f3d99SPierre-Louis Bossart
256320b8b0dSShuming Fan reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
257320b8b0dSShuming Fan ret = regmap_read(rt711->regmap, reg, &jack_status);
258320b8b0dSShuming Fan if (ret < 0)
259320b8b0dSShuming Fan goto io_error;
260320b8b0dSShuming Fan
261320b8b0dSShuming Fan /* pin attached */
262320b8b0dSShuming Fan if (jack_status & (1 << 31)) {
263320b8b0dSShuming Fan /* jack in */
264320b8b0dSShuming Fan if (rt711->jack_type == 0) {
265320b8b0dSShuming Fan ret = rt711_headset_detect(rt711);
266320b8b0dSShuming Fan if (ret < 0)
267320b8b0dSShuming Fan return;
268320b8b0dSShuming Fan if (rt711->jack_type == SND_JACK_HEADSET)
269320b8b0dSShuming Fan btn_type = rt711_button_detect(rt711);
270320b8b0dSShuming Fan } else if (rt711->jack_type == SND_JACK_HEADSET) {
271320b8b0dSShuming Fan /* jack is already in, report button event */
272320b8b0dSShuming Fan btn_type = rt711_button_detect(rt711);
273320b8b0dSShuming Fan }
274320b8b0dSShuming Fan } else {
275320b8b0dSShuming Fan /* jack out */
276320b8b0dSShuming Fan rt711->jack_type = 0;
277320b8b0dSShuming Fan }
278320b8b0dSShuming Fan
279320b8b0dSShuming Fan dev_dbg(&rt711->slave->dev,
280320b8b0dSShuming Fan "in %s, jack_type=0x%x\n", __func__, rt711->jack_type);
281320b8b0dSShuming Fan dev_dbg(&rt711->slave->dev,
282320b8b0dSShuming Fan "in %s, btn_type=0x%x\n", __func__, btn_type);
283320b8b0dSShuming Fan
284320b8b0dSShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
285320b8b0dSShuming Fan SND_JACK_HEADSET |
286320b8b0dSShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 |
287320b8b0dSShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3);
288320b8b0dSShuming Fan
289320b8b0dSShuming Fan if (btn_type) {
290320b8b0dSShuming Fan /* button released */
291320b8b0dSShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
292320b8b0dSShuming Fan SND_JACK_HEADSET |
293320b8b0dSShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 |
294320b8b0dSShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3);
295320b8b0dSShuming Fan
296320b8b0dSShuming Fan mod_delayed_work(system_power_efficient_wq,
297320b8b0dSShuming Fan &rt711->jack_btn_check_work, msecs_to_jiffies(200));
298320b8b0dSShuming Fan }
299320b8b0dSShuming Fan
300320b8b0dSShuming Fan return;
301320b8b0dSShuming Fan
302320b8b0dSShuming Fan io_error:
303320b8b0dSShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
304320b8b0dSShuming Fan }
305320b8b0dSShuming Fan
rt711_btn_check_handler(struct work_struct * work)306320b8b0dSShuming Fan static void rt711_btn_check_handler(struct work_struct *work)
307320b8b0dSShuming Fan {
308320b8b0dSShuming Fan struct rt711_priv *rt711 = container_of(work, struct rt711_priv,
309320b8b0dSShuming Fan jack_btn_check_work.work);
310320b8b0dSShuming Fan int btn_type = 0, ret;
311320b8b0dSShuming Fan unsigned int jack_status = 0, reg;
312320b8b0dSShuming Fan
313320b8b0dSShuming Fan reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
314320b8b0dSShuming Fan ret = regmap_read(rt711->regmap, reg, &jack_status);
315320b8b0dSShuming Fan if (ret < 0)
316320b8b0dSShuming Fan goto io_error;
317320b8b0dSShuming Fan
318320b8b0dSShuming Fan /* pin attached */
319320b8b0dSShuming Fan if (jack_status & (1 << 31)) {
320320b8b0dSShuming Fan if (rt711->jack_type == SND_JACK_HEADSET) {
321320b8b0dSShuming Fan /* jack is already in, report button event */
322320b8b0dSShuming Fan btn_type = rt711_button_detect(rt711);
323320b8b0dSShuming Fan }
324320b8b0dSShuming Fan } else {
325320b8b0dSShuming Fan rt711->jack_type = 0;
326320b8b0dSShuming Fan }
327320b8b0dSShuming Fan
328320b8b0dSShuming Fan /* cbj comparator */
329320b8b0dSShuming Fan ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
330320b8b0dSShuming Fan RT711_COMBO_JACK_AUTO_CTL2, ®);
331320b8b0dSShuming Fan if (ret < 0)
332320b8b0dSShuming Fan goto io_error;
333320b8b0dSShuming Fan
334320b8b0dSShuming Fan if ((reg & 0xf0) == 0xf0)
335320b8b0dSShuming Fan btn_type = 0;
336320b8b0dSShuming Fan
337320b8b0dSShuming Fan dev_dbg(&rt711->slave->dev,
338320b8b0dSShuming Fan "%s, btn_type=0x%x\n", __func__, btn_type);
339320b8b0dSShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
340320b8b0dSShuming Fan SND_JACK_HEADSET |
341320b8b0dSShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 |
342320b8b0dSShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3);
343320b8b0dSShuming Fan
344320b8b0dSShuming Fan if (btn_type) {
345320b8b0dSShuming Fan /* button released */
346320b8b0dSShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
347320b8b0dSShuming Fan SND_JACK_HEADSET |
348320b8b0dSShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 |
349320b8b0dSShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3);
350320b8b0dSShuming Fan
351320b8b0dSShuming Fan mod_delayed_work(system_power_efficient_wq,
352320b8b0dSShuming Fan &rt711->jack_btn_check_work, msecs_to_jiffies(200));
353320b8b0dSShuming Fan }
354320b8b0dSShuming Fan
355320b8b0dSShuming Fan return;
356320b8b0dSShuming Fan
357320b8b0dSShuming Fan io_error:
358320b8b0dSShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
359320b8b0dSShuming Fan }
360320b8b0dSShuming Fan
rt711_jack_init(struct rt711_priv * rt711)361320b8b0dSShuming Fan static void rt711_jack_init(struct rt711_priv *rt711)
362320b8b0dSShuming Fan {
363320b8b0dSShuming Fan struct snd_soc_dapm_context *dapm =
364320b8b0dSShuming Fan snd_soc_component_get_dapm(rt711->component);
365320b8b0dSShuming Fan
366320b8b0dSShuming Fan mutex_lock(&rt711->calibrate_mutex);
367320b8b0dSShuming Fan /* power on */
368320b8b0dSShuming Fan if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
369320b8b0dSShuming Fan regmap_write(rt711->regmap,
370320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
371320b8b0dSShuming Fan
372320b8b0dSShuming Fan if (rt711->hs_jack) {
373320b8b0dSShuming Fan /* unsolicited response & IRQ control */
374320b8b0dSShuming Fan regmap_write(rt711->regmap,
375320b8b0dSShuming Fan RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x82);
376320b8b0dSShuming Fan regmap_write(rt711->regmap,
377320b8b0dSShuming Fan RT711_SET_HP_UNSOLICITED_ENABLE, 0x81);
378320b8b0dSShuming Fan regmap_write(rt711->regmap,
379320b8b0dSShuming Fan RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x83);
380320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
381320b8b0dSShuming Fan 0x10, 0x2420);
382320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
383320b8b0dSShuming Fan 0x19, 0x2e11);
384320b8b0dSShuming Fan
385320b8b0dSShuming Fan switch (rt711->jd_src) {
386320b8b0dSShuming Fan case RT711_JD1:
387320b8b0dSShuming Fan /* default settings was already for JD1 */
388320b8b0dSShuming Fan break;
389320b8b0dSShuming Fan case RT711_JD2:
390320b8b0dSShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
391320b8b0dSShuming Fan RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP |
392320b8b0dSShuming Fan RT711_HP_JD_SEL_JD2,
393320b8b0dSShuming Fan RT711_JD2_2PORT_200K_DECODE_HP |
394320b8b0dSShuming Fan RT711_HP_JD_SEL_JD2);
395320b8b0dSShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
396320b8b0dSShuming Fan RT711_CC_DET1,
397320b8b0dSShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12,
398320b8b0dSShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12);
399320b8b0dSShuming Fan break;
400683b0df2SShuming Fan case RT711_JD2_100K:
401683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
402683b0df2SShuming Fan RT711_JD_CTL2, RT711_JD2_2PORT_100K_DECODE | RT711_JD2_1PORT_TYPE_DECODE |
403683b0df2SShuming Fan RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_TYPE_100K_DECODE,
404683b0df2SShuming Fan RT711_JD2_2PORT_100K_DECODE_HP | RT711_JD2_1PORT_JD_HP |
405683b0df2SShuming Fan RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_JD_RESERVED);
406683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
407683b0df2SShuming Fan RT711_CC_DET1,
408683b0df2SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12,
409683b0df2SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12);
410683b0df2SShuming Fan break;
411683b0df2SShuming Fan case RT711_JD2_1P8V_1PORT:
412683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
413683b0df2SShuming Fan RT711_JD_CTL1, RT711_JD2_DIGITAL_JD_MODE_SEL,
414683b0df2SShuming Fan RT711_JD2_1_JD_MODE);
415683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
416683b0df2SShuming Fan RT711_JD_CTL2, RT711_JD2_1PORT_TYPE_DECODE |
417683b0df2SShuming Fan RT711_HP_JD_SEL_JD2,
418683b0df2SShuming Fan RT711_JD2_1PORT_JD_HP |
419683b0df2SShuming Fan RT711_HP_JD_SEL_JD2);
420683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
421683b0df2SShuming Fan RT711_JD_CTL4, RT711_JD2_PAD_PULL_UP_MASK |
422683b0df2SShuming Fan RT711_JD2_MODE_SEL_MASK,
423683b0df2SShuming Fan RT711_JD2_PAD_PULL_UP |
424683b0df2SShuming Fan RT711_JD2_MODE2_1P8V_1PORT);
425683b0df2SShuming Fan rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
426683b0df2SShuming Fan RT711_CC_DET1,
427683b0df2SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12,
428683b0df2SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12);
429683b0df2SShuming Fan break;
430320b8b0dSShuming Fan default:
431320b8b0dSShuming Fan dev_warn(rt711->component->dev, "Wrong JD source\n");
432320b8b0dSShuming Fan break;
433320b8b0dSShuming Fan }
434320b8b0dSShuming Fan
435320b8b0dSShuming Fan dev_dbg(&rt711->slave->dev, "in %s enable\n", __func__);
436320b8b0dSShuming Fan
437320b8b0dSShuming Fan mod_delayed_work(system_power_efficient_wq,
438320b8b0dSShuming Fan &rt711->jack_detect_work, msecs_to_jiffies(250));
439320b8b0dSShuming Fan } else {
440320b8b0dSShuming Fan regmap_write(rt711->regmap,
441320b8b0dSShuming Fan RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x00);
442320b8b0dSShuming Fan regmap_write(rt711->regmap,
443320b8b0dSShuming Fan RT711_SET_HP_UNSOLICITED_ENABLE, 0x00);
444320b8b0dSShuming Fan regmap_write(rt711->regmap,
445320b8b0dSShuming Fan RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x00);
446320b8b0dSShuming Fan
447320b8b0dSShuming Fan dev_dbg(&rt711->slave->dev, "in %s disable\n", __func__);
448320b8b0dSShuming Fan }
449320b8b0dSShuming Fan
450320b8b0dSShuming Fan /* power off */
451320b8b0dSShuming Fan if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
452320b8b0dSShuming Fan regmap_write(rt711->regmap,
453320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
454320b8b0dSShuming Fan mutex_unlock(&rt711->calibrate_mutex);
455320b8b0dSShuming Fan }
456320b8b0dSShuming Fan
rt711_set_jack_detect(struct snd_soc_component * component,struct snd_soc_jack * hs_jack,void * data)457320b8b0dSShuming Fan static int rt711_set_jack_detect(struct snd_soc_component *component,
458320b8b0dSShuming Fan struct snd_soc_jack *hs_jack, void *data)
459320b8b0dSShuming Fan {
460320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
461e02b99e9SPierre-Louis Bossart int ret;
462320b8b0dSShuming Fan
463320b8b0dSShuming Fan rt711->hs_jack = hs_jack;
464320b8b0dSShuming Fan
465*a8590dd7SPierre-Louis Bossart /* we can only resume if the device was initialized at least once */
466*a8590dd7SPierre-Louis Bossart if (!rt711->first_hw_init)
467*a8590dd7SPierre-Louis Bossart return 0;
468*a8590dd7SPierre-Louis Bossart
469e02b99e9SPierre-Louis Bossart ret = pm_runtime_resume_and_get(component->dev);
470e02b99e9SPierre-Louis Bossart if (ret < 0) {
471e02b99e9SPierre-Louis Bossart if (ret != -EACCES) {
472e02b99e9SPierre-Louis Bossart dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
473e02b99e9SPierre-Louis Bossart return ret;
474e02b99e9SPierre-Louis Bossart }
475e02b99e9SPierre-Louis Bossart
476e02b99e9SPierre-Louis Bossart /* pm_runtime not enabled yet */
477e02b99e9SPierre-Louis Bossart dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
478320b8b0dSShuming Fan return 0;
479320b8b0dSShuming Fan }
480320b8b0dSShuming Fan
481320b8b0dSShuming Fan rt711_jack_init(rt711);
482320b8b0dSShuming Fan
483e02b99e9SPierre-Louis Bossart pm_runtime_mark_last_busy(component->dev);
484e02b99e9SPierre-Louis Bossart pm_runtime_put_autosuspend(component->dev);
485e02b99e9SPierre-Louis Bossart
486320b8b0dSShuming Fan return 0;
487320b8b0dSShuming Fan }
488320b8b0dSShuming Fan
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)489320b8b0dSShuming Fan static void rt711_get_gain(struct rt711_priv *rt711, unsigned int addr_h,
490320b8b0dSShuming Fan unsigned int addr_l, unsigned int val_h,
491320b8b0dSShuming Fan unsigned int *r_val, unsigned int *l_val)
492320b8b0dSShuming Fan {
493320b8b0dSShuming Fan /* R Channel */
494320b8b0dSShuming Fan *r_val = (val_h << 8);
495320b8b0dSShuming Fan regmap_read(rt711->regmap, addr_l, r_val);
496320b8b0dSShuming Fan
497320b8b0dSShuming Fan /* L Channel */
498320b8b0dSShuming Fan val_h |= 0x20;
499320b8b0dSShuming Fan *l_val = (val_h << 8);
500320b8b0dSShuming Fan regmap_read(rt711->regmap, addr_h, l_val);
501320b8b0dSShuming Fan }
502320b8b0dSShuming Fan
503320b8b0dSShuming Fan /* For Verb-Set Amplifier Gain (Verb ID = 3h) */
rt711_set_amp_gain_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)504320b8b0dSShuming Fan static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol,
505320b8b0dSShuming Fan struct snd_ctl_elem_value *ucontrol)
506320b8b0dSShuming Fan {
507320b8b0dSShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
508320b8b0dSShuming Fan struct snd_soc_dapm_context *dapm =
509320b8b0dSShuming Fan snd_soc_component_get_dapm(component);
510320b8b0dSShuming Fan struct soc_mixer_control *mc =
511320b8b0dSShuming Fan (struct soc_mixer_control *)kcontrol->private_value;
512320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
513320b8b0dSShuming Fan unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
514320b8b0dSShuming Fan unsigned int read_ll, read_rl;
515320b8b0dSShuming Fan int i;
516320b8b0dSShuming Fan
5176108f990SShuming Fan mutex_lock(&rt711->calibrate_mutex);
5186108f990SShuming Fan
519320b8b0dSShuming Fan /* Can't use update bit function, so read the original value first */
520320b8b0dSShuming Fan addr_h = mc->reg;
521320b8b0dSShuming Fan addr_l = mc->rreg;
522320b8b0dSShuming Fan if (mc->shift == RT711_DIR_OUT_SFT) /* output */
523320b8b0dSShuming Fan val_h = 0x80;
524320b8b0dSShuming Fan else /* input */
525320b8b0dSShuming Fan val_h = 0x0;
526320b8b0dSShuming Fan
527320b8b0dSShuming Fan rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
528320b8b0dSShuming Fan
529320b8b0dSShuming Fan /* L Channel */
530320b8b0dSShuming Fan if (mc->invert) {
531320b8b0dSShuming Fan /* for mute/unmute */
532320b8b0dSShuming Fan val_ll = (mc->max - ucontrol->value.integer.value[0])
533320b8b0dSShuming Fan << RT711_MUTE_SFT;
534320b8b0dSShuming Fan /* keep gain */
535320b8b0dSShuming Fan read_ll = read_ll & 0x7f;
536320b8b0dSShuming Fan val_ll |= read_ll;
537320b8b0dSShuming Fan } else {
538320b8b0dSShuming Fan /* for gain */
539320b8b0dSShuming Fan val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
540320b8b0dSShuming Fan if (val_ll > mc->max)
541320b8b0dSShuming Fan val_ll = mc->max;
542320b8b0dSShuming Fan /* keep mute status */
543320b8b0dSShuming Fan read_ll = read_ll & (1 << RT711_MUTE_SFT);
544320b8b0dSShuming Fan val_ll |= read_ll;
545320b8b0dSShuming Fan }
546320b8b0dSShuming Fan
547320b8b0dSShuming Fan if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
548320b8b0dSShuming Fan regmap_write(rt711->regmap,
549320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
550320b8b0dSShuming Fan
551320b8b0dSShuming Fan /* R Channel */
552320b8b0dSShuming Fan if (mc->invert) {
553320b8b0dSShuming Fan /* for mute/unmute */
554320b8b0dSShuming Fan val_lr = (mc->max - ucontrol->value.integer.value[1])
555320b8b0dSShuming Fan << RT711_MUTE_SFT;
556320b8b0dSShuming Fan /* keep gain */
557320b8b0dSShuming Fan read_rl = read_rl & 0x7f;
558320b8b0dSShuming Fan val_lr |= read_rl;
559320b8b0dSShuming Fan } else {
560320b8b0dSShuming Fan /* for gain */
561320b8b0dSShuming Fan val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
562320b8b0dSShuming Fan if (val_lr > mc->max)
563320b8b0dSShuming Fan val_lr = mc->max;
564320b8b0dSShuming Fan /* keep mute status */
565320b8b0dSShuming Fan read_rl = read_rl & (1 << RT711_MUTE_SFT);
566320b8b0dSShuming Fan val_lr |= read_rl;
567320b8b0dSShuming Fan }
568320b8b0dSShuming Fan
569320b8b0dSShuming Fan for (i = 0; i < 3; i++) { /* retry 3 times at most */
570320b8b0dSShuming Fan
571320b8b0dSShuming Fan if (val_ll == val_lr) {
572320b8b0dSShuming Fan /* Set both L/R channels at the same time */
573320b8b0dSShuming Fan val_h = (1 << mc->shift) | (3 << 4);
574320b8b0dSShuming Fan regmap_write(rt711->regmap,
575320b8b0dSShuming Fan addr_h, (val_h << 8 | val_ll));
576320b8b0dSShuming Fan regmap_write(rt711->regmap,
577320b8b0dSShuming Fan addr_l, (val_h << 8 | val_ll));
578320b8b0dSShuming Fan } else {
579320b8b0dSShuming Fan /* Lch*/
580320b8b0dSShuming Fan val_h = (1 << mc->shift) | (1 << 5);
581320b8b0dSShuming Fan regmap_write(rt711->regmap,
582320b8b0dSShuming Fan addr_h, (val_h << 8 | val_ll));
583320b8b0dSShuming Fan
584320b8b0dSShuming Fan /* Rch */
585320b8b0dSShuming Fan val_h = (1 << mc->shift) | (1 << 4);
586320b8b0dSShuming Fan regmap_write(rt711->regmap,
587320b8b0dSShuming Fan addr_l, (val_h << 8 | val_lr));
588320b8b0dSShuming Fan }
589320b8b0dSShuming Fan /* check result */
590320b8b0dSShuming Fan if (mc->shift == RT711_DIR_OUT_SFT) /* output */
591320b8b0dSShuming Fan val_h = 0x80;
592320b8b0dSShuming Fan else /* input */
593320b8b0dSShuming Fan val_h = 0x0;
594320b8b0dSShuming Fan
595320b8b0dSShuming Fan rt711_get_gain(rt711, addr_h, addr_l, val_h,
596320b8b0dSShuming Fan &read_rl, &read_ll);
597320b8b0dSShuming Fan if (read_rl == val_lr && read_ll == val_ll)
598320b8b0dSShuming Fan break;
599320b8b0dSShuming Fan }
600320b8b0dSShuming Fan
601320b8b0dSShuming Fan if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
602320b8b0dSShuming Fan regmap_write(rt711->regmap,
603320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
6046108f990SShuming Fan
6056108f990SShuming Fan mutex_unlock(&rt711->calibrate_mutex);
606320b8b0dSShuming Fan return 0;
607320b8b0dSShuming Fan }
608320b8b0dSShuming Fan
rt711_set_amp_gain_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)609320b8b0dSShuming Fan static int rt711_set_amp_gain_get(struct snd_kcontrol *kcontrol,
610320b8b0dSShuming Fan struct snd_ctl_elem_value *ucontrol)
611320b8b0dSShuming Fan {
612320b8b0dSShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
613320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
614320b8b0dSShuming Fan struct soc_mixer_control *mc =
615320b8b0dSShuming Fan (struct soc_mixer_control *)kcontrol->private_value;
616320b8b0dSShuming Fan unsigned int addr_h, addr_l, val_h;
617320b8b0dSShuming Fan unsigned int read_ll, read_rl;
618320b8b0dSShuming Fan
619320b8b0dSShuming Fan /* switch to get command */
620320b8b0dSShuming Fan addr_h = mc->reg;
621320b8b0dSShuming Fan addr_l = mc->rreg;
622320b8b0dSShuming Fan if (mc->shift == RT711_DIR_OUT_SFT) /* output */
623320b8b0dSShuming Fan val_h = 0x80;
624320b8b0dSShuming Fan else /* input */
625320b8b0dSShuming Fan val_h = 0x0;
626320b8b0dSShuming Fan
627320b8b0dSShuming Fan rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
628320b8b0dSShuming Fan
629320b8b0dSShuming Fan if (mc->invert) {
630320b8b0dSShuming Fan /* mute/unmute for switch controls */
631320b8b0dSShuming Fan read_ll = !((read_ll & 0x80) >> RT711_MUTE_SFT);
632320b8b0dSShuming Fan read_rl = !((read_rl & 0x80) >> RT711_MUTE_SFT);
633320b8b0dSShuming Fan } else {
634320b8b0dSShuming Fan /* for gain volume controls */
635320b8b0dSShuming Fan read_ll = read_ll & 0x7f;
636320b8b0dSShuming Fan read_rl = read_rl & 0x7f;
637320b8b0dSShuming Fan }
638320b8b0dSShuming Fan ucontrol->value.integer.value[0] = read_ll;
639320b8b0dSShuming Fan ucontrol->value.integer.value[1] = read_rl;
640320b8b0dSShuming Fan
641320b8b0dSShuming Fan return 0;
642320b8b0dSShuming Fan }
643320b8b0dSShuming Fan
644320b8b0dSShuming Fan static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
645320b8b0dSShuming Fan static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
646320b8b0dSShuming Fan static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
647320b8b0dSShuming Fan
648320b8b0dSShuming Fan static const struct snd_kcontrol_new rt711_snd_controls[] = {
649320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("DAC Surr Playback Volume",
650320b8b0dSShuming Fan RT711_SET_GAIN_DAC2_H, RT711_SET_GAIN_DAC2_L,
651320b8b0dSShuming Fan RT711_DIR_OUT_SFT, 0x57, 0,
652320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, out_vol_tlv),
653320b8b0dSShuming Fan SOC_DOUBLE_R_EXT("ADC 08 Capture Switch",
654320b8b0dSShuming Fan RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
655320b8b0dSShuming Fan RT711_DIR_IN_SFT, 1, 1,
656320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put),
657320b8b0dSShuming Fan SOC_DOUBLE_R_EXT("ADC 09 Capture Switch",
658320b8b0dSShuming Fan RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
659320b8b0dSShuming Fan RT711_DIR_IN_SFT, 1, 1,
660320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put),
661320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume",
662320b8b0dSShuming Fan RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
663320b8b0dSShuming Fan RT711_DIR_IN_SFT, 0x3f, 0,
664320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
665320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume",
666320b8b0dSShuming Fan RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
667320b8b0dSShuming Fan RT711_DIR_IN_SFT, 0x3f, 0,
668320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
669320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("AMIC Volume",
670320b8b0dSShuming Fan RT711_SET_GAIN_AMIC_H, RT711_SET_GAIN_AMIC_L,
671320b8b0dSShuming Fan RT711_DIR_IN_SFT, 3, 0,
672320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
673320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("DMIC1 Volume",
674320b8b0dSShuming Fan RT711_SET_GAIN_DMIC1_H, RT711_SET_GAIN_DMIC1_L,
675320b8b0dSShuming Fan RT711_DIR_IN_SFT, 3, 0,
676320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
677320b8b0dSShuming Fan SOC_DOUBLE_R_EXT_TLV("DMIC2 Volume",
678320b8b0dSShuming Fan RT711_SET_GAIN_DMIC2_H, RT711_SET_GAIN_DMIC2_L,
679320b8b0dSShuming Fan RT711_DIR_IN_SFT, 3, 0,
680320b8b0dSShuming Fan rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
681320b8b0dSShuming Fan };
682320b8b0dSShuming Fan
rt711_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)683320b8b0dSShuming Fan static int rt711_mux_get(struct snd_kcontrol *kcontrol,
684320b8b0dSShuming Fan struct snd_ctl_elem_value *ucontrol)
685320b8b0dSShuming Fan {
686320b8b0dSShuming Fan struct snd_soc_component *component =
687320b8b0dSShuming Fan snd_soc_dapm_kcontrol_component(kcontrol);
688320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
689320b8b0dSShuming Fan unsigned int reg, val = 0, nid;
690320b8b0dSShuming Fan int ret;
691320b8b0dSShuming Fan
692320b8b0dSShuming Fan if (strstr(ucontrol->id.name, "ADC 22 Mux"))
693320b8b0dSShuming Fan nid = RT711_MIXER_IN1;
694320b8b0dSShuming Fan else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
695320b8b0dSShuming Fan nid = RT711_MIXER_IN2;
696320b8b0dSShuming Fan else
697320b8b0dSShuming Fan return -EINVAL;
698320b8b0dSShuming Fan
699320b8b0dSShuming Fan /* vid = 0xf01 */
700320b8b0dSShuming Fan reg = RT711_VERB_SET_CONNECT_SEL | nid;
701320b8b0dSShuming Fan ret = regmap_read(rt711->regmap, reg, &val);
702320b8b0dSShuming Fan if (ret < 0) {
703320b8b0dSShuming Fan dev_err(component->dev, "%s: sdw read failed: %d\n",
704320b8b0dSShuming Fan __func__, ret);
705320b8b0dSShuming Fan return ret;
706320b8b0dSShuming Fan }
707320b8b0dSShuming Fan
708320b8b0dSShuming Fan ucontrol->value.enumerated.item[0] = val;
709320b8b0dSShuming Fan
710320b8b0dSShuming Fan return 0;
711320b8b0dSShuming Fan }
712320b8b0dSShuming Fan
rt711_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)713320b8b0dSShuming Fan static int rt711_mux_put(struct snd_kcontrol *kcontrol,
714320b8b0dSShuming Fan struct snd_ctl_elem_value *ucontrol)
715320b8b0dSShuming Fan {
716320b8b0dSShuming Fan struct snd_soc_component *component =
717320b8b0dSShuming Fan snd_soc_dapm_kcontrol_component(kcontrol);
718320b8b0dSShuming Fan struct snd_soc_dapm_context *dapm =
719320b8b0dSShuming Fan snd_soc_dapm_kcontrol_dapm(kcontrol);
720320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
721320b8b0dSShuming Fan struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
722320b8b0dSShuming Fan unsigned int *item = ucontrol->value.enumerated.item;
723320b8b0dSShuming Fan unsigned int val, val2 = 0, change, reg, nid;
724320b8b0dSShuming Fan int ret;
725320b8b0dSShuming Fan
726320b8b0dSShuming Fan if (item[0] >= e->items)
727320b8b0dSShuming Fan return -EINVAL;
728320b8b0dSShuming Fan
729320b8b0dSShuming Fan if (strstr(ucontrol->id.name, "ADC 22 Mux"))
730320b8b0dSShuming Fan nid = RT711_MIXER_IN1;
731320b8b0dSShuming Fan else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
732320b8b0dSShuming Fan nid = RT711_MIXER_IN2;
733320b8b0dSShuming Fan else
734320b8b0dSShuming Fan return -EINVAL;
735320b8b0dSShuming Fan
736320b8b0dSShuming Fan /* Verb ID = 0x701h */
737320b8b0dSShuming Fan val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
738320b8b0dSShuming Fan
739320b8b0dSShuming Fan reg = RT711_VERB_SET_CONNECT_SEL | nid;
740320b8b0dSShuming Fan ret = regmap_read(rt711->regmap, reg, &val2);
741320b8b0dSShuming Fan if (ret < 0) {
742320b8b0dSShuming Fan dev_err(component->dev, "%s: sdw read failed: %d\n",
743320b8b0dSShuming Fan __func__, ret);
744320b8b0dSShuming Fan return ret;
745320b8b0dSShuming Fan }
746320b8b0dSShuming Fan
747320b8b0dSShuming Fan if (val == val2)
748320b8b0dSShuming Fan change = 0;
749320b8b0dSShuming Fan else
750320b8b0dSShuming Fan change = 1;
751320b8b0dSShuming Fan
752320b8b0dSShuming Fan if (change) {
753320b8b0dSShuming Fan reg = RT711_VERB_SET_CONNECT_SEL | nid;
754320b8b0dSShuming Fan regmap_write(rt711->regmap, reg, val);
755320b8b0dSShuming Fan }
756320b8b0dSShuming Fan
757320b8b0dSShuming Fan snd_soc_dapm_mux_update_power(dapm, kcontrol,
758320b8b0dSShuming Fan item[0], e, NULL);
759320b8b0dSShuming Fan
760320b8b0dSShuming Fan return change;
761320b8b0dSShuming Fan }
762320b8b0dSShuming Fan
763320b8b0dSShuming Fan static const char * const adc_mux_text[] = {
764320b8b0dSShuming Fan "MIC2",
765320b8b0dSShuming Fan "LINE1",
766320b8b0dSShuming Fan "LINE2",
767320b8b0dSShuming Fan "DMIC",
768320b8b0dSShuming Fan };
769320b8b0dSShuming Fan
770320b8b0dSShuming Fan static SOC_ENUM_SINGLE_DECL(
771320b8b0dSShuming Fan rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text);
772320b8b0dSShuming Fan
773320b8b0dSShuming Fan static SOC_ENUM_SINGLE_DECL(
774320b8b0dSShuming Fan rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text);
775320b8b0dSShuming Fan
776320b8b0dSShuming Fan static const struct snd_kcontrol_new rt711_adc22_mux =
777320b8b0dSShuming Fan SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt711_adc22_enum,
778320b8b0dSShuming Fan rt711_mux_get, rt711_mux_put);
779320b8b0dSShuming Fan
780320b8b0dSShuming Fan static const struct snd_kcontrol_new rt711_adc23_mux =
781320b8b0dSShuming Fan SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt711_adc23_enum,
782320b8b0dSShuming Fan rt711_mux_get, rt711_mux_put);
783320b8b0dSShuming Fan
rt711_dac_surround_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)784320b8b0dSShuming Fan static int rt711_dac_surround_event(struct snd_soc_dapm_widget *w,
785320b8b0dSShuming Fan struct snd_kcontrol *kcontrol, int event)
786320b8b0dSShuming Fan {
787320b8b0dSShuming Fan struct snd_soc_component *component =
788320b8b0dSShuming Fan snd_soc_dapm_to_component(w->dapm);
789320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
790320b8b0dSShuming Fan unsigned int val_h = (1 << RT711_DIR_OUT_SFT) | (0x3 << 4);
791320b8b0dSShuming Fan unsigned int val_l;
792320b8b0dSShuming Fan
793320b8b0dSShuming Fan switch (event) {
794320b8b0dSShuming Fan case SND_SOC_DAPM_POST_PMU:
795320b8b0dSShuming Fan regmap_write(rt711->regmap,
796320b8b0dSShuming Fan RT711_SET_STREAMID_DAC2, 0x10);
797320b8b0dSShuming Fan
798320b8b0dSShuming Fan val_l = 0x00;
799320b8b0dSShuming Fan regmap_write(rt711->regmap,
800320b8b0dSShuming Fan RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
801320b8b0dSShuming Fan break;
802320b8b0dSShuming Fan case SND_SOC_DAPM_PRE_PMD:
803320b8b0dSShuming Fan val_l = (1 << RT711_MUTE_SFT);
804320b8b0dSShuming Fan regmap_write(rt711->regmap,
805320b8b0dSShuming Fan RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
806320b8b0dSShuming Fan usleep_range(50000, 55000);
807320b8b0dSShuming Fan
808320b8b0dSShuming Fan regmap_write(rt711->regmap,
809320b8b0dSShuming Fan RT711_SET_STREAMID_DAC2, 0x00);
810320b8b0dSShuming Fan break;
811320b8b0dSShuming Fan }
812320b8b0dSShuming Fan return 0;
813320b8b0dSShuming Fan }
814320b8b0dSShuming Fan
rt711_adc_09_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)815320b8b0dSShuming Fan static int rt711_adc_09_event(struct snd_soc_dapm_widget *w,
816320b8b0dSShuming Fan struct snd_kcontrol *kcontrol, int event)
817320b8b0dSShuming Fan {
818320b8b0dSShuming Fan struct snd_soc_component *component =
819320b8b0dSShuming Fan snd_soc_dapm_to_component(w->dapm);
820320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
821320b8b0dSShuming Fan
822320b8b0dSShuming Fan switch (event) {
823320b8b0dSShuming Fan case SND_SOC_DAPM_POST_PMU:
824320b8b0dSShuming Fan regmap_write(rt711->regmap,
825320b8b0dSShuming Fan RT711_SET_STREAMID_ADC1, 0x10);
826320b8b0dSShuming Fan break;
827320b8b0dSShuming Fan case SND_SOC_DAPM_PRE_PMD:
828320b8b0dSShuming Fan regmap_write(rt711->regmap,
829320b8b0dSShuming Fan RT711_SET_STREAMID_ADC1, 0x00);
830320b8b0dSShuming Fan break;
831320b8b0dSShuming Fan }
832320b8b0dSShuming Fan return 0;
833320b8b0dSShuming Fan }
834320b8b0dSShuming Fan
rt711_adc_08_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)835320b8b0dSShuming Fan static int rt711_adc_08_event(struct snd_soc_dapm_widget *w,
836320b8b0dSShuming Fan struct snd_kcontrol *kcontrol, int event)
837320b8b0dSShuming Fan {
838320b8b0dSShuming Fan struct snd_soc_component *component =
839320b8b0dSShuming Fan snd_soc_dapm_to_component(w->dapm);
840320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
841320b8b0dSShuming Fan
842320b8b0dSShuming Fan switch (event) {
843320b8b0dSShuming Fan case SND_SOC_DAPM_POST_PMU:
844320b8b0dSShuming Fan regmap_write(rt711->regmap,
845320b8b0dSShuming Fan RT711_SET_STREAMID_ADC2, 0x10);
846320b8b0dSShuming Fan break;
847320b8b0dSShuming Fan case SND_SOC_DAPM_PRE_PMD:
848320b8b0dSShuming Fan regmap_write(rt711->regmap,
849320b8b0dSShuming Fan RT711_SET_STREAMID_ADC2, 0x00);
850320b8b0dSShuming Fan break;
851320b8b0dSShuming Fan }
852320b8b0dSShuming Fan return 0;
853320b8b0dSShuming Fan }
854320b8b0dSShuming Fan
855320b8b0dSShuming Fan static const struct snd_soc_dapm_widget rt711_dapm_widgets[] = {
856320b8b0dSShuming Fan SND_SOC_DAPM_OUTPUT("HP"),
857320b8b0dSShuming Fan SND_SOC_DAPM_INPUT("MIC2"),
858320b8b0dSShuming Fan SND_SOC_DAPM_INPUT("DMIC1"),
859320b8b0dSShuming Fan SND_SOC_DAPM_INPUT("DMIC2"),
860320b8b0dSShuming Fan SND_SOC_DAPM_INPUT("LINE1"),
861320b8b0dSShuming Fan SND_SOC_DAPM_INPUT("LINE2"),
862320b8b0dSShuming Fan
863320b8b0dSShuming Fan SND_SOC_DAPM_DAC_E("DAC Surround", NULL, SND_SOC_NOPM, 0, 0,
864320b8b0dSShuming Fan rt711_dac_surround_event,
865320b8b0dSShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
866320b8b0dSShuming Fan SND_SOC_DAPM_ADC_E("ADC 09", NULL, SND_SOC_NOPM, 0, 0,
867320b8b0dSShuming Fan rt711_adc_09_event,
868320b8b0dSShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
869320b8b0dSShuming Fan SND_SOC_DAPM_ADC_E("ADC 08", NULL, SND_SOC_NOPM, 0, 0,
870320b8b0dSShuming Fan rt711_adc_08_event,
871320b8b0dSShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
872320b8b0dSShuming Fan SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0,
873320b8b0dSShuming Fan &rt711_adc22_mux),
874320b8b0dSShuming Fan SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0,
875320b8b0dSShuming Fan &rt711_adc23_mux),
876320b8b0dSShuming Fan
877320b8b0dSShuming Fan SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0),
878320b8b0dSShuming Fan SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0),
879320b8b0dSShuming Fan SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
880320b8b0dSShuming Fan };
881320b8b0dSShuming Fan
882320b8b0dSShuming Fan static const struct snd_soc_dapm_route rt711_audio_map[] = {
883320b8b0dSShuming Fan {"DAC Surround", NULL, "DP3RX"},
884320b8b0dSShuming Fan {"DP2TX", NULL, "ADC 09"},
885320b8b0dSShuming Fan {"DP4TX", NULL, "ADC 08"},
886320b8b0dSShuming Fan
887320b8b0dSShuming Fan {"ADC 09", NULL, "ADC 22 Mux"},
888320b8b0dSShuming Fan {"ADC 08", NULL, "ADC 23 Mux"},
889320b8b0dSShuming Fan {"ADC 22 Mux", "DMIC", "DMIC1"},
890320b8b0dSShuming Fan {"ADC 22 Mux", "LINE1", "LINE1"},
891320b8b0dSShuming Fan {"ADC 22 Mux", "LINE2", "LINE2"},
892320b8b0dSShuming Fan {"ADC 22 Mux", "MIC2", "MIC2"},
893320b8b0dSShuming Fan {"ADC 23 Mux", "DMIC", "DMIC2"},
894320b8b0dSShuming Fan {"ADC 23 Mux", "LINE1", "LINE1"},
895320b8b0dSShuming Fan {"ADC 23 Mux", "LINE2", "LINE2"},
896320b8b0dSShuming Fan {"ADC 23 Mux", "MIC2", "MIC2"},
897320b8b0dSShuming Fan
898320b8b0dSShuming Fan {"HP", NULL, "DAC Surround"},
899320b8b0dSShuming Fan };
900320b8b0dSShuming Fan
rt711_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)901320b8b0dSShuming Fan static int rt711_set_bias_level(struct snd_soc_component *component,
902320b8b0dSShuming Fan enum snd_soc_bias_level level)
903320b8b0dSShuming Fan {
904320b8b0dSShuming Fan struct snd_soc_dapm_context *dapm =
905320b8b0dSShuming Fan snd_soc_component_get_dapm(component);
906320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
907320b8b0dSShuming Fan
908320b8b0dSShuming Fan switch (level) {
909320b8b0dSShuming Fan case SND_SOC_BIAS_PREPARE:
910320b8b0dSShuming Fan if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
911320b8b0dSShuming Fan regmap_write(rt711->regmap,
912320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE,
913320b8b0dSShuming Fan AC_PWRST_D0);
914320b8b0dSShuming Fan }
915320b8b0dSShuming Fan break;
916320b8b0dSShuming Fan
917320b8b0dSShuming Fan case SND_SOC_BIAS_STANDBY:
9186108f990SShuming Fan mutex_lock(&rt711->calibrate_mutex);
919320b8b0dSShuming Fan regmap_write(rt711->regmap,
920320b8b0dSShuming Fan RT711_SET_AUDIO_POWER_STATE,
921320b8b0dSShuming Fan AC_PWRST_D3);
9226108f990SShuming Fan mutex_unlock(&rt711->calibrate_mutex);
923320b8b0dSShuming Fan break;
924320b8b0dSShuming Fan
925320b8b0dSShuming Fan default:
926320b8b0dSShuming Fan break;
927320b8b0dSShuming Fan }
928320b8b0dSShuming Fan
929320b8b0dSShuming Fan return 0;
930320b8b0dSShuming Fan }
931320b8b0dSShuming Fan
rt711_parse_dt(struct rt711_priv * rt711,struct device * dev)932320b8b0dSShuming Fan static int rt711_parse_dt(struct rt711_priv *rt711, struct device *dev)
933320b8b0dSShuming Fan {
934320b8b0dSShuming Fan device_property_read_u32(dev, "realtek,jd-src",
935320b8b0dSShuming Fan &rt711->jd_src);
936320b8b0dSShuming Fan
937320b8b0dSShuming Fan return 0;
938320b8b0dSShuming Fan }
939320b8b0dSShuming Fan
rt711_probe(struct snd_soc_component * component)940320b8b0dSShuming Fan static int rt711_probe(struct snd_soc_component *component)
941320b8b0dSShuming Fan {
942320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
943011e397fSPierre-Louis Bossart int ret;
944320b8b0dSShuming Fan
945320b8b0dSShuming Fan rt711_parse_dt(rt711, &rt711->slave->dev);
946320b8b0dSShuming Fan rt711->component = component;
947320b8b0dSShuming Fan
948*a8590dd7SPierre-Louis Bossart if (!rt711->first_hw_init)
949*a8590dd7SPierre-Louis Bossart return 0;
950*a8590dd7SPierre-Louis Bossart
951011e397fSPierre-Louis Bossart ret = pm_runtime_resume(component->dev);
952011e397fSPierre-Louis Bossart if (ret < 0 && ret != -EACCES)
953011e397fSPierre-Louis Bossart return ret;
954011e397fSPierre-Louis Bossart
955320b8b0dSShuming Fan return 0;
956320b8b0dSShuming Fan }
957320b8b0dSShuming Fan
958320b8b0dSShuming Fan static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
959320b8b0dSShuming Fan .probe = rt711_probe,
960320b8b0dSShuming Fan .set_bias_level = rt711_set_bias_level,
961320b8b0dSShuming Fan .controls = rt711_snd_controls,
962320b8b0dSShuming Fan .num_controls = ARRAY_SIZE(rt711_snd_controls),
963320b8b0dSShuming Fan .dapm_widgets = rt711_dapm_widgets,
964320b8b0dSShuming Fan .num_dapm_widgets = ARRAY_SIZE(rt711_dapm_widgets),
965320b8b0dSShuming Fan .dapm_routes = rt711_audio_map,
966320b8b0dSShuming Fan .num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
967320b8b0dSShuming Fan .set_jack = rt711_set_jack_detect,
96833f06beaSCharles Keepax .endianness = 1,
969320b8b0dSShuming Fan };
970320b8b0dSShuming Fan
rt711_set_sdw_stream(struct snd_soc_dai * dai,void * sdw_stream,int direction)971320b8b0dSShuming Fan static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
972320b8b0dSShuming Fan int direction)
973320b8b0dSShuming Fan {
974fa55b31fSPierre-Louis Bossart snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
975320b8b0dSShuming Fan
976320b8b0dSShuming Fan return 0;
977320b8b0dSShuming Fan }
978320b8b0dSShuming Fan
rt711_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)979320b8b0dSShuming Fan static void rt711_shutdown(struct snd_pcm_substream *substream,
980320b8b0dSShuming Fan struct snd_soc_dai *dai)
981320b8b0dSShuming Fan {
982320b8b0dSShuming Fan snd_soc_dai_set_dma_data(dai, substream, NULL);
983320b8b0dSShuming Fan }
984320b8b0dSShuming Fan
rt711_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)985320b8b0dSShuming Fan static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
986320b8b0dSShuming Fan struct snd_pcm_hw_params *params,
987320b8b0dSShuming Fan struct snd_soc_dai *dai)
988320b8b0dSShuming Fan {
989320b8b0dSShuming Fan struct snd_soc_component *component = dai->component;
990320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
991754bef67SCharles Keepax struct sdw_stream_config stream_config = {0};
992754bef67SCharles Keepax struct sdw_port_config port_config = {0};
993fa55b31fSPierre-Louis Bossart struct sdw_stream_runtime *sdw_stream;
994754bef67SCharles Keepax int retval;
995320b8b0dSShuming Fan unsigned int val = 0;
996320b8b0dSShuming Fan
997320b8b0dSShuming Fan dev_dbg(dai->dev, "%s %s", __func__, dai->name);
998fa55b31fSPierre-Louis Bossart sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
999320b8b0dSShuming Fan
1000fa55b31fSPierre-Louis Bossart if (!sdw_stream)
1001320b8b0dSShuming Fan return -EINVAL;
1002320b8b0dSShuming Fan
1003320b8b0dSShuming Fan if (!rt711->slave)
1004320b8b0dSShuming Fan return -EINVAL;
1005320b8b0dSShuming Fan
1006320b8b0dSShuming Fan /* SoundWire specific configuration */
1007754bef67SCharles Keepax snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
1008754bef67SCharles Keepax
1009320b8b0dSShuming Fan if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1010754bef67SCharles Keepax port_config.num = 3;
1011320b8b0dSShuming Fan } else {
1012320b8b0dSShuming Fan if (dai->id == RT711_AIF1)
1013754bef67SCharles Keepax port_config.num = 4;
1014320b8b0dSShuming Fan else if (dai->id == RT711_AIF2)
1015754bef67SCharles Keepax port_config.num = 2;
1016320b8b0dSShuming Fan else
1017320b8b0dSShuming Fan return -EINVAL;
1018320b8b0dSShuming Fan }
1019320b8b0dSShuming Fan
1020320b8b0dSShuming Fan retval = sdw_stream_add_slave(rt711->slave, &stream_config,
1021fa55b31fSPierre-Louis Bossart &port_config, 1, sdw_stream);
1022320b8b0dSShuming Fan if (retval) {
1023320b8b0dSShuming Fan dev_err(dai->dev, "Unable to configure port\n");
1024320b8b0dSShuming Fan return retval;
1025320b8b0dSShuming Fan }
1026320b8b0dSShuming Fan
1027320b8b0dSShuming Fan if (params_channels(params) <= 16) {
1028320b8b0dSShuming Fan /* bit 3:0 Number of Channel */
1029320b8b0dSShuming Fan val |= (params_channels(params) - 1);
1030320b8b0dSShuming Fan } else {
1031320b8b0dSShuming Fan dev_err(component->dev, "Unsupported channels %d\n",
1032320b8b0dSShuming Fan params_channels(params));
1033320b8b0dSShuming Fan return -EINVAL;
1034320b8b0dSShuming Fan }
1035320b8b0dSShuming Fan
1036320b8b0dSShuming Fan switch (params_width(params)) {
1037320b8b0dSShuming Fan /* bit 6:4 Bits per Sample */
1038320b8b0dSShuming Fan case 8:
1039320b8b0dSShuming Fan break;
1040320b8b0dSShuming Fan case 16:
1041320b8b0dSShuming Fan val |= (0x1 << 4);
1042320b8b0dSShuming Fan break;
1043320b8b0dSShuming Fan case 20:
1044320b8b0dSShuming Fan val |= (0x2 << 4);
1045320b8b0dSShuming Fan break;
1046320b8b0dSShuming Fan case 24:
1047320b8b0dSShuming Fan val |= (0x3 << 4);
1048320b8b0dSShuming Fan break;
1049320b8b0dSShuming Fan case 32:
1050320b8b0dSShuming Fan val |= (0x4 << 4);
1051320b8b0dSShuming Fan break;
1052320b8b0dSShuming Fan default:
1053320b8b0dSShuming Fan return -EINVAL;
1054320b8b0dSShuming Fan }
1055320b8b0dSShuming Fan
1056320b8b0dSShuming Fan /* 48Khz */
1057320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_DAC_FORMAT_H, val);
1058320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_ADC1_FORMAT_H, val);
1059320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_ADC2_FORMAT_H, val);
1060320b8b0dSShuming Fan
1061320b8b0dSShuming Fan return retval;
1062320b8b0dSShuming Fan }
1063320b8b0dSShuming Fan
rt711_pcm_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)1064320b8b0dSShuming Fan static int rt711_pcm_hw_free(struct snd_pcm_substream *substream,
1065320b8b0dSShuming Fan struct snd_soc_dai *dai)
1066320b8b0dSShuming Fan {
1067320b8b0dSShuming Fan struct snd_soc_component *component = dai->component;
1068320b8b0dSShuming Fan struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
1069fa55b31fSPierre-Louis Bossart struct sdw_stream_runtime *sdw_stream =
1070320b8b0dSShuming Fan snd_soc_dai_get_dma_data(dai, substream);
1071320b8b0dSShuming Fan
1072320b8b0dSShuming Fan if (!rt711->slave)
1073320b8b0dSShuming Fan return -EINVAL;
1074320b8b0dSShuming Fan
1075fa55b31fSPierre-Louis Bossart sdw_stream_remove_slave(rt711->slave, sdw_stream);
1076320b8b0dSShuming Fan return 0;
1077320b8b0dSShuming Fan }
1078320b8b0dSShuming Fan
1079320b8b0dSShuming Fan #define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
1080320b8b0dSShuming Fan #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1081320b8b0dSShuming Fan SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1082320b8b0dSShuming Fan
1083f9e56a34SRikard Falkeborn static const struct snd_soc_dai_ops rt711_ops = {
1084320b8b0dSShuming Fan .hw_params = rt711_pcm_hw_params,
1085320b8b0dSShuming Fan .hw_free = rt711_pcm_hw_free,
1086e8444560SPierre-Louis Bossart .set_stream = rt711_set_sdw_stream,
1087320b8b0dSShuming Fan .shutdown = rt711_shutdown,
1088320b8b0dSShuming Fan };
1089320b8b0dSShuming Fan
1090320b8b0dSShuming Fan static struct snd_soc_dai_driver rt711_dai[] = {
1091320b8b0dSShuming Fan {
1092320b8b0dSShuming Fan .name = "rt711-aif1",
1093320b8b0dSShuming Fan .id = RT711_AIF1,
1094320b8b0dSShuming Fan .playback = {
1095320b8b0dSShuming Fan .stream_name = "DP3 Playback",
1096320b8b0dSShuming Fan .channels_min = 1,
1097320b8b0dSShuming Fan .channels_max = 2,
1098320b8b0dSShuming Fan .rates = RT711_STEREO_RATES,
1099320b8b0dSShuming Fan .formats = RT711_FORMATS,
1100320b8b0dSShuming Fan },
1101320b8b0dSShuming Fan .capture = {
1102320b8b0dSShuming Fan .stream_name = "DP4 Capture",
1103320b8b0dSShuming Fan .channels_min = 1,
1104320b8b0dSShuming Fan .channels_max = 2,
1105320b8b0dSShuming Fan .rates = RT711_STEREO_RATES,
1106320b8b0dSShuming Fan .formats = RT711_FORMATS,
1107320b8b0dSShuming Fan },
1108320b8b0dSShuming Fan .ops = &rt711_ops,
1109320b8b0dSShuming Fan },
1110320b8b0dSShuming Fan {
1111320b8b0dSShuming Fan .name = "rt711-aif2",
1112320b8b0dSShuming Fan .id = RT711_AIF2,
1113320b8b0dSShuming Fan .capture = {
1114320b8b0dSShuming Fan .stream_name = "DP2 Capture",
1115320b8b0dSShuming Fan .channels_min = 1,
1116320b8b0dSShuming Fan .channels_max = 2,
1117320b8b0dSShuming Fan .rates = RT711_STEREO_RATES,
1118320b8b0dSShuming Fan .formats = RT711_FORMATS,
1119320b8b0dSShuming Fan },
1120320b8b0dSShuming Fan .ops = &rt711_ops,
1121320b8b0dSShuming Fan }
1122320b8b0dSShuming Fan };
1123320b8b0dSShuming Fan
1124320b8b0dSShuming Fan /* Bus clock frequency */
1125320b8b0dSShuming Fan #define RT711_CLK_FREQ_9600000HZ 9600000
1126320b8b0dSShuming Fan #define RT711_CLK_FREQ_12000000HZ 12000000
1127320b8b0dSShuming Fan #define RT711_CLK_FREQ_6000000HZ 6000000
1128320b8b0dSShuming Fan #define RT711_CLK_FREQ_4800000HZ 4800000
1129320b8b0dSShuming Fan #define RT711_CLK_FREQ_2400000HZ 2400000
1130320b8b0dSShuming Fan #define RT711_CLK_FREQ_12288000HZ 12288000
1131320b8b0dSShuming Fan
rt711_clock_config(struct device * dev)1132320b8b0dSShuming Fan int rt711_clock_config(struct device *dev)
1133320b8b0dSShuming Fan {
1134320b8b0dSShuming Fan struct rt711_priv *rt711 = dev_get_drvdata(dev);
1135320b8b0dSShuming Fan unsigned int clk_freq, value;
1136320b8b0dSShuming Fan
1137320b8b0dSShuming Fan clk_freq = (rt711->params.curr_dr_freq >> 1);
1138320b8b0dSShuming Fan
1139320b8b0dSShuming Fan switch (clk_freq) {
1140320b8b0dSShuming Fan case RT711_CLK_FREQ_12000000HZ:
1141320b8b0dSShuming Fan value = 0x0;
1142320b8b0dSShuming Fan break;
1143320b8b0dSShuming Fan case RT711_CLK_FREQ_6000000HZ:
1144320b8b0dSShuming Fan value = 0x1;
1145320b8b0dSShuming Fan break;
1146320b8b0dSShuming Fan case RT711_CLK_FREQ_9600000HZ:
1147320b8b0dSShuming Fan value = 0x2;
1148320b8b0dSShuming Fan break;
1149320b8b0dSShuming Fan case RT711_CLK_FREQ_4800000HZ:
1150320b8b0dSShuming Fan value = 0x3;
1151320b8b0dSShuming Fan break;
1152320b8b0dSShuming Fan case RT711_CLK_FREQ_2400000HZ:
1153320b8b0dSShuming Fan value = 0x4;
1154320b8b0dSShuming Fan break;
1155320b8b0dSShuming Fan case RT711_CLK_FREQ_12288000HZ:
1156320b8b0dSShuming Fan value = 0x5;
1157320b8b0dSShuming Fan break;
1158320b8b0dSShuming Fan default:
1159320b8b0dSShuming Fan return -EINVAL;
1160320b8b0dSShuming Fan }
1161320b8b0dSShuming Fan
1162320b8b0dSShuming Fan regmap_write(rt711->regmap, 0xe0, value);
1163320b8b0dSShuming Fan regmap_write(rt711->regmap, 0xf0, value);
1164320b8b0dSShuming Fan
1165320b8b0dSShuming Fan dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
1166320b8b0dSShuming Fan
1167320b8b0dSShuming Fan return 0;
1168320b8b0dSShuming Fan }
1169320b8b0dSShuming Fan
rt711_calibration_work(struct work_struct * work)1170320b8b0dSShuming Fan static void rt711_calibration_work(struct work_struct *work)
1171320b8b0dSShuming Fan {
1172320b8b0dSShuming Fan struct rt711_priv *rt711 =
1173320b8b0dSShuming Fan container_of(work, struct rt711_priv, calibration_work);
1174320b8b0dSShuming Fan
1175320b8b0dSShuming Fan rt711_calibration(rt711);
1176320b8b0dSShuming Fan }
1177320b8b0dSShuming Fan
rt711_init(struct device * dev,struct regmap * sdw_regmap,struct regmap * regmap,struct sdw_slave * slave)1178320b8b0dSShuming Fan int rt711_init(struct device *dev, struct regmap *sdw_regmap,
1179320b8b0dSShuming Fan struct regmap *regmap, struct sdw_slave *slave)
1180320b8b0dSShuming Fan {
1181320b8b0dSShuming Fan struct rt711_priv *rt711;
1182320b8b0dSShuming Fan int ret;
1183320b8b0dSShuming Fan
1184320b8b0dSShuming Fan rt711 = devm_kzalloc(dev, sizeof(*rt711), GFP_KERNEL);
1185320b8b0dSShuming Fan if (!rt711)
1186320b8b0dSShuming Fan return -ENOMEM;
1187320b8b0dSShuming Fan
1188320b8b0dSShuming Fan dev_set_drvdata(dev, rt711);
1189320b8b0dSShuming Fan rt711->slave = slave;
1190320b8b0dSShuming Fan rt711->sdw_regmap = sdw_regmap;
1191320b8b0dSShuming Fan rt711->regmap = regmap;
1192320b8b0dSShuming Fan
119349ae74abSPierre-Louis Bossart regcache_cache_only(rt711->regmap, true);
119449ae74abSPierre-Louis Bossart
119574d40901SPierre-Louis Bossart mutex_init(&rt711->calibrate_mutex);
119618236370SPierre-Louis Bossart mutex_init(&rt711->disable_irq_lock);
119718236370SPierre-Louis Bossart
1198a49267a3SPierre-Louis Bossart INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler);
1199a49267a3SPierre-Louis Bossart INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler);
1200a49267a3SPierre-Louis Bossart INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
1201a49267a3SPierre-Louis Bossart
1202320b8b0dSShuming Fan /*
1203320b8b0dSShuming Fan * Mark hw_init to false
1204320b8b0dSShuming Fan * HW init will be performed when device reports present
1205320b8b0dSShuming Fan */
1206320b8b0dSShuming Fan rt711->hw_init = false;
1207320b8b0dSShuming Fan rt711->first_hw_init = false;
1208320b8b0dSShuming Fan
1209320b8b0dSShuming Fan /* JD source uses JD2 in default */
1210320b8b0dSShuming Fan rt711->jd_src = RT711_JD2;
1211320b8b0dSShuming Fan
1212320b8b0dSShuming Fan ret = devm_snd_soc_register_component(dev,
1213320b8b0dSShuming Fan &soc_codec_dev_rt711,
1214320b8b0dSShuming Fan rt711_dai,
1215320b8b0dSShuming Fan ARRAY_SIZE(rt711_dai));
1216*a8590dd7SPierre-Louis Bossart if (ret < 0)
1217*a8590dd7SPierre-Louis Bossart return ret;
1218320b8b0dSShuming Fan
1219*a8590dd7SPierre-Louis Bossart /* set autosuspend parameters */
1220*a8590dd7SPierre-Louis Bossart pm_runtime_set_autosuspend_delay(dev, 3000);
1221*a8590dd7SPierre-Louis Bossart pm_runtime_use_autosuspend(dev);
1222*a8590dd7SPierre-Louis Bossart
1223*a8590dd7SPierre-Louis Bossart /* make sure the device does not suspend immediately */
1224*a8590dd7SPierre-Louis Bossart pm_runtime_mark_last_busy(dev);
1225*a8590dd7SPierre-Louis Bossart
1226*a8590dd7SPierre-Louis Bossart pm_runtime_enable(dev);
1227*a8590dd7SPierre-Louis Bossart
1228*a8590dd7SPierre-Louis Bossart /* important note: the device is NOT tagged as 'active' and will remain
1229*a8590dd7SPierre-Louis Bossart * 'suspended' until the hardware is enumerated/initialized. This is required
1230*a8590dd7SPierre-Louis Bossart * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently
1231*a8590dd7SPierre-Louis Bossart * fail with -EACCESS because of race conditions between card creation and enumeration
1232*a8590dd7SPierre-Louis Bossart */
1233*a8590dd7SPierre-Louis Bossart
1234*a8590dd7SPierre-Louis Bossart dev_dbg(dev, "%s\n", __func__);
1235320b8b0dSShuming Fan
1236320b8b0dSShuming Fan return ret;
1237320b8b0dSShuming Fan }
1238320b8b0dSShuming Fan
rt711_io_init(struct device * dev,struct sdw_slave * slave)1239320b8b0dSShuming Fan int rt711_io_init(struct device *dev, struct sdw_slave *slave)
1240320b8b0dSShuming Fan {
1241320b8b0dSShuming Fan struct rt711_priv *rt711 = dev_get_drvdata(dev);
1242320b8b0dSShuming Fan
124318236370SPierre-Louis Bossart rt711->disable_irq = false;
124418236370SPierre-Louis Bossart
1245320b8b0dSShuming Fan if (rt711->hw_init)
1246320b8b0dSShuming Fan return 0;
1247320b8b0dSShuming Fan
1248320b8b0dSShuming Fan regcache_cache_only(rt711->regmap, false);
124949ae74abSPierre-Louis Bossart if (rt711->first_hw_init)
1250320b8b0dSShuming Fan regcache_cache_bypass(rt711->regmap, true);
1251320b8b0dSShuming Fan
1252320b8b0dSShuming Fan /*
1253*a8590dd7SPierre-Louis Bossart * PM runtime status is marked as 'active' only when a Slave reports as Attached
1254320b8b0dSShuming Fan */
1255*a8590dd7SPierre-Louis Bossart if (!rt711->first_hw_init)
1256320b8b0dSShuming Fan /* update count of parent 'active' children */
1257320b8b0dSShuming Fan pm_runtime_set_active(&slave->dev);
1258320b8b0dSShuming Fan
1259320b8b0dSShuming Fan pm_runtime_get_noresume(&slave->dev);
1260320b8b0dSShuming Fan
1261320b8b0dSShuming Fan rt711_reset(rt711->regmap);
1262320b8b0dSShuming Fan
1263320b8b0dSShuming Fan /* power on */
1264320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
1265320b8b0dSShuming Fan
1266320b8b0dSShuming Fan /* Set Pin Widget */
1267320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_MIC2, 0x25);
1268320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_HP, 0xc0);
1269320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_DMIC1, 0x20);
1270320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_DMIC2, 0x20);
1271320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_LINE1, 0x20);
1272320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_PIN_LINE2, 0x20);
1273320b8b0dSShuming Fan
1274320b8b0dSShuming Fan /* Mute HP/ADC1/ADC2 */
1275320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0xa080);
1276320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0x9080);
1277320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x6080);
1278320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x5080);
1279320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x6080);
1280320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x5080);
1281320b8b0dSShuming Fan
1282320b8b0dSShuming Fan /* Set Configuration Default */
1283320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4f12, 0x91);
1284320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4e12, 0xd6);
1285320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4d12, 0x11);
1286320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4c12, 0x20);
1287320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4f13, 0x91);
1288320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4e13, 0xd6);
1289320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4d13, 0x11);
1290320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4c13, 0x21);
1291320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4c21, 0xf0);
1292320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4d21, 0x11);
1293320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4e21, 0x11);
1294320b8b0dSShuming Fan regmap_write(rt711->regmap, 0x4f21, 0x01);
1295320b8b0dSShuming Fan
1296320b8b0dSShuming Fan /* Data port arrangement */
1297320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1298320b8b0dSShuming Fan RT711_TX_RX_MUX_CTL, 0x0154);
1299320b8b0dSShuming Fan
1300320b8b0dSShuming Fan /* Set index */
1301320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1302320b8b0dSShuming Fan RT711_DIGITAL_MISC_CTRL4, 0x201b);
1303320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1304320b8b0dSShuming Fan RT711_COMBO_JACK_AUTO_CTL1, 0x5089);
1305320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1306320b8b0dSShuming Fan RT711_VREFOUT_CTL, 0x5064);
1307320b8b0dSShuming Fan rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
1308320b8b0dSShuming Fan RT711_INLINE_CMD_CTL, 0xd249);
1309320b8b0dSShuming Fan
1310320b8b0dSShuming Fan /* Finish Initial Settings, set power to D3 */
1311320b8b0dSShuming Fan regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
1312320b8b0dSShuming Fan
1313320b8b0dSShuming Fan if (rt711->first_hw_init)
1314320b8b0dSShuming Fan rt711_calibration(rt711);
1315a49267a3SPierre-Louis Bossart else
1316320b8b0dSShuming Fan schedule_work(&rt711->calibration_work);
1317320b8b0dSShuming Fan
1318320b8b0dSShuming Fan /*
1319320b8b0dSShuming Fan * if set_jack callback occurred early than io_init,
1320320b8b0dSShuming Fan * we set up the jack detection function now
1321320b8b0dSShuming Fan */
1322320b8b0dSShuming Fan if (rt711->hs_jack)
1323320b8b0dSShuming Fan rt711_jack_init(rt711);
1324320b8b0dSShuming Fan
1325320b8b0dSShuming Fan if (rt711->first_hw_init) {
1326320b8b0dSShuming Fan regcache_cache_bypass(rt711->regmap, false);
1327320b8b0dSShuming Fan regcache_mark_dirty(rt711->regmap);
1328320b8b0dSShuming Fan } else
1329320b8b0dSShuming Fan rt711->first_hw_init = true;
1330320b8b0dSShuming Fan
1331320b8b0dSShuming Fan /* Mark Slave initialization complete */
1332320b8b0dSShuming Fan rt711->hw_init = true;
1333320b8b0dSShuming Fan
1334320b8b0dSShuming Fan pm_runtime_mark_last_busy(&slave->dev);
1335320b8b0dSShuming Fan pm_runtime_put_autosuspend(&slave->dev);
1336320b8b0dSShuming Fan
1337320b8b0dSShuming Fan dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
1338320b8b0dSShuming Fan return 0;
1339320b8b0dSShuming Fan }
1340320b8b0dSShuming Fan
1341320b8b0dSShuming Fan MODULE_DESCRIPTION("ASoC RT711 SDW driver");
1342320b8b0dSShuming Fan MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
1343320b8b0dSShuming Fan MODULE_LICENSE("GPL");
1344