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