1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // rt711-sdca.c -- rt711 SDCA ALSA SoC audio driver |
4 | // |
5 | // Copyright(c) 2021 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/soundwire/sdw_registers.h> |
16 | #include <linux/slab.h> |
17 | #include <linux/bitops.h> |
18 | #include <sound/core.h> |
19 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> |
21 | #include <sound/sdw.h> |
22 | #include <sound/soc-dapm.h> |
23 | #include <sound/initval.h> |
24 | #include <sound/tlv.h> |
25 | #include <sound/jack.h> |
26 | |
27 | #include "rt711-sdca.h" |
28 | |
29 | static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711, |
30 | unsigned int nid, unsigned int reg, unsigned int value) |
31 | { |
32 | int ret; |
33 | struct regmap *regmap = rt711->mbq_regmap; |
34 | unsigned int addr = (nid << 20) | reg; |
35 | |
36 | ret = regmap_write(map: regmap, reg: addr, val: value); |
37 | if (ret < 0) |
38 | dev_err(&rt711->slave->dev, |
39 | "%s: Failed to set private value: %06x <= %04x ret=%d\n" , |
40 | __func__, addr, value, ret); |
41 | |
42 | return ret; |
43 | } |
44 | |
45 | static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711, |
46 | unsigned int nid, unsigned int reg, unsigned int *value) |
47 | { |
48 | int ret; |
49 | struct regmap *regmap = rt711->mbq_regmap; |
50 | unsigned int addr = (nid << 20) | reg; |
51 | |
52 | ret = regmap_read(map: regmap, reg: addr, val: value); |
53 | if (ret < 0) |
54 | dev_err(&rt711->slave->dev, |
55 | "%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_sdca_index_update_bits(struct rt711_sdca_priv *rt711, |
62 | unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) |
63 | { |
64 | unsigned int tmp; |
65 | int ret; |
66 | |
67 | ret = rt711_sdca_index_read(rt711, nid, reg, value: &tmp); |
68 | if (ret < 0) |
69 | return ret; |
70 | |
71 | set_mask_bits(&tmp, mask, val); |
72 | return rt711_sdca_index_write(rt711, nid, reg, value: tmp); |
73 | } |
74 | |
75 | static void rt711_sdca_reset(struct rt711_sdca_priv *rt711) |
76 | { |
77 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
78 | RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET, |
79 | RT711_HIDDEN_REG_SW_RESET); |
80 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
81 | RT711_HDA_LEGACY_RESET_CTL, mask: 0x1, val: 0x1); |
82 | } |
83 | |
84 | static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711) |
85 | { |
86 | unsigned int val, loop_rc = 0, loop_dc = 0; |
87 | struct device *dev; |
88 | struct regmap *regmap = rt711->regmap; |
89 | int chk_cnt = 100; |
90 | int ret = 0; |
91 | |
92 | mutex_lock(&rt711->calibrate_mutex); |
93 | dev = regmap_get_device(map: regmap); |
94 | |
95 | regmap_read(map: rt711->regmap, RT711_RC_CAL_STATUS, val: &val); |
96 | /* RC calibration */ |
97 | if (!(val & 0x40)) |
98 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, |
99 | RT711_MISC_POWER_CTL0, mask: 0x0010, val: 0x0010); |
100 | |
101 | for (loop_rc = 0; loop_rc < chk_cnt && !(val & 0x40); loop_rc++) { |
102 | usleep_range(min: 10000, max: 11000); |
103 | ret = regmap_read(map: rt711->regmap, RT711_RC_CAL_STATUS, val: &val); |
104 | if (ret < 0) |
105 | goto _cali_fail_; |
106 | } |
107 | if (loop_rc == chk_cnt) |
108 | dev_err(dev, "%s, RC calibration time-out!\n" , __func__); |
109 | |
110 | /* HP calibration by manual mode setting */ |
111 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
112 | RT711_FSM_CTL, mask: 0x2000, val: 0x2000); |
113 | |
114 | /* Calibration manual mode */ |
115 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
116 | RT711_FSM_CTL, mask: 0xf, RT711_CALI_CTL); |
117 | |
118 | /* reset HP calibration */ |
119 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, |
120 | RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, val: 0x00); |
121 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, |
122 | RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, |
123 | RT711_DAC_DC_FORCE_CALI_RST); |
124 | |
125 | /* cal_clk_en_reg */ |
126 | if (rt711->hw_ver == RT711_VER_VD0) |
127 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, |
128 | RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_CLK_EN, |
129 | RT711_DAC_DC_CALI_CLK_EN); |
130 | |
131 | /* trigger */ |
132 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, |
133 | RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER, |
134 | RT711_DAC_DC_CALI_TRIGGER); |
135 | |
136 | /* wait for calibration process */ |
137 | rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, |
138 | RT711_DAC_DC_CALI_CTL1, value: &val); |
139 | |
140 | for (loop_dc = 0; loop_dc < chk_cnt && |
141 | (val & RT711_DAC_DC_CALI_TRIGGER); loop_dc++) { |
142 | usleep_range(min: 10000, max: 11000); |
143 | ret = rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, |
144 | RT711_DAC_DC_CALI_CTL1, value: &val); |
145 | if (ret < 0) |
146 | goto _cali_fail_; |
147 | } |
148 | if (loop_dc == chk_cnt) |
149 | dev_err(dev, "%s, calibration time-out!\n" , __func__); |
150 | |
151 | if (loop_dc == chk_cnt || loop_rc == chk_cnt) |
152 | ret = -ETIMEDOUT; |
153 | |
154 | _cali_fail_: |
155 | /* enable impedance sense */ |
156 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
157 | RT711_FSM_CTL, RT711_FSM_IMP_EN, RT711_FSM_IMP_EN); |
158 | |
159 | /* release HP-JD and trigger FSM */ |
160 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
161 | RT711_DIGITAL_MISC_CTRL4, value: 0x201b); |
162 | |
163 | mutex_unlock(lock: &rt711->calibrate_mutex); |
164 | dev_dbg(dev, "%s calibration complete, ret=%d\n" , __func__, ret); |
165 | return ret; |
166 | } |
167 | |
168 | static unsigned int rt711_sdca_button_detect(struct rt711_sdca_priv *rt711) |
169 | { |
170 | unsigned int btn_type = 0, offset, idx, val, owner; |
171 | int ret; |
172 | unsigned char buf[3]; |
173 | |
174 | /* get current UMP message owner */ |
175 | ret = regmap_read(map: rt711->regmap, |
176 | SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), |
177 | val: &owner); |
178 | if (ret < 0) |
179 | return 0; |
180 | |
181 | /* if owner is device then there is no button event from device */ |
182 | if (owner == 1) |
183 | return 0; |
184 | |
185 | /* read UMP message offset */ |
186 | ret = regmap_read(map: rt711->regmap, |
187 | SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), |
188 | val: &offset); |
189 | if (ret < 0) |
190 | goto _end_btn_det_; |
191 | |
192 | for (idx = 0; idx < sizeof(buf); idx++) { |
193 | ret = regmap_read(map: rt711->regmap, |
194 | RT711_BUF_ADDR_HID1 + offset + idx, val: &val); |
195 | if (ret < 0) |
196 | goto _end_btn_det_; |
197 | buf[idx] = val & 0xff; |
198 | } |
199 | |
200 | if (buf[0] == 0x11) { |
201 | switch (buf[1] & 0xf0) { |
202 | case 0x10: |
203 | btn_type |= SND_JACK_BTN_2; |
204 | break; |
205 | case 0x20: |
206 | btn_type |= SND_JACK_BTN_3; |
207 | break; |
208 | case 0x40: |
209 | btn_type |= SND_JACK_BTN_0; |
210 | break; |
211 | case 0x80: |
212 | btn_type |= SND_JACK_BTN_1; |
213 | break; |
214 | } |
215 | switch (buf[2]) { |
216 | case 0x01: |
217 | case 0x10: |
218 | btn_type |= SND_JACK_BTN_2; |
219 | break; |
220 | case 0x02: |
221 | case 0x20: |
222 | btn_type |= SND_JACK_BTN_3; |
223 | break; |
224 | case 0x04: |
225 | case 0x40: |
226 | btn_type |= SND_JACK_BTN_0; |
227 | break; |
228 | case 0x08: |
229 | case 0x80: |
230 | btn_type |= SND_JACK_BTN_1; |
231 | break; |
232 | } |
233 | } |
234 | |
235 | _end_btn_det_: |
236 | /* Host is owner, so set back to device */ |
237 | if (owner == 0) |
238 | /* set owner to device */ |
239 | regmap_write(map: rt711->regmap, |
240 | SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, |
241 | RT711_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE, 0), val: 0x01); |
242 | |
243 | return btn_type; |
244 | } |
245 | |
246 | static int rt711_sdca_headset_detect(struct rt711_sdca_priv *rt711) |
247 | { |
248 | unsigned int det_mode; |
249 | int ret; |
250 | |
251 | /* get detected_mode */ |
252 | ret = regmap_read(map: rt711->regmap, |
253 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), |
254 | val: &det_mode); |
255 | if (ret < 0) |
256 | goto io_error; |
257 | |
258 | switch (det_mode) { |
259 | case 0x00: |
260 | rt711->jack_type = 0; |
261 | break; |
262 | case 0x03: |
263 | rt711->jack_type = SND_JACK_HEADPHONE; |
264 | break; |
265 | case 0x05: |
266 | rt711->jack_type = SND_JACK_HEADSET; |
267 | break; |
268 | } |
269 | |
270 | /* write selected_mode */ |
271 | if (det_mode) { |
272 | ret = regmap_write(map: rt711->regmap, |
273 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_SELECTED_MODE, 0), |
274 | val: det_mode); |
275 | if (ret < 0) |
276 | goto io_error; |
277 | } |
278 | |
279 | dev_dbg(&rt711->slave->dev, |
280 | "%s, detected_mode=0x%x\n" , __func__, det_mode); |
281 | |
282 | return 0; |
283 | |
284 | io_error: |
285 | pr_err_ratelimited("IO error in %s, ret %d\n" , __func__, ret); |
286 | return ret; |
287 | } |
288 | |
289 | static void rt711_sdca_jack_detect_handler(struct work_struct *work) |
290 | { |
291 | struct rt711_sdca_priv *rt711 = |
292 | container_of(work, struct rt711_sdca_priv, jack_detect_work.work); |
293 | int btn_type = 0, ret; |
294 | |
295 | if (!rt711->hs_jack) |
296 | return; |
297 | |
298 | if (!snd_soc_card_is_instantiated(card: rt711->component->card)) |
299 | return; |
300 | |
301 | /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ |
302 | if (rt711->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) { |
303 | ret = rt711_sdca_headset_detect(rt711); |
304 | if (ret < 0) |
305 | return; |
306 | } |
307 | |
308 | /* SDW_SCP_SDCA_INT_SDCA_8 is used for button detection */ |
309 | if (rt711->scp_sdca_stat2 & SDW_SCP_SDCA_INT_SDCA_8) |
310 | btn_type = rt711_sdca_button_detect(rt711); |
311 | |
312 | if (rt711->jack_type == 0) |
313 | btn_type = 0; |
314 | |
315 | dev_dbg(&rt711->slave->dev, |
316 | "in %s, jack_type=0x%x\n" , __func__, rt711->jack_type); |
317 | dev_dbg(&rt711->slave->dev, |
318 | "in %s, btn_type=0x%x\n" , __func__, btn_type); |
319 | dev_dbg(&rt711->slave->dev, |
320 | "in %s, scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n" , __func__, |
321 | rt711->scp_sdca_stat1, rt711->scp_sdca_stat2); |
322 | |
323 | snd_soc_jack_report(jack: rt711->hs_jack, status: rt711->jack_type | btn_type, |
324 | mask: SND_JACK_HEADSET | |
325 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
326 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
327 | |
328 | if (btn_type) { |
329 | /* button released */ |
330 | snd_soc_jack_report(jack: rt711->hs_jack, status: rt711->jack_type, |
331 | mask: SND_JACK_HEADSET | |
332 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
333 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
334 | |
335 | mod_delayed_work(wq: system_power_efficient_wq, |
336 | dwork: &rt711->jack_btn_check_work, delay: msecs_to_jiffies(m: 200)); |
337 | } |
338 | } |
339 | |
340 | static void rt711_sdca_btn_check_handler(struct work_struct *work) |
341 | { |
342 | struct rt711_sdca_priv *rt711 = |
343 | container_of(work, struct rt711_sdca_priv, jack_btn_check_work.work); |
344 | int btn_type = 0, ret, idx; |
345 | unsigned int det_mode, offset, val; |
346 | unsigned char buf[3]; |
347 | |
348 | ret = regmap_read(map: rt711->regmap, |
349 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), |
350 | val: &det_mode); |
351 | if (ret < 0) |
352 | goto io_error; |
353 | |
354 | /* pin attached */ |
355 | if (det_mode) { |
356 | /* read UMP message offset */ |
357 | ret = regmap_read(map: rt711->regmap, |
358 | SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), |
359 | val: &offset); |
360 | if (ret < 0) |
361 | goto io_error; |
362 | |
363 | for (idx = 0; idx < sizeof(buf); idx++) { |
364 | ret = regmap_read(map: rt711->regmap, |
365 | RT711_BUF_ADDR_HID1 + offset + idx, val: &val); |
366 | if (ret < 0) |
367 | goto io_error; |
368 | buf[idx] = val & 0xff; |
369 | } |
370 | |
371 | if (buf[0] == 0x11) { |
372 | switch (buf[1] & 0xf0) { |
373 | case 0x10: |
374 | btn_type |= SND_JACK_BTN_2; |
375 | break; |
376 | case 0x20: |
377 | btn_type |= SND_JACK_BTN_3; |
378 | break; |
379 | case 0x40: |
380 | btn_type |= SND_JACK_BTN_0; |
381 | break; |
382 | case 0x80: |
383 | btn_type |= SND_JACK_BTN_1; |
384 | break; |
385 | } |
386 | switch (buf[2]) { |
387 | case 0x01: |
388 | case 0x10: |
389 | btn_type |= SND_JACK_BTN_2; |
390 | break; |
391 | case 0x02: |
392 | case 0x20: |
393 | btn_type |= SND_JACK_BTN_3; |
394 | break; |
395 | case 0x04: |
396 | case 0x40: |
397 | btn_type |= SND_JACK_BTN_0; |
398 | break; |
399 | case 0x08: |
400 | case 0x80: |
401 | btn_type |= SND_JACK_BTN_1; |
402 | break; |
403 | } |
404 | } |
405 | } else |
406 | rt711->jack_type = 0; |
407 | |
408 | dev_dbg(&rt711->slave->dev, "%s, btn_type=0x%x\n" , __func__, btn_type); |
409 | snd_soc_jack_report(jack: rt711->hs_jack, status: rt711->jack_type | btn_type, |
410 | mask: SND_JACK_HEADSET | |
411 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
412 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
413 | |
414 | if (btn_type) { |
415 | /* button released */ |
416 | snd_soc_jack_report(jack: rt711->hs_jack, status: rt711->jack_type, |
417 | mask: SND_JACK_HEADSET | |
418 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
419 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
420 | |
421 | mod_delayed_work(wq: system_power_efficient_wq, |
422 | dwork: &rt711->jack_btn_check_work, delay: msecs_to_jiffies(m: 200)); |
423 | } |
424 | |
425 | return; |
426 | |
427 | io_error: |
428 | pr_err_ratelimited("IO error in %s, ret %d\n" , __func__, ret); |
429 | } |
430 | |
431 | static void rt711_sdca_jack_init(struct rt711_sdca_priv *rt711) |
432 | { |
433 | mutex_lock(&rt711->calibrate_mutex); |
434 | |
435 | if (rt711->hs_jack) { |
436 | /* Enable HID1 event & set button RTC mode */ |
437 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
438 | RT711_PUSH_BTN_INT_CTL6, mask: 0x80f0, val: 0x8000); |
439 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
440 | RT711_PUSH_BTN_INT_CTL2, mask: 0x11dd, val: 0x11dd); |
441 | rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, |
442 | RT711_PUSH_BTN_INT_CTL7, value: 0xffff); |
443 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
444 | RT711_PUSH_BTN_INT_CTL9, mask: 0xf000, val: 0x0000); |
445 | |
446 | /* GE_mode_change_event_en & Hid1_push_button_event_en */ |
447 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
448 | RT711_GE_MODE_RELATED_CTL, mask: 0x0c00, val: 0x0c00); |
449 | |
450 | switch (rt711->jd_src) { |
451 | case RT711_JD1: |
452 | /* default settings was already for JD1 */ |
453 | break; |
454 | case RT711_JD2: |
455 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
456 | RT711_JD_CTL1, RT711_JD2_DIGITAL_MODE_SEL, |
457 | RT711_JD2_DIGITAL_MODE_SEL); |
458 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
459 | RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2, |
460 | RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2); |
461 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
462 | RT711_CC_DET1, |
463 | RT711_HP_JD_FINAL_RESULT_CTL_JD12, |
464 | RT711_HP_JD_FINAL_RESULT_CTL_JD12); |
465 | break; |
466 | case RT711_JD2_100K: |
467 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
468 | RT711_COMBO_JACK_AUTO_CTL3, value: 0xa47e); |
469 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
470 | RT711_JD_CTL1, RT711_JD2_DIGITAL_MODE_SEL, |
471 | RT711_JD2_DIGITAL_MODE_SEL); |
472 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
473 | RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP | |
474 | RT711_JD2_2PORT_100K_DECODE_MASK | RT711_HP_JD_SEL_JD2, |
475 | RT711_JD2_2PORT_100K_DECODE_HP | RT711_HP_JD_SEL_JD2); |
476 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
477 | RT711_CC_DET1, |
478 | RT711_HP_JD_FINAL_RESULT_CTL_JD12 | RT711_POW_CC1_AGPI, |
479 | RT711_HP_JD_FINAL_RESULT_CTL_JD12 | RT711_POW_CC1_AGPI_OFF); |
480 | break; |
481 | default: |
482 | dev_warn(rt711->component->dev, "Wrong JD source\n" ); |
483 | break; |
484 | } |
485 | |
486 | /* set SCP_SDCA_IntMask1[0]=1 */ |
487 | sdw_write_no_pm(slave: rt711->slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0); |
488 | /* set SCP_SDCA_IntMask2[0]=1 */ |
489 | sdw_write_no_pm(slave: rt711->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); |
490 | dev_dbg(&rt711->slave->dev, "in %s enable\n" , __func__); |
491 | } else { |
492 | /* disable HID 1/2 event */ |
493 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
494 | RT711_GE_MODE_RELATED_CTL, mask: 0x0c00, val: 0x0000); |
495 | |
496 | dev_dbg(&rt711->slave->dev, "in %s disable\n" , __func__); |
497 | } |
498 | |
499 | mutex_unlock(lock: &rt711->calibrate_mutex); |
500 | } |
501 | |
502 | static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, |
503 | struct snd_soc_jack *hs_jack, void *data) |
504 | { |
505 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
506 | int ret; |
507 | |
508 | rt711->hs_jack = hs_jack; |
509 | |
510 | /* we can only resume if the device was initialized at least once */ |
511 | if (!rt711->first_hw_init) |
512 | return 0; |
513 | |
514 | ret = pm_runtime_resume_and_get(dev: component->dev); |
515 | if (ret < 0) { |
516 | if (ret != -EACCES) { |
517 | dev_err(component->dev, "%s: failed to resume %d\n" , __func__, ret); |
518 | return ret; |
519 | } |
520 | |
521 | /* pm_runtime not enabled yet */ |
522 | dev_dbg(component->dev, "%s: skipping jack init for now\n" , __func__); |
523 | return 0; |
524 | } |
525 | |
526 | rt711_sdca_jack_init(rt711); |
527 | |
528 | pm_runtime_mark_last_busy(dev: component->dev); |
529 | pm_runtime_put_autosuspend(dev: component->dev); |
530 | |
531 | return 0; |
532 | } |
533 | |
534 | /* For SDCA control DAC/ADC Gain */ |
535 | static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, |
536 | struct snd_ctl_elem_value *ucontrol) |
537 | { |
538 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
539 | struct soc_mixer_control *mc = |
540 | (struct soc_mixer_control *)kcontrol->private_value; |
541 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
542 | unsigned int read_l, read_r, gain_l_val, gain_r_val; |
543 | unsigned int i, adc_vol_flag = 0, changed = 0; |
544 | unsigned int lvalue, rvalue; |
545 | |
546 | if (strstr(ucontrol->id.name, "FU1E Capture Volume" ) || |
547 | strstr(ucontrol->id.name, "FU0F Capture Volume" )) |
548 | adc_vol_flag = 1; |
549 | |
550 | regmap_read(map: rt711->mbq_regmap, reg: mc->reg, val: &lvalue); |
551 | regmap_read(map: rt711->mbq_regmap, reg: mc->rreg, val: &rvalue); |
552 | |
553 | /* control value to 2's complement value */ |
554 | /* L Channel */ |
555 | gain_l_val = ucontrol->value.integer.value[0]; |
556 | if (gain_l_val > mc->max) |
557 | gain_l_val = mc->max; |
558 | read_l = gain_l_val; |
559 | |
560 | if (mc->shift == 8) /* boost gain */ |
561 | gain_l_val = (gain_l_val * 10) << mc->shift; |
562 | else { /* ADC/DAC gain */ |
563 | if (adc_vol_flag && gain_l_val > mc->shift) |
564 | gain_l_val = (gain_l_val - mc->shift) * 75; |
565 | else |
566 | gain_l_val = (mc->shift - gain_l_val) * 75; |
567 | gain_l_val <<= 8; |
568 | gain_l_val /= 100; |
569 | if (!(adc_vol_flag && read_l > mc->shift)) { |
570 | gain_l_val = ~gain_l_val; |
571 | gain_l_val += 1; |
572 | } |
573 | gain_l_val &= 0xffff; |
574 | } |
575 | |
576 | /* R Channel */ |
577 | gain_r_val = ucontrol->value.integer.value[1]; |
578 | if (gain_r_val > mc->max) |
579 | gain_r_val = mc->max; |
580 | read_r = gain_r_val; |
581 | |
582 | if (mc->shift == 8) /* boost gain */ |
583 | gain_r_val = (gain_r_val * 10) << mc->shift; |
584 | else { /* ADC/DAC gain */ |
585 | if (adc_vol_flag && gain_r_val > mc->shift) |
586 | gain_r_val = (gain_r_val - mc->shift) * 75; |
587 | else |
588 | gain_r_val = (mc->shift - gain_r_val) * 75; |
589 | gain_r_val <<= 8; |
590 | gain_r_val /= 100; |
591 | if (!(adc_vol_flag && read_r > mc->shift)) { |
592 | gain_r_val = ~gain_r_val; |
593 | gain_r_val += 1; |
594 | } |
595 | gain_r_val &= 0xffff; |
596 | } |
597 | |
598 | if (lvalue != gain_l_val || rvalue != gain_r_val) |
599 | changed = 1; |
600 | else |
601 | return 0; |
602 | |
603 | for (i = 0; i < 3; i++) { /* retry 3 times at most */ |
604 | /* Lch*/ |
605 | regmap_write(map: rt711->mbq_regmap, reg: mc->reg, val: gain_l_val); |
606 | |
607 | /* Rch */ |
608 | regmap_write(map: rt711->mbq_regmap, reg: mc->rreg, val: gain_r_val); |
609 | |
610 | regmap_read(map: rt711->mbq_regmap, reg: mc->reg, val: &read_l); |
611 | regmap_read(map: rt711->mbq_regmap, reg: mc->rreg, val: &read_r); |
612 | if (read_r == gain_r_val && read_l == gain_l_val) |
613 | break; |
614 | } |
615 | |
616 | return i == 3 ? -EIO : changed; |
617 | } |
618 | |
619 | static int rt711_sdca_set_gain_get(struct snd_kcontrol *kcontrol, |
620 | struct snd_ctl_elem_value *ucontrol) |
621 | { |
622 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
623 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
624 | struct soc_mixer_control *mc = |
625 | (struct soc_mixer_control *)kcontrol->private_value; |
626 | unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; |
627 | unsigned int adc_vol_flag = 0, neg_flag = 0; |
628 | |
629 | if (strstr(ucontrol->id.name, "FU1E Capture Volume" ) || |
630 | strstr(ucontrol->id.name, "FU0F Capture Volume" )) |
631 | adc_vol_flag = 1; |
632 | |
633 | regmap_read(map: rt711->mbq_regmap, reg: mc->reg, val: &read_l); |
634 | regmap_read(map: rt711->mbq_regmap, reg: mc->rreg, val: &read_r); |
635 | |
636 | /* 2's complement value to control value */ |
637 | if (mc->shift == 8) /* boost gain */ |
638 | ctl_l = (read_l >> mc->shift) / 10; |
639 | else { /* ADC/DAC gain */ |
640 | ctl_l = read_l; |
641 | if (read_l & BIT(15)) { |
642 | ctl_l = 0xffff & ~(read_l - 1); |
643 | neg_flag = 1; |
644 | } |
645 | ctl_l *= 100; |
646 | ctl_l >>= 8; |
647 | if (adc_vol_flag) { |
648 | if (neg_flag) |
649 | ctl_l = mc->shift - (ctl_l / 75); |
650 | else |
651 | ctl_l = mc->shift + (ctl_l / 75); |
652 | } else |
653 | ctl_l = mc->max - (ctl_l / 75); |
654 | } |
655 | |
656 | neg_flag = 0; |
657 | if (read_l != read_r) { |
658 | if (mc->shift == 8) /* boost gain */ |
659 | ctl_r = (read_r >> mc->shift) / 10; |
660 | else { /* ADC/DAC gain */ |
661 | ctl_r = read_r; |
662 | if (read_r & BIT(15)) { |
663 | ctl_r = 0xffff & ~(read_r - 1); |
664 | neg_flag = 1; |
665 | } |
666 | ctl_r *= 100; |
667 | ctl_r >>= 8; |
668 | if (adc_vol_flag) { |
669 | if (neg_flag) |
670 | ctl_r = mc->shift - (ctl_r / 75); |
671 | else |
672 | ctl_r = mc->shift + (ctl_r / 75); |
673 | } else |
674 | ctl_r = mc->max - (ctl_r / 75); |
675 | } |
676 | } else |
677 | ctl_r = ctl_l; |
678 | |
679 | ucontrol->value.integer.value[0] = ctl_l; |
680 | ucontrol->value.integer.value[1] = ctl_r; |
681 | |
682 | return 0; |
683 | } |
684 | |
685 | static int rt711_sdca_set_fu0f_capture_ctl(struct rt711_sdca_priv *rt711) |
686 | { |
687 | int err; |
688 | unsigned int ch_l, ch_r; |
689 | |
690 | ch_l = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_l_mute) ? 0x01 : 0x00; |
691 | ch_r = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_r_mute) ? 0x01 : 0x00; |
692 | |
693 | err = regmap_write(map: rt711->regmap, |
694 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, |
695 | RT711_SDCA_CTL_FU_MUTE, CH_L), val: ch_l); |
696 | if (err < 0) |
697 | return err; |
698 | |
699 | err = regmap_write(map: rt711->regmap, |
700 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, |
701 | RT711_SDCA_CTL_FU_MUTE, CH_R), val: ch_r); |
702 | if (err < 0) |
703 | return err; |
704 | |
705 | return 0; |
706 | } |
707 | |
708 | static int rt711_sdca_set_fu1e_capture_ctl(struct rt711_sdca_priv *rt711) |
709 | { |
710 | int err; |
711 | unsigned int ch_l, ch_r; |
712 | |
713 | ch_l = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_l_mute) ? 0x01 : 0x00; |
714 | ch_r = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_r_mute) ? 0x01 : 0x00; |
715 | |
716 | err = regmap_write(map: rt711->regmap, |
717 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, |
718 | RT711_SDCA_CTL_FU_MUTE, CH_L), val: ch_l); |
719 | if (err < 0) |
720 | return err; |
721 | |
722 | err = regmap_write(map: rt711->regmap, |
723 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, |
724 | RT711_SDCA_CTL_FU_MUTE, CH_R), val: ch_r); |
725 | if (err < 0) |
726 | return err; |
727 | |
728 | return 0; |
729 | } |
730 | |
731 | static int rt711_sdca_fu1e_capture_get(struct snd_kcontrol *kcontrol, |
732 | struct snd_ctl_elem_value *ucontrol) |
733 | { |
734 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
735 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
736 | |
737 | ucontrol->value.integer.value[0] = !rt711->fu1e_mixer_l_mute; |
738 | ucontrol->value.integer.value[1] = !rt711->fu1e_mixer_r_mute; |
739 | return 0; |
740 | } |
741 | |
742 | static int rt711_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol, |
743 | struct snd_ctl_elem_value *ucontrol) |
744 | { |
745 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
746 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
747 | int err, changed = 0; |
748 | |
749 | if (rt711->fu1e_mixer_l_mute != !ucontrol->value.integer.value[0] || |
750 | rt711->fu1e_mixer_r_mute != !ucontrol->value.integer.value[1]) |
751 | changed = 1; |
752 | |
753 | rt711->fu1e_mixer_l_mute = !ucontrol->value.integer.value[0]; |
754 | rt711->fu1e_mixer_r_mute = !ucontrol->value.integer.value[1]; |
755 | err = rt711_sdca_set_fu1e_capture_ctl(rt711); |
756 | if (err < 0) |
757 | return err; |
758 | |
759 | return changed; |
760 | } |
761 | |
762 | static int rt711_sdca_fu0f_capture_get(struct snd_kcontrol *kcontrol, |
763 | struct snd_ctl_elem_value *ucontrol) |
764 | { |
765 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
766 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
767 | |
768 | ucontrol->value.integer.value[0] = !rt711->fu0f_mixer_l_mute; |
769 | ucontrol->value.integer.value[1] = !rt711->fu0f_mixer_r_mute; |
770 | return 0; |
771 | } |
772 | |
773 | static int rt711_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol, |
774 | struct snd_ctl_elem_value *ucontrol) |
775 | { |
776 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
777 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
778 | int err, changed = 0; |
779 | |
780 | if (rt711->fu0f_mixer_l_mute != !ucontrol->value.integer.value[0] || |
781 | rt711->fu0f_mixer_r_mute != !ucontrol->value.integer.value[1]) |
782 | changed = 1; |
783 | |
784 | rt711->fu0f_mixer_l_mute = !ucontrol->value.integer.value[0]; |
785 | rt711->fu0f_mixer_r_mute = !ucontrol->value.integer.value[1]; |
786 | err = rt711_sdca_set_fu0f_capture_ctl(rt711); |
787 | if (err < 0) |
788 | return err; |
789 | |
790 | return changed; |
791 | } |
792 | |
793 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); |
794 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); |
795 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); |
796 | |
797 | static const struct snd_kcontrol_new rt711_sdca_snd_controls[] = { |
798 | SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume" , |
799 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_L), |
800 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R), |
801 | 0x57, 0x57, 0, |
802 | rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, out_vol_tlv), |
803 | SOC_DOUBLE_EXT("FU1E Capture Switch" , SND_SOC_NOPM, 0, 1, 1, 0, |
804 | rt711_sdca_fu1e_capture_get, rt711_sdca_fu1e_capture_put), |
805 | SOC_DOUBLE_EXT("FU0F Capture Switch" , SND_SOC_NOPM, 0, 1, 1, 0, |
806 | rt711_sdca_fu0f_capture_get, rt711_sdca_fu0f_capture_put), |
807 | SOC_DOUBLE_R_EXT_TLV("FU1E Capture Volume" , |
808 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L), |
809 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R), |
810 | 0x17, 0x3f, 0, |
811 | rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), |
812 | SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume" , |
813 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_L), |
814 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_R), |
815 | 0x17, 0x3f, 0, |
816 | rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), |
817 | SOC_DOUBLE_R_EXT_TLV("FU44 Gain Volume" , |
818 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), |
819 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), |
820 | 8, 3, 0, |
821 | rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), |
822 | SOC_DOUBLE_R_EXT_TLV("FU15 Gain Volume" , |
823 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), |
824 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), |
825 | 8, 3, 0, |
826 | rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), |
827 | }; |
828 | |
829 | static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol, |
830 | struct snd_ctl_elem_value *ucontrol) |
831 | { |
832 | struct snd_soc_component *component = |
833 | snd_soc_dapm_kcontrol_component(kcontrol); |
834 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
835 | unsigned int val = 0, mask_sft; |
836 | |
837 | if (strstr(ucontrol->id.name, "ADC 22 Mux" )) |
838 | mask_sft = 10; |
839 | else if (strstr(ucontrol->id.name, "ADC 23 Mux" )) |
840 | mask_sft = 13; |
841 | else |
842 | return -EINVAL; |
843 | |
844 | rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, |
845 | RT711_HDA_LEGACY_MUX_CTL1, value: &val); |
846 | |
847 | ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; |
848 | |
849 | return 0; |
850 | } |
851 | |
852 | static int rt711_sdca_mux_put(struct snd_kcontrol *kcontrol, |
853 | struct snd_ctl_elem_value *ucontrol) |
854 | { |
855 | struct snd_soc_component *component = |
856 | snd_soc_dapm_kcontrol_component(kcontrol); |
857 | struct snd_soc_dapm_context *dapm = |
858 | snd_soc_dapm_kcontrol_dapm(kcontrol); |
859 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
860 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
861 | unsigned int *item = ucontrol->value.enumerated.item; |
862 | unsigned int val, val2 = 0, change, mask_sft; |
863 | |
864 | if (item[0] >= e->items) |
865 | return -EINVAL; |
866 | |
867 | if (strstr(ucontrol->id.name, "ADC 22 Mux" )) |
868 | mask_sft = 10; |
869 | else if (strstr(ucontrol->id.name, "ADC 23 Mux" )) |
870 | mask_sft = 13; |
871 | else |
872 | return -EINVAL; |
873 | |
874 | val = snd_soc_enum_item_to_val(e, item: item[0]) << e->shift_l; |
875 | |
876 | rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, |
877 | RT711_HDA_LEGACY_MUX_CTL1, value: &val2); |
878 | val2 = (val2 >> mask_sft) & 0x7; |
879 | |
880 | if (val == val2) |
881 | change = 0; |
882 | else |
883 | change = 1; |
884 | |
885 | if (change) |
886 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
887 | RT711_HDA_LEGACY_MUX_CTL1, mask: 0x7 << mask_sft, |
888 | val: val << mask_sft); |
889 | |
890 | snd_soc_dapm_mux_update_power(dapm, kcontrol, |
891 | mux: item[0], e, NULL); |
892 | |
893 | return change; |
894 | } |
895 | |
896 | static const char * const adc_mux_text[] = { |
897 | "MIC2" , |
898 | "LINE1" , |
899 | "LINE2" , |
900 | "DMIC" , |
901 | }; |
902 | |
903 | static SOC_ENUM_SINGLE_DECL( |
904 | rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text); |
905 | |
906 | static SOC_ENUM_SINGLE_DECL( |
907 | rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text); |
908 | |
909 | static const struct snd_kcontrol_new rt711_sdca_adc22_mux = |
910 | SOC_DAPM_ENUM_EXT("ADC 22 Mux" , rt711_adc22_enum, |
911 | rt711_sdca_mux_get, rt711_sdca_mux_put); |
912 | |
913 | static const struct snd_kcontrol_new rt711_sdca_adc23_mux = |
914 | SOC_DAPM_ENUM_EXT("ADC 23 Mux" , rt711_adc23_enum, |
915 | rt711_sdca_mux_get, rt711_sdca_mux_put); |
916 | |
917 | static int rt711_sdca_fu05_event(struct snd_soc_dapm_widget *w, |
918 | struct snd_kcontrol *kcontrol, int event) |
919 | { |
920 | struct snd_soc_component *component = |
921 | snd_soc_dapm_to_component(dapm: w->dapm); |
922 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
923 | unsigned char unmute = 0x0, mute = 0x1; |
924 | |
925 | switch (event) { |
926 | case SND_SOC_DAPM_POST_PMU: |
927 | regmap_write(map: rt711->regmap, |
928 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, |
929 | RT711_SDCA_CTL_FU_MUTE, CH_L), |
930 | val: unmute); |
931 | regmap_write(map: rt711->regmap, |
932 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, |
933 | RT711_SDCA_CTL_FU_MUTE, CH_R), |
934 | val: unmute); |
935 | break; |
936 | case SND_SOC_DAPM_PRE_PMD: |
937 | regmap_write(map: rt711->regmap, |
938 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, |
939 | RT711_SDCA_CTL_FU_MUTE, CH_L), |
940 | val: mute); |
941 | regmap_write(map: rt711->regmap, |
942 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, |
943 | RT711_SDCA_CTL_FU_MUTE, CH_R), |
944 | val: mute); |
945 | break; |
946 | } |
947 | return 0; |
948 | } |
949 | |
950 | static int rt711_sdca_fu0f_event(struct snd_soc_dapm_widget *w, |
951 | struct snd_kcontrol *kcontrol, int event) |
952 | { |
953 | struct snd_soc_component *component = |
954 | snd_soc_dapm_to_component(dapm: w->dapm); |
955 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
956 | |
957 | switch (event) { |
958 | case SND_SOC_DAPM_POST_PMU: |
959 | rt711->fu0f_dapm_mute = false; |
960 | rt711_sdca_set_fu0f_capture_ctl(rt711); |
961 | break; |
962 | case SND_SOC_DAPM_PRE_PMD: |
963 | rt711->fu0f_dapm_mute = true; |
964 | rt711_sdca_set_fu0f_capture_ctl(rt711); |
965 | break; |
966 | } |
967 | return 0; |
968 | } |
969 | |
970 | static int rt711_sdca_fu1e_event(struct snd_soc_dapm_widget *w, |
971 | struct snd_kcontrol *kcontrol, int event) |
972 | { |
973 | struct snd_soc_component *component = |
974 | snd_soc_dapm_to_component(dapm: w->dapm); |
975 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
976 | |
977 | switch (event) { |
978 | case SND_SOC_DAPM_POST_PMU: |
979 | rt711->fu1e_dapm_mute = false; |
980 | rt711_sdca_set_fu1e_capture_ctl(rt711); |
981 | break; |
982 | case SND_SOC_DAPM_PRE_PMD: |
983 | rt711->fu1e_dapm_mute = true; |
984 | rt711_sdca_set_fu1e_capture_ctl(rt711); |
985 | break; |
986 | } |
987 | return 0; |
988 | } |
989 | |
990 | static int rt711_sdca_pde28_event(struct snd_soc_dapm_widget *w, |
991 | struct snd_kcontrol *kcontrol, int event) |
992 | { |
993 | struct snd_soc_component *component = |
994 | snd_soc_dapm_to_component(dapm: w->dapm); |
995 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
996 | unsigned char ps0 = 0x0, ps3 = 0x3; |
997 | |
998 | switch (event) { |
999 | case SND_SOC_DAPM_POST_PMU: |
1000 | regmap_write(map: rt711->regmap, |
1001 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, |
1002 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1003 | val: ps0); |
1004 | break; |
1005 | case SND_SOC_DAPM_PRE_PMD: |
1006 | regmap_write(map: rt711->regmap, |
1007 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, |
1008 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1009 | val: ps3); |
1010 | break; |
1011 | } |
1012 | return 0; |
1013 | } |
1014 | |
1015 | static int rt711_sdca_pde29_event(struct snd_soc_dapm_widget *w, |
1016 | struct snd_kcontrol *kcontrol, int event) |
1017 | { |
1018 | struct snd_soc_component *component = |
1019 | snd_soc_dapm_to_component(dapm: w->dapm); |
1020 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1021 | unsigned char ps0 = 0x0, ps3 = 0x3; |
1022 | |
1023 | switch (event) { |
1024 | case SND_SOC_DAPM_POST_PMU: |
1025 | regmap_write(map: rt711->regmap, |
1026 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, |
1027 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1028 | val: ps0); |
1029 | break; |
1030 | case SND_SOC_DAPM_PRE_PMD: |
1031 | regmap_write(map: rt711->regmap, |
1032 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, |
1033 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1034 | val: ps3); |
1035 | break; |
1036 | } |
1037 | return 0; |
1038 | } |
1039 | |
1040 | static int rt711_sdca_pde2a_event(struct snd_soc_dapm_widget *w, |
1041 | struct snd_kcontrol *kcontrol, int event) |
1042 | { |
1043 | struct snd_soc_component *component = |
1044 | snd_soc_dapm_to_component(dapm: w->dapm); |
1045 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1046 | unsigned char ps0 = 0x0, ps3 = 0x3; |
1047 | |
1048 | switch (event) { |
1049 | case SND_SOC_DAPM_POST_PMU: |
1050 | regmap_write(map: rt711->regmap, |
1051 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, |
1052 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1053 | val: ps0); |
1054 | break; |
1055 | case SND_SOC_DAPM_PRE_PMD: |
1056 | regmap_write(map: rt711->regmap, |
1057 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, |
1058 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1059 | val: ps3); |
1060 | break; |
1061 | } |
1062 | return 0; |
1063 | } |
1064 | |
1065 | static int rt711_sdca_line1_power_event(struct snd_soc_dapm_widget *w, |
1066 | struct snd_kcontrol *kcontrol, int event) |
1067 | { |
1068 | struct snd_soc_component *component = |
1069 | snd_soc_dapm_to_component(dapm: w->dapm); |
1070 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1071 | static unsigned int sel_mode = 0xffff; |
1072 | |
1073 | switch (event) { |
1074 | case SND_SOC_DAPM_POST_PMU: |
1075 | regmap_read(map: rt711->regmap, |
1076 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, |
1077 | RT711_SDCA_CTL_SELECTED_MODE, 0), |
1078 | val: &sel_mode); |
1079 | regmap_write(map: rt711->regmap, |
1080 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, |
1081 | RT711_SDCA_CTL_VENDOR_DEF, 0), |
1082 | val: 0x1); |
1083 | regmap_write(map: rt711->regmap, |
1084 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, |
1085 | RT711_SDCA_CTL_SELECTED_MODE, 0), |
1086 | val: 0x7); |
1087 | break; |
1088 | case SND_SOC_DAPM_PRE_PMD: |
1089 | regmap_write(map: rt711->regmap, |
1090 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, |
1091 | RT711_SDCA_CTL_VENDOR_DEF, 0), |
1092 | val: 0x0); |
1093 | if (sel_mode != 0xffff) |
1094 | regmap_write(map: rt711->regmap, |
1095 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, |
1096 | RT711_SDCA_CTL_SELECTED_MODE, 0), |
1097 | val: sel_mode); |
1098 | break; |
1099 | } |
1100 | |
1101 | return 0; |
1102 | } |
1103 | |
1104 | static int rt711_sdca_line2_power_event(struct snd_soc_dapm_widget *w, |
1105 | struct snd_kcontrol *kcontrol, int event) |
1106 | { |
1107 | struct snd_soc_component *component = |
1108 | snd_soc_dapm_to_component(dapm: w->dapm); |
1109 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1110 | unsigned char ps0 = 0x0, ps3 = 0x3; |
1111 | |
1112 | switch (event) { |
1113 | case SND_SOC_DAPM_POST_PMU: |
1114 | regmap_write(map: rt711->regmap, |
1115 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, |
1116 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1117 | val: ps0); |
1118 | regmap_write(map: rt711->regmap, |
1119 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, |
1120 | RT711_SDCA_CTL_VENDOR_DEF, 0), |
1121 | val: 0x1); |
1122 | break; |
1123 | case SND_SOC_DAPM_PRE_PMD: |
1124 | regmap_write(map: rt711->regmap, |
1125 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, |
1126 | RT711_SDCA_CTL_VENDOR_DEF, 0), |
1127 | val: 0x0); |
1128 | regmap_write(map: rt711->regmap, |
1129 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, |
1130 | RT711_SDCA_CTL_REQ_POWER_STATE, 0), |
1131 | val: ps3); |
1132 | break; |
1133 | } |
1134 | |
1135 | return 0; |
1136 | } |
1137 | |
1138 | static const struct snd_soc_dapm_widget rt711_sdca_dapm_widgets[] = { |
1139 | SND_SOC_DAPM_OUTPUT("HP" ), |
1140 | SND_SOC_DAPM_INPUT("MIC2" ), |
1141 | SND_SOC_DAPM_INPUT("DMIC1" ), |
1142 | SND_SOC_DAPM_INPUT("DMIC2" ), |
1143 | SND_SOC_DAPM_INPUT("LINE1" ), |
1144 | SND_SOC_DAPM_INPUT("LINE2" ), |
1145 | |
1146 | SND_SOC_DAPM_PGA_E("LINE1 Power" , SND_SOC_NOPM, |
1147 | 0, 0, NULL, 0, rt711_sdca_line1_power_event, |
1148 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1149 | SND_SOC_DAPM_PGA_E("LINE2 Power" , SND_SOC_NOPM, |
1150 | 0, 0, NULL, 0, rt711_sdca_line2_power_event, |
1151 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1152 | |
1153 | SND_SOC_DAPM_SUPPLY("PDE 28" , SND_SOC_NOPM, 0, 0, |
1154 | rt711_sdca_pde28_event, |
1155 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1156 | SND_SOC_DAPM_SUPPLY("PDE 29" , SND_SOC_NOPM, 0, 0, |
1157 | rt711_sdca_pde29_event, |
1158 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1159 | SND_SOC_DAPM_SUPPLY("PDE 2A" , SND_SOC_NOPM, 0, 0, |
1160 | rt711_sdca_pde2a_event, |
1161 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1162 | |
1163 | SND_SOC_DAPM_DAC_E("FU 05" , NULL, SND_SOC_NOPM, 0, 0, |
1164 | rt711_sdca_fu05_event, |
1165 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1166 | SND_SOC_DAPM_ADC_E("FU 0F" , NULL, SND_SOC_NOPM, 0, 0, |
1167 | rt711_sdca_fu0f_event, |
1168 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1169 | SND_SOC_DAPM_ADC_E("FU 1E" , NULL, SND_SOC_NOPM, 0, 0, |
1170 | rt711_sdca_fu1e_event, |
1171 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1172 | SND_SOC_DAPM_MUX("ADC 22 Mux" , SND_SOC_NOPM, 0, 0, |
1173 | &rt711_sdca_adc22_mux), |
1174 | SND_SOC_DAPM_MUX("ADC 23 Mux" , SND_SOC_NOPM, 0, 0, |
1175 | &rt711_sdca_adc23_mux), |
1176 | |
1177 | SND_SOC_DAPM_AIF_IN("DP3RX" , "DP3 Playback" , 0, SND_SOC_NOPM, 0, 0), |
1178 | SND_SOC_DAPM_AIF_OUT("DP2TX" , "DP2 Capture" , 0, SND_SOC_NOPM, 0, 0), |
1179 | SND_SOC_DAPM_AIF_OUT("DP4TX" , "DP4 Capture" , 0, SND_SOC_NOPM, 0, 0), |
1180 | }; |
1181 | |
1182 | static const struct snd_soc_dapm_route rt711_sdca_audio_map[] = { |
1183 | {"FU 05" , NULL, "DP3RX" }, |
1184 | {"DP2TX" , NULL, "FU 0F" }, |
1185 | {"DP4TX" , NULL, "FU 1E" }, |
1186 | |
1187 | {"LINE1 Power" , NULL, "LINE1" }, |
1188 | {"LINE2 Power" , NULL, "LINE2" }, |
1189 | {"HP" , NULL, "PDE 28" }, |
1190 | {"FU 0F" , NULL, "PDE 29" }, |
1191 | {"FU 1E" , NULL, "PDE 2A" }, |
1192 | |
1193 | {"FU 0F" , NULL, "ADC 22 Mux" }, |
1194 | {"FU 1E" , NULL, "ADC 23 Mux" }, |
1195 | {"ADC 22 Mux" , "DMIC" , "DMIC1" }, |
1196 | {"ADC 22 Mux" , "LINE1" , "LINE1 Power" }, |
1197 | {"ADC 22 Mux" , "LINE2" , "LINE2 Power" }, |
1198 | {"ADC 22 Mux" , "MIC2" , "MIC2" }, |
1199 | {"ADC 23 Mux" , "DMIC" , "DMIC2" }, |
1200 | {"ADC 23 Mux" , "LINE1" , "LINE1 Power" }, |
1201 | {"ADC 23 Mux" , "LINE2" , "LINE2 Power" }, |
1202 | {"ADC 23 Mux" , "MIC2" , "MIC2" }, |
1203 | |
1204 | {"HP" , NULL, "FU 05" }, |
1205 | }; |
1206 | |
1207 | static int rt711_sdca_parse_dt(struct rt711_sdca_priv *rt711, struct device *dev) |
1208 | { |
1209 | device_property_read_u32(dev, propname: "realtek,jd-src" , val: &rt711->jd_src); |
1210 | |
1211 | return 0; |
1212 | } |
1213 | |
1214 | static int rt711_sdca_probe(struct snd_soc_component *component) |
1215 | { |
1216 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1217 | int ret; |
1218 | |
1219 | rt711_sdca_parse_dt(rt711, dev: &rt711->slave->dev); |
1220 | rt711->component = component; |
1221 | |
1222 | if (!rt711->first_hw_init) |
1223 | return 0; |
1224 | |
1225 | ret = pm_runtime_resume(dev: component->dev); |
1226 | if (ret < 0 && ret != -EACCES) |
1227 | return ret; |
1228 | |
1229 | return 0; |
1230 | } |
1231 | |
1232 | static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { |
1233 | .probe = rt711_sdca_probe, |
1234 | .controls = rt711_sdca_snd_controls, |
1235 | .num_controls = ARRAY_SIZE(rt711_sdca_snd_controls), |
1236 | .dapm_widgets = rt711_sdca_dapm_widgets, |
1237 | .num_dapm_widgets = ARRAY_SIZE(rt711_sdca_dapm_widgets), |
1238 | .dapm_routes = rt711_sdca_audio_map, |
1239 | .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), |
1240 | .set_jack = rt711_sdca_set_jack_detect, |
1241 | .endianness = 1, |
1242 | }; |
1243 | |
1244 | static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, |
1245 | int direction) |
1246 | { |
1247 | snd_soc_dai_dma_data_set(dai, stream: direction, data: sdw_stream); |
1248 | |
1249 | return 0; |
1250 | } |
1251 | |
1252 | static void rt711_sdca_shutdown(struct snd_pcm_substream *substream, |
1253 | struct snd_soc_dai *dai) |
1254 | { |
1255 | snd_soc_dai_set_dma_data(dai, substream, NULL); |
1256 | } |
1257 | |
1258 | static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, |
1259 | struct snd_pcm_hw_params *params, |
1260 | struct snd_soc_dai *dai) |
1261 | { |
1262 | struct snd_soc_component *component = dai->component; |
1263 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1264 | struct sdw_stream_config stream_config = {0}; |
1265 | struct sdw_port_config port_config = {0}; |
1266 | struct sdw_stream_runtime *sdw_stream; |
1267 | int retval; |
1268 | unsigned int sampling_rate; |
1269 | |
1270 | dev_dbg(dai->dev, "%s %s" , __func__, dai->name); |
1271 | sdw_stream = snd_soc_dai_get_dma_data(dai, substream); |
1272 | |
1273 | if (!sdw_stream) |
1274 | return -EINVAL; |
1275 | |
1276 | if (!rt711->slave) |
1277 | return -EINVAL; |
1278 | |
1279 | /* SoundWire specific configuration */ |
1280 | snd_sdw_params_to_config(substream, params, stream_config: &stream_config, port_config: &port_config); |
1281 | |
1282 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1283 | port_config.num = 3; |
1284 | } else { |
1285 | if (dai->id == RT711_AIF1) |
1286 | port_config.num = 2; |
1287 | else if (dai->id == RT711_AIF2) |
1288 | port_config.num = 4; |
1289 | else |
1290 | return -EINVAL; |
1291 | } |
1292 | |
1293 | retval = sdw_stream_add_slave(slave: rt711->slave, stream_config: &stream_config, |
1294 | port_config: &port_config, num_ports: 1, stream: sdw_stream); |
1295 | if (retval) { |
1296 | dev_err(dai->dev, "%s: Unable to configure port\n" , __func__); |
1297 | return retval; |
1298 | } |
1299 | |
1300 | if (params_channels(p: params) > 16) { |
1301 | dev_err(component->dev, "%s: Unsupported channels %d\n" , |
1302 | __func__, params_channels(params)); |
1303 | return -EINVAL; |
1304 | } |
1305 | |
1306 | /* sampling rate configuration */ |
1307 | switch (params_rate(p: params)) { |
1308 | case 44100: |
1309 | sampling_rate = RT711_SDCA_RATE_44100HZ; |
1310 | break; |
1311 | case 48000: |
1312 | sampling_rate = RT711_SDCA_RATE_48000HZ; |
1313 | break; |
1314 | case 96000: |
1315 | sampling_rate = RT711_SDCA_RATE_96000HZ; |
1316 | break; |
1317 | case 192000: |
1318 | sampling_rate = RT711_SDCA_RATE_192000HZ; |
1319 | break; |
1320 | default: |
1321 | dev_err(component->dev, "%s: Rate %d is not supported\n" , |
1322 | __func__, params_rate(params)); |
1323 | return -EINVAL; |
1324 | } |
1325 | |
1326 | /* set sampling frequency */ |
1327 | regmap_write(map: rt711->regmap, |
1328 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS01, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
1329 | val: sampling_rate); |
1330 | regmap_write(map: rt711->regmap, |
1331 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS11, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
1332 | val: sampling_rate); |
1333 | regmap_write(map: rt711->regmap, |
1334 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_CS1F, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
1335 | val: sampling_rate); |
1336 | |
1337 | return 0; |
1338 | } |
1339 | |
1340 | static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, |
1341 | struct snd_soc_dai *dai) |
1342 | { |
1343 | struct snd_soc_component *component = dai->component; |
1344 | struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(c: component); |
1345 | struct sdw_stream_runtime *sdw_stream = |
1346 | snd_soc_dai_get_dma_data(dai, substream); |
1347 | |
1348 | if (!rt711->slave) |
1349 | return -EINVAL; |
1350 | |
1351 | sdw_stream_remove_slave(slave: rt711->slave, stream: sdw_stream); |
1352 | return 0; |
1353 | } |
1354 | |
1355 | #define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ |
1356 | SNDRV_PCM_RATE_192000) |
1357 | #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
1358 | SNDRV_PCM_FMTBIT_S24_LE) |
1359 | |
1360 | static const struct snd_soc_dai_ops rt711_sdca_ops = { |
1361 | .hw_params = rt711_sdca_pcm_hw_params, |
1362 | .hw_free = rt711_sdca_pcm_hw_free, |
1363 | .set_stream = rt711_sdca_set_sdw_stream, |
1364 | .shutdown = rt711_sdca_shutdown, |
1365 | }; |
1366 | |
1367 | static struct snd_soc_dai_driver rt711_sdca_dai[] = { |
1368 | { |
1369 | .name = "rt711-sdca-aif1" , |
1370 | .id = RT711_AIF1, |
1371 | .playback = { |
1372 | .stream_name = "DP3 Playback" , |
1373 | .channels_min = 1, |
1374 | .channels_max = 2, |
1375 | .rates = RT711_STEREO_RATES, |
1376 | .formats = RT711_FORMATS, |
1377 | }, |
1378 | .capture = { |
1379 | .stream_name = "DP2 Capture" , |
1380 | .channels_min = 1, |
1381 | .channels_max = 2, |
1382 | .rates = RT711_STEREO_RATES, |
1383 | .formats = RT711_FORMATS, |
1384 | }, |
1385 | .ops = &rt711_sdca_ops, |
1386 | }, |
1387 | { |
1388 | .name = "rt711-sdca-aif2" , |
1389 | .id = RT711_AIF2, |
1390 | .capture = { |
1391 | .stream_name = "DP4 Capture" , |
1392 | .channels_min = 1, |
1393 | .channels_max = 2, |
1394 | .rates = RT711_STEREO_RATES, |
1395 | .formats = RT711_FORMATS, |
1396 | }, |
1397 | .ops = &rt711_sdca_ops, |
1398 | } |
1399 | }; |
1400 | |
1401 | int rt711_sdca_init(struct device *dev, struct regmap *regmap, |
1402 | struct regmap *mbq_regmap, struct sdw_slave *slave) |
1403 | { |
1404 | struct rt711_sdca_priv *rt711; |
1405 | int ret; |
1406 | |
1407 | rt711 = devm_kzalloc(dev, size: sizeof(*rt711), GFP_KERNEL); |
1408 | if (!rt711) |
1409 | return -ENOMEM; |
1410 | |
1411 | dev_set_drvdata(dev, data: rt711); |
1412 | rt711->slave = slave; |
1413 | rt711->regmap = regmap; |
1414 | rt711->mbq_regmap = mbq_regmap; |
1415 | |
1416 | regcache_cache_only(map: rt711->regmap, enable: true); |
1417 | regcache_cache_only(map: rt711->mbq_regmap, enable: true); |
1418 | |
1419 | mutex_init(&rt711->calibrate_mutex); |
1420 | mutex_init(&rt711->disable_irq_lock); |
1421 | |
1422 | INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler); |
1423 | INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); |
1424 | |
1425 | /* |
1426 | * Mark hw_init to false |
1427 | * HW init will be performed when device reports present |
1428 | */ |
1429 | rt711->hw_init = false; |
1430 | rt711->first_hw_init = false; |
1431 | rt711->fu0f_dapm_mute = true; |
1432 | rt711->fu1e_dapm_mute = true; |
1433 | rt711->fu0f_mixer_l_mute = rt711->fu0f_mixer_r_mute = true; |
1434 | rt711->fu1e_mixer_l_mute = rt711->fu1e_mixer_r_mute = true; |
1435 | |
1436 | /* JD source uses JD2 in default */ |
1437 | rt711->jd_src = RT711_JD2; |
1438 | |
1439 | ret = devm_snd_soc_register_component(dev, |
1440 | component_driver: &soc_sdca_dev_rt711, |
1441 | dai_drv: rt711_sdca_dai, |
1442 | ARRAY_SIZE(rt711_sdca_dai)); |
1443 | |
1444 | if (ret < 0) |
1445 | return ret; |
1446 | |
1447 | /* set autosuspend parameters */ |
1448 | pm_runtime_set_autosuspend_delay(dev, delay: 3000); |
1449 | pm_runtime_use_autosuspend(dev); |
1450 | |
1451 | /* make sure the device does not suspend immediately */ |
1452 | pm_runtime_mark_last_busy(dev); |
1453 | |
1454 | pm_runtime_enable(dev); |
1455 | |
1456 | /* important note: the device is NOT tagged as 'active' and will remain |
1457 | * 'suspended' until the hardware is enumerated/initialized. This is required |
1458 | * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently |
1459 | * fail with -EACCESS because of race conditions between card creation and enumeration |
1460 | */ |
1461 | |
1462 | dev_dbg(dev, "%s\n" , __func__); |
1463 | |
1464 | return 0; |
1465 | } |
1466 | |
1467 | static void rt711_sdca_vd0_io_init(struct rt711_sdca_priv *rt711) |
1468 | { |
1469 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1470 | RT711_GPIO_TEST_MODE_CTL2, value: 0x0e00); |
1471 | rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, |
1472 | RT711_HDA_LEGACY_GPIO_CTL, value: 0x0008); |
1473 | |
1474 | regmap_write(map: rt711->regmap, reg: 0x2f5a, val: 0x01); |
1475 | |
1476 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1477 | RT711_ADC27_VOL_SET, value: 0x8728); |
1478 | |
1479 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1480 | RT711_COMBO_JACK_AUTO_CTL3, value: 0xa472); |
1481 | |
1482 | regmap_write(map: rt711->regmap, reg: 0x2f50, val: 0x02); |
1483 | |
1484 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, |
1485 | RT711_MISC_POWER_CTL4, mask: 0x6000, val: 0x6000); |
1486 | |
1487 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
1488 | RT711_COMBO_JACK_AUTO_CTL3, mask: 0x000c, val: 0x000c); |
1489 | |
1490 | rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, |
1491 | RT711_HDA_LEGACY_CONFIG_CTL, value: 0x0000); |
1492 | |
1493 | rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, |
1494 | RT711_VAD_SRAM_CTL1, value: 0x0050); |
1495 | } |
1496 | |
1497 | static void rt711_sdca_vd1_io_init(struct rt711_sdca_priv *rt711) |
1498 | { |
1499 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
1500 | RT711_HDA_LEGACY_UNSOLICITED_CTL, mask: 0x0300, val: 0x0000); |
1501 | |
1502 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1503 | RT711_COMBO_JACK_AUTO_CTL3, value: 0xa43e); |
1504 | |
1505 | regmap_write(map: rt711->regmap, reg: 0x2f5a, val: 0x05); |
1506 | |
1507 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1508 | RT711_JD_CTRL6, value: 0x0500); |
1509 | |
1510 | rt711_sdca_index_write(rt711, RT711_VENDOR_REG, |
1511 | RT711_DMIC_CTL1, value: 0x6173); |
1512 | |
1513 | rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, |
1514 | RT711_HDA_LEGACY_CONFIG_CTL, value: 0x0000); |
1515 | |
1516 | rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, |
1517 | RT711_VAD_SRAM_CTL1, value: 0x0050); |
1518 | } |
1519 | |
1520 | int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) |
1521 | { |
1522 | struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); |
1523 | int ret = 0; |
1524 | unsigned int val; |
1525 | |
1526 | rt711->disable_irq = false; |
1527 | |
1528 | if (rt711->hw_init) |
1529 | return 0; |
1530 | |
1531 | regcache_cache_only(map: rt711->regmap, enable: false); |
1532 | regcache_cache_only(map: rt711->mbq_regmap, enable: false); |
1533 | |
1534 | if (rt711->first_hw_init) { |
1535 | regcache_cache_bypass(map: rt711->regmap, enable: true); |
1536 | regcache_cache_bypass(map: rt711->mbq_regmap, enable: true); |
1537 | } else { |
1538 | /* |
1539 | * PM runtime status is marked as 'active' only when a Slave reports as Attached |
1540 | */ |
1541 | |
1542 | /* update count of parent 'active' children */ |
1543 | pm_runtime_set_active(dev: &slave->dev); |
1544 | } |
1545 | |
1546 | pm_runtime_get_noresume(dev: &slave->dev); |
1547 | |
1548 | rt711_sdca_reset(rt711); |
1549 | |
1550 | rt711_sdca_index_read(rt711, RT711_VENDOR_REG, RT711_JD_PRODUCT_NUM, value: &val); |
1551 | rt711->hw_ver = val & 0xf; |
1552 | |
1553 | if (rt711->hw_ver == RT711_VER_VD0) |
1554 | rt711_sdca_vd0_io_init(rt711); |
1555 | else |
1556 | rt711_sdca_vd1_io_init(rt711); |
1557 | |
1558 | /* DP4 mux select from 08_filter_Out_pri */ |
1559 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, |
1560 | RT711_FILTER_SRC_SEL, mask: 0x1800, val: 0x0800); |
1561 | |
1562 | /* ge_exclusive_inbox_en disable */ |
1563 | rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, |
1564 | RT711_PUSH_BTN_INT_CTL0, mask: 0x20, val: 0x00); |
1565 | |
1566 | /* calibration */ |
1567 | ret = rt711_sdca_calibration(rt711); |
1568 | if (ret < 0) |
1569 | dev_err(dev, "%s, calibration failed!\n" , __func__); |
1570 | |
1571 | /* HP output enable */ |
1572 | regmap_write(map: rt711->regmap, |
1573 | SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_OT1, RT711_SDCA_CTL_VENDOR_DEF, 0), val: 0x4); |
1574 | |
1575 | /* |
1576 | * if set_jack callback occurred early than io_init, |
1577 | * we set up the jack detection function now |
1578 | */ |
1579 | if (rt711->hs_jack) |
1580 | rt711_sdca_jack_init(rt711); |
1581 | |
1582 | if (rt711->first_hw_init) { |
1583 | regcache_cache_bypass(map: rt711->regmap, enable: false); |
1584 | regcache_mark_dirty(map: rt711->regmap); |
1585 | regcache_cache_bypass(map: rt711->mbq_regmap, enable: false); |
1586 | regcache_mark_dirty(map: rt711->mbq_regmap); |
1587 | } else |
1588 | rt711->first_hw_init = true; |
1589 | |
1590 | /* Mark Slave initialization complete */ |
1591 | rt711->hw_init = true; |
1592 | |
1593 | pm_runtime_mark_last_busy(dev: &slave->dev); |
1594 | pm_runtime_put_autosuspend(dev: &slave->dev); |
1595 | |
1596 | dev_dbg(&slave->dev, "%s hw_init complete\n" , __func__); |
1597 | return 0; |
1598 | } |
1599 | |
1600 | MODULE_DESCRIPTION("ASoC RT711 SDCA SDW driver" ); |
1601 | MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>" ); |
1602 | MODULE_LICENSE("GPL" ); |
1603 | |