1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // mt6358.c -- mt6358 ALSA SoC audio codec driver |
4 | // |
5 | // Copyright (c) 2018 MediaTek Inc. |
6 | // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com> |
7 | |
8 | #include <linux/platform_device.h> |
9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/module.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/kthread.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/mfd/mt6397/core.h> |
15 | #include <linux/regulator/consumer.h> |
16 | |
17 | #include <sound/soc.h> |
18 | #include <sound/tlv.h> |
19 | |
20 | #include "mt6358.h" |
21 | |
22 | enum { |
23 | AUDIO_ANALOG_VOLUME_HSOUTL, |
24 | AUDIO_ANALOG_VOLUME_HSOUTR, |
25 | AUDIO_ANALOG_VOLUME_HPOUTL, |
26 | AUDIO_ANALOG_VOLUME_HPOUTR, |
27 | AUDIO_ANALOG_VOLUME_LINEOUTL, |
28 | AUDIO_ANALOG_VOLUME_LINEOUTR, |
29 | AUDIO_ANALOG_VOLUME_MICAMP1, |
30 | AUDIO_ANALOG_VOLUME_MICAMP2, |
31 | AUDIO_ANALOG_VOLUME_TYPE_MAX |
32 | }; |
33 | |
34 | enum { |
35 | MUX_ADC_L, |
36 | MUX_ADC_R, |
37 | MUX_PGA_L, |
38 | MUX_PGA_R, |
39 | MUX_MIC_TYPE, |
40 | MUX_HP_L, |
41 | MUX_HP_R, |
42 | MUX_NUM, |
43 | }; |
44 | |
45 | enum { |
46 | DEVICE_HP, |
47 | DEVICE_LO, |
48 | DEVICE_RCV, |
49 | DEVICE_MIC1, |
50 | DEVICE_MIC2, |
51 | DEVICE_NUM |
52 | }; |
53 | |
54 | /* Supply widget subseq */ |
55 | enum { |
56 | /* common */ |
57 | SUPPLY_SEQ_CLK_BUF, |
58 | SUPPLY_SEQ_AUD_GLB, |
59 | SUPPLY_SEQ_CLKSQ, |
60 | SUPPLY_SEQ_VOW_AUD_LPW, |
61 | SUPPLY_SEQ_AUD_VOW, |
62 | SUPPLY_SEQ_VOW_CLK, |
63 | SUPPLY_SEQ_VOW_LDO, |
64 | SUPPLY_SEQ_TOP_CK, |
65 | SUPPLY_SEQ_TOP_CK_LAST, |
66 | SUPPLY_SEQ_AUD_TOP, |
67 | SUPPLY_SEQ_AUD_TOP_LAST, |
68 | SUPPLY_SEQ_AFE, |
69 | /* capture */ |
70 | SUPPLY_SEQ_ADC_SUPPLY, |
71 | }; |
72 | |
73 | enum { |
74 | CH_L = 0, |
75 | CH_R, |
76 | NUM_CH, |
77 | }; |
78 | |
79 | #define REG_STRIDE 2 |
80 | |
81 | struct mt6358_priv { |
82 | struct device *dev; |
83 | struct regmap *regmap; |
84 | |
85 | unsigned int dl_rate; |
86 | unsigned int ul_rate; |
87 | |
88 | int ana_gain[AUDIO_ANALOG_VOLUME_TYPE_MAX]; |
89 | unsigned int mux_select[MUX_NUM]; |
90 | |
91 | int dev_counter[DEVICE_NUM]; |
92 | |
93 | int mtkaif_protocol; |
94 | |
95 | struct regulator *avdd_reg; |
96 | |
97 | int wov_enabled; |
98 | |
99 | unsigned int dmic_one_wire_mode; |
100 | }; |
101 | |
102 | int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, |
103 | int mtkaif_protocol) |
104 | { |
105 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
106 | |
107 | priv->mtkaif_protocol = mtkaif_protocol; |
108 | return 0; |
109 | } |
110 | EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_protocol); |
111 | |
112 | static void playback_gpio_set(struct mt6358_priv *priv) |
113 | { |
114 | /* set gpio mosi mode */ |
115 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE2_CLR, |
116 | mask: 0x01f8, val: 0x01f8); |
117 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE2_SET, |
118 | mask: 0xffff, val: 0x0249); |
119 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE2, |
120 | mask: 0xffff, val: 0x0249); |
121 | } |
122 | |
123 | static void playback_gpio_reset(struct mt6358_priv *priv) |
124 | { |
125 | /* set pad_aud_*_mosi to GPIO mode and dir input |
126 | * reason: |
127 | * pad_aud_dat_mosi*, because the pin is used as boot strap |
128 | * don't clean clk/sync, for mtkaif protocol 2 |
129 | */ |
130 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE2_CLR, |
131 | mask: 0x01f8, val: 0x01f8); |
132 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE2, |
133 | mask: 0x01f8, val: 0x0000); |
134 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_DIR0, |
135 | mask: 0xf << 8, val: 0x0); |
136 | } |
137 | |
138 | static void capture_gpio_set(struct mt6358_priv *priv) |
139 | { |
140 | /* set gpio miso mode */ |
141 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3_CLR, |
142 | mask: 0xffff, val: 0xffff); |
143 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3_SET, |
144 | mask: 0xffff, val: 0x0249); |
145 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3, |
146 | mask: 0xffff, val: 0x0249); |
147 | } |
148 | |
149 | static void capture_gpio_reset(struct mt6358_priv *priv) |
150 | { |
151 | /* set pad_aud_*_miso to GPIO mode and dir input |
152 | * reason: |
153 | * pad_aud_clk_miso, because when playback only the miso_clk |
154 | * will also have 26m, so will have power leak |
155 | * pad_aud_dat_miso*, because the pin is used as boot strap |
156 | */ |
157 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3_CLR, |
158 | mask: 0xffff, val: 0xffff); |
159 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3, |
160 | mask: 0xffff, val: 0x0000); |
161 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_DIR0, |
162 | mask: 0xf << 12, val: 0x0); |
163 | } |
164 | |
165 | /* use only when not govern by DAPM */ |
166 | static int mt6358_set_dcxo(struct mt6358_priv *priv, bool enable) |
167 | { |
168 | regmap_update_bits(map: priv->regmap, MT6358_DCXO_CW14, |
169 | mask: 0x1 << RG_XO_AUDIO_EN_M_SFT, |
170 | val: (enable ? 1 : 0) << RG_XO_AUDIO_EN_M_SFT); |
171 | return 0; |
172 | } |
173 | |
174 | /* use only when not govern by DAPM */ |
175 | static int mt6358_set_clksq(struct mt6358_priv *priv, bool enable) |
176 | { |
177 | /* audio clk source from internal dcxo */ |
178 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON6, |
179 | RG_CLKSQ_IN_SEL_TEST_MASK_SFT, |
180 | val: 0x0); |
181 | |
182 | /* Enable/disable CLKSQ 26MHz */ |
183 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON6, |
184 | RG_CLKSQ_EN_MASK_SFT, |
185 | val: (enable ? 1 : 0) << RG_CLKSQ_EN_SFT); |
186 | return 0; |
187 | } |
188 | |
189 | /* use only when not govern by DAPM */ |
190 | static int mt6358_set_aud_global_bias(struct mt6358_priv *priv, bool enable) |
191 | { |
192 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
193 | RG_AUDGLB_PWRDN_VA28_MASK_SFT, |
194 | val: (enable ? 0 : 1) << RG_AUDGLB_PWRDN_VA28_SFT); |
195 | return 0; |
196 | } |
197 | |
198 | /* use only when not govern by DAPM */ |
199 | static int mt6358_set_topck(struct mt6358_priv *priv, bool enable) |
200 | { |
201 | regmap_update_bits(map: priv->regmap, MT6358_AUD_TOP_CKPDN_CON0, |
202 | mask: 0x0066, val: enable ? 0x0 : 0x66); |
203 | return 0; |
204 | } |
205 | |
206 | static int mt6358_mtkaif_tx_enable(struct mt6358_priv *priv) |
207 | { |
208 | switch (priv->mtkaif_protocol) { |
209 | case MT6358_MTKAIF_PROTOCOL_2_CLK_P2: |
210 | /* MTKAIF TX format setting */ |
211 | regmap_update_bits(map: priv->regmap, |
212 | MT6358_AFE_ADDA_MTKAIF_CFG0, |
213 | mask: 0xffff, val: 0x0010); |
214 | /* enable aud_pad TX fifos */ |
215 | regmap_update_bits(map: priv->regmap, |
216 | MT6358_AFE_AUD_PAD_TOP, |
217 | mask: 0xff00, val: 0x3800); |
218 | regmap_update_bits(map: priv->regmap, |
219 | MT6358_AFE_AUD_PAD_TOP, |
220 | mask: 0xff00, val: 0x3900); |
221 | break; |
222 | case MT6358_MTKAIF_PROTOCOL_2: |
223 | /* MTKAIF TX format setting */ |
224 | regmap_update_bits(map: priv->regmap, |
225 | MT6358_AFE_ADDA_MTKAIF_CFG0, |
226 | mask: 0xffff, val: 0x0010); |
227 | /* enable aud_pad TX fifos */ |
228 | regmap_update_bits(map: priv->regmap, |
229 | MT6358_AFE_AUD_PAD_TOP, |
230 | mask: 0xff00, val: 0x3100); |
231 | break; |
232 | case MT6358_MTKAIF_PROTOCOL_1: |
233 | default: |
234 | /* MTKAIF TX format setting */ |
235 | regmap_update_bits(map: priv->regmap, |
236 | MT6358_AFE_ADDA_MTKAIF_CFG0, |
237 | mask: 0xffff, val: 0x0000); |
238 | /* enable aud_pad TX fifos */ |
239 | regmap_update_bits(map: priv->regmap, |
240 | MT6358_AFE_AUD_PAD_TOP, |
241 | mask: 0xff00, val: 0x3100); |
242 | break; |
243 | } |
244 | return 0; |
245 | } |
246 | |
247 | static int mt6358_mtkaif_tx_disable(struct mt6358_priv *priv) |
248 | { |
249 | /* disable aud_pad TX fifos */ |
250 | regmap_update_bits(map: priv->regmap, MT6358_AFE_AUD_PAD_TOP, |
251 | mask: 0xff00, val: 0x3000); |
252 | return 0; |
253 | } |
254 | |
255 | int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt) |
256 | { |
257 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
258 | |
259 | playback_gpio_set(priv); |
260 | capture_gpio_set(priv); |
261 | mt6358_mtkaif_tx_enable(priv); |
262 | |
263 | mt6358_set_dcxo(priv, enable: true); |
264 | mt6358_set_aud_global_bias(priv, enable: true); |
265 | mt6358_set_clksq(priv, enable: true); |
266 | mt6358_set_topck(priv, enable: true); |
267 | |
268 | /* set dat_miso_loopback on */ |
269 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
270 | RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, |
271 | val: 1 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); |
272 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
273 | RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, |
274 | val: 1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); |
275 | return 0; |
276 | } |
277 | EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_enable); |
278 | |
279 | int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt) |
280 | { |
281 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
282 | |
283 | /* set dat_miso_loopback off */ |
284 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
285 | RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, |
286 | val: 0 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); |
287 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
288 | RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, |
289 | val: 0 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); |
290 | |
291 | mt6358_set_topck(priv, enable: false); |
292 | mt6358_set_clksq(priv, enable: false); |
293 | mt6358_set_aud_global_bias(priv, enable: false); |
294 | mt6358_set_dcxo(priv, enable: false); |
295 | |
296 | mt6358_mtkaif_tx_disable(priv); |
297 | playback_gpio_reset(priv); |
298 | capture_gpio_reset(priv); |
299 | return 0; |
300 | } |
301 | EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_disable); |
302 | |
303 | int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt, |
304 | int phase_1, int phase_2) |
305 | { |
306 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
307 | |
308 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
309 | RG_AUD_PAD_TOP_PHASE_MODE_MASK_SFT, |
310 | val: phase_1 << RG_AUD_PAD_TOP_PHASE_MODE_SFT); |
311 | regmap_update_bits(map: priv->regmap, MT6358_AUDIO_DIG_CFG, |
312 | RG_AUD_PAD_TOP_PHASE_MODE2_MASK_SFT, |
313 | val: phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT); |
314 | return 0; |
315 | } |
316 | EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_calibration_phase); |
317 | |
318 | /* dl pga gain */ |
319 | enum { |
320 | DL_GAIN_8DB = 0, |
321 | DL_GAIN_0DB = 8, |
322 | DL_GAIN_N_1DB = 9, |
323 | DL_GAIN_N_10DB = 18, |
324 | DL_GAIN_N_40DB = 0x1f, |
325 | }; |
326 | |
327 | #define DL_GAIN_N_10DB_REG (DL_GAIN_N_10DB << 7 | DL_GAIN_N_10DB) |
328 | #define DL_GAIN_N_40DB_REG (DL_GAIN_N_40DB << 7 | DL_GAIN_N_40DB) |
329 | #define DL_GAIN_REG_MASK 0x0f9f |
330 | |
331 | static void hp_zcd_disable(struct mt6358_priv *priv) |
332 | { |
333 | regmap_write(map: priv->regmap, MT6358_ZCD_CON0, val: 0x0000); |
334 | } |
335 | |
336 | static void hp_main_output_ramp(struct mt6358_priv *priv, bool up) |
337 | { |
338 | int i, stage; |
339 | int target = 7; |
340 | |
341 | /* Enable/Reduce HPL/R main output stage step by step */ |
342 | for (i = 0; i <= target; i++) { |
343 | stage = up ? i : target - i; |
344 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, |
345 | mask: 0x7 << 8, val: stage << 8); |
346 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, |
347 | mask: 0x7 << 11, val: stage << 11); |
348 | usleep_range(min: 100, max: 150); |
349 | } |
350 | } |
351 | |
352 | static void hp_aux_feedback_loop_gain_ramp(struct mt6358_priv *priv, bool up) |
353 | { |
354 | int i, stage; |
355 | |
356 | /* Reduce HP aux feedback loop gain step by step */ |
357 | for (i = 0; i <= 0xf; i++) { |
358 | stage = up ? i : 0xf - i; |
359 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, |
360 | mask: 0xf << 12, val: stage << 12); |
361 | usleep_range(min: 100, max: 150); |
362 | } |
363 | } |
364 | |
365 | static void hp_pull_down(struct mt6358_priv *priv, bool enable) |
366 | { |
367 | int i; |
368 | |
369 | if (enable) { |
370 | for (i = 0x0; i <= 0x6; i++) { |
371 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
372 | mask: 0x7, val: i); |
373 | usleep_range(min: 600, max: 700); |
374 | } |
375 | } else { |
376 | for (i = 0x6; i >= 0x1; i--) { |
377 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
378 | mask: 0x7, val: i); |
379 | usleep_range(min: 600, max: 700); |
380 | } |
381 | } |
382 | } |
383 | |
384 | static bool is_valid_hp_pga_idx(int reg_idx) |
385 | { |
386 | return (reg_idx >= DL_GAIN_8DB && reg_idx <= DL_GAIN_N_10DB) || |
387 | reg_idx == DL_GAIN_N_40DB; |
388 | } |
389 | |
390 | static void headset_volume_ramp(struct mt6358_priv *priv, int from, int to) |
391 | { |
392 | int offset = 0, count = 0, reg_idx; |
393 | |
394 | if (!is_valid_hp_pga_idx(reg_idx: from) || !is_valid_hp_pga_idx(reg_idx: to)) |
395 | dev_warn(priv->dev, "%s(), volume index is not valid, from %d, to %d\n" , |
396 | __func__, from, to); |
397 | |
398 | dev_info(priv->dev, "%s(), from %d, to %d\n" , |
399 | __func__, from, to); |
400 | |
401 | if (to > from) |
402 | offset = to - from; |
403 | else |
404 | offset = from - to; |
405 | |
406 | while (offset >= 0) { |
407 | if (to > from) |
408 | reg_idx = from + count; |
409 | else |
410 | reg_idx = from - count; |
411 | |
412 | if (is_valid_hp_pga_idx(reg_idx)) { |
413 | regmap_update_bits(map: priv->regmap, |
414 | MT6358_ZCD_CON2, |
415 | DL_GAIN_REG_MASK, |
416 | val: (reg_idx << 7) | reg_idx); |
417 | usleep_range(min: 200, max: 300); |
418 | } |
419 | offset--; |
420 | count++; |
421 | } |
422 | } |
423 | |
424 | static int mt6358_put_volsw(struct snd_kcontrol *kcontrol, |
425 | struct snd_ctl_elem_value *ucontrol) |
426 | { |
427 | struct snd_soc_component *component = |
428 | snd_soc_kcontrol_component(kcontrol); |
429 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: component); |
430 | struct soc_mixer_control *mc = |
431 | (struct soc_mixer_control *)kcontrol->private_value; |
432 | unsigned int reg = 0; |
433 | int ret; |
434 | |
435 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
436 | if (ret < 0) |
437 | return ret; |
438 | |
439 | switch (mc->reg) { |
440 | case MT6358_ZCD_CON2: |
441 | regmap_read(map: priv->regmap, MT6358_ZCD_CON2, val: ®); |
442 | priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL] = |
443 | (reg >> RG_AUDHPLGAIN_SFT) & RG_AUDHPLGAIN_MASK; |
444 | priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTR] = |
445 | (reg >> RG_AUDHPRGAIN_SFT) & RG_AUDHPRGAIN_MASK; |
446 | break; |
447 | case MT6358_ZCD_CON1: |
448 | regmap_read(map: priv->regmap, MT6358_ZCD_CON1, val: ®); |
449 | priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL] = |
450 | (reg >> RG_AUDLOLGAIN_SFT) & RG_AUDLOLGAIN_MASK; |
451 | priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTR] = |
452 | (reg >> RG_AUDLORGAIN_SFT) & RG_AUDLORGAIN_MASK; |
453 | break; |
454 | case MT6358_ZCD_CON3: |
455 | regmap_read(map: priv->regmap, MT6358_ZCD_CON3, val: ®); |
456 | priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTL] = |
457 | (reg >> RG_AUDHSGAIN_SFT) & RG_AUDHSGAIN_MASK; |
458 | priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTR] = |
459 | (reg >> RG_AUDHSGAIN_SFT) & RG_AUDHSGAIN_MASK; |
460 | break; |
461 | case MT6358_AUDENC_ANA_CON0: |
462 | case MT6358_AUDENC_ANA_CON1: |
463 | regmap_read(map: priv->regmap, MT6358_AUDENC_ANA_CON0, val: ®); |
464 | priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP1] = |
465 | (reg >> RG_AUDPREAMPLGAIN_SFT) & RG_AUDPREAMPLGAIN_MASK; |
466 | regmap_read(map: priv->regmap, MT6358_AUDENC_ANA_CON1, val: ®); |
467 | priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP2] = |
468 | (reg >> RG_AUDPREAMPRGAIN_SFT) & RG_AUDPREAMPRGAIN_MASK; |
469 | break; |
470 | } |
471 | |
472 | return ret; |
473 | } |
474 | |
475 | static void mt6358_restore_pga(struct mt6358_priv *priv); |
476 | |
477 | static int mt6358_enable_wov_phase2(struct mt6358_priv *priv) |
478 | { |
479 | /* analog */ |
480 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
481 | mask: 0xffff, val: 0x0000); |
482 | regmap_update_bits(map: priv->regmap, MT6358_DCXO_CW14, mask: 0xffff, val: 0xa2b5); |
483 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
484 | mask: 0xffff, val: 0x0800); |
485 | mt6358_restore_pga(priv); |
486 | |
487 | regmap_update_bits(map: priv->regmap, MT6358_DCXO_CW13, mask: 0xffff, val: 0x9929); |
488 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
489 | mask: 0xffff, val: 0x0025); |
490 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON8, |
491 | mask: 0xffff, val: 0x0005); |
492 | |
493 | /* digital */ |
494 | regmap_update_bits(map: priv->regmap, MT6358_AUD_TOP_CKPDN_CON0, |
495 | mask: 0xffff, val: 0x0000); |
496 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3, mask: 0xffff, val: 0x0120); |
497 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG0, mask: 0xffff, val: 0xffff); |
498 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG1, mask: 0xffff, val: 0x0200); |
499 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG2, mask: 0xffff, val: 0x2424); |
500 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG3, mask: 0xffff, val: 0xdbac); |
501 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG4, mask: 0xffff, val: 0x029e); |
502 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG5, mask: 0xffff, val: 0x0000); |
503 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_POSDIV_CFG0, |
504 | mask: 0xffff, val: 0x0000); |
505 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_HPF_CFG0, |
506 | mask: 0xffff, val: 0x0451); |
507 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_TOP, mask: 0xffff, val: 0x68d1); |
508 | |
509 | return 0; |
510 | } |
511 | |
512 | static int mt6358_disable_wov_phase2(struct mt6358_priv *priv) |
513 | { |
514 | /* digital */ |
515 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_TOP, mask: 0xffff, val: 0xc000); |
516 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_HPF_CFG0, |
517 | mask: 0xffff, val: 0x0450); |
518 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_POSDIV_CFG0, |
519 | mask: 0xffff, val: 0x0c00); |
520 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG5, mask: 0xffff, val: 0x0100); |
521 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG4, mask: 0xffff, val: 0x006c); |
522 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG3, mask: 0xffff, val: 0xa879); |
523 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG2, mask: 0xffff, val: 0x2323); |
524 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG1, mask: 0xffff, val: 0x0400); |
525 | regmap_update_bits(map: priv->regmap, MT6358_AFE_VOW_CFG0, mask: 0xffff, val: 0x0000); |
526 | regmap_update_bits(map: priv->regmap, MT6358_GPIO_MODE3, mask: 0xffff, val: 0x02d8); |
527 | regmap_update_bits(map: priv->regmap, MT6358_AUD_TOP_CKPDN_CON0, |
528 | mask: 0xffff, val: 0x0000); |
529 | |
530 | /* analog */ |
531 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON8, |
532 | mask: 0xffff, val: 0x0004); |
533 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
534 | mask: 0xffff, val: 0x0000); |
535 | regmap_update_bits(map: priv->regmap, MT6358_DCXO_CW13, mask: 0xffff, val: 0x9829); |
536 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
537 | mask: 0xffff, val: 0x0000); |
538 | mt6358_restore_pga(priv); |
539 | regmap_update_bits(map: priv->regmap, MT6358_DCXO_CW14, mask: 0xffff, val: 0xa2b5); |
540 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
541 | mask: 0xffff, val: 0x0010); |
542 | |
543 | return 0; |
544 | } |
545 | |
546 | static int mt6358_get_wov(struct snd_kcontrol *kcontrol, |
547 | struct snd_ctl_elem_value *ucontrol) |
548 | { |
549 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
550 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); |
551 | |
552 | ucontrol->value.integer.value[0] = priv->wov_enabled; |
553 | return 0; |
554 | } |
555 | |
556 | static int mt6358_put_wov(struct snd_kcontrol *kcontrol, |
557 | struct snd_ctl_elem_value *ucontrol) |
558 | { |
559 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
560 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); |
561 | int enabled = ucontrol->value.integer.value[0]; |
562 | |
563 | if (enabled < 0 || enabled > 1) |
564 | return -EINVAL; |
565 | |
566 | if (priv->wov_enabled != enabled) { |
567 | if (enabled) |
568 | mt6358_enable_wov_phase2(priv); |
569 | else |
570 | mt6358_disable_wov_phase2(priv); |
571 | |
572 | priv->wov_enabled = enabled; |
573 | |
574 | return 1; |
575 | } |
576 | |
577 | return 0; |
578 | } |
579 | |
580 | static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0); |
581 | static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 600, 0); |
582 | |
583 | static const struct snd_kcontrol_new mt6358_snd_controls[] = { |
584 | /* dl pga gain */ |
585 | SOC_DOUBLE_EXT_TLV("Headphone Volume" , |
586 | MT6358_ZCD_CON2, 0, 7, 0x12, 1, |
587 | snd_soc_get_volsw, mt6358_put_volsw, playback_tlv), |
588 | SOC_DOUBLE_EXT_TLV("Lineout Volume" , |
589 | MT6358_ZCD_CON1, 0, 7, 0x12, 1, |
590 | snd_soc_get_volsw, mt6358_put_volsw, playback_tlv), |
591 | SOC_SINGLE_EXT_TLV("Handset Volume" , |
592 | MT6358_ZCD_CON3, 0, 0x12, 1, |
593 | snd_soc_get_volsw, mt6358_put_volsw, playback_tlv), |
594 | /* ul pga gain */ |
595 | SOC_DOUBLE_R_EXT_TLV("PGA Volume" , |
596 | MT6358_AUDENC_ANA_CON0, MT6358_AUDENC_ANA_CON1, |
597 | 8, 4, 0, |
598 | snd_soc_get_volsw, mt6358_put_volsw, pga_tlv), |
599 | |
600 | SOC_SINGLE_BOOL_EXT("Wake-on-Voice Phase2 Switch" , 0, |
601 | mt6358_get_wov, mt6358_put_wov), |
602 | }; |
603 | |
604 | /* MUX */ |
605 | /* LOL MUX */ |
606 | static const char * const lo_in_mux_map[] = { |
607 | "Open" , "Mute" , "Playback" , "Test Mode" |
608 | }; |
609 | |
610 | static int lo_in_mux_map_value[] = { |
611 | 0x0, 0x1, 0x2, 0x3, |
612 | }; |
613 | |
614 | static SOC_VALUE_ENUM_SINGLE_DECL(lo_in_mux_map_enum, |
615 | MT6358_AUDDEC_ANA_CON7, |
616 | RG_AUDLOLMUXINPUTSEL_VAUDP15_SFT, |
617 | RG_AUDLOLMUXINPUTSEL_VAUDP15_MASK, |
618 | lo_in_mux_map, |
619 | lo_in_mux_map_value); |
620 | |
621 | static const struct snd_kcontrol_new lo_in_mux_control = |
622 | SOC_DAPM_ENUM("In Select" , lo_in_mux_map_enum); |
623 | |
624 | /*HP MUX */ |
625 | enum { |
626 | HP_MUX_OPEN = 0, |
627 | HP_MUX_HPSPK, |
628 | HP_MUX_HP, |
629 | HP_MUX_TEST_MODE, |
630 | HP_MUX_HP_IMPEDANCE, |
631 | HP_MUX_MASK = 0x7, |
632 | }; |
633 | |
634 | static const char * const hp_in_mux_map[] = { |
635 | "Open" , |
636 | "LoudSPK Playback" , |
637 | "Audio Playback" , |
638 | "Test Mode" , |
639 | "HP Impedance" , |
640 | }; |
641 | |
642 | static int hp_in_mux_map_value[] = { |
643 | HP_MUX_OPEN, |
644 | HP_MUX_HPSPK, |
645 | HP_MUX_HP, |
646 | HP_MUX_TEST_MODE, |
647 | HP_MUX_HP_IMPEDANCE, |
648 | }; |
649 | |
650 | static SOC_VALUE_ENUM_SINGLE_DECL(hpl_in_mux_map_enum, |
651 | SND_SOC_NOPM, |
652 | 0, |
653 | HP_MUX_MASK, |
654 | hp_in_mux_map, |
655 | hp_in_mux_map_value); |
656 | |
657 | static const struct snd_kcontrol_new hpl_in_mux_control = |
658 | SOC_DAPM_ENUM("HPL Select" , hpl_in_mux_map_enum); |
659 | |
660 | static SOC_VALUE_ENUM_SINGLE_DECL(hpr_in_mux_map_enum, |
661 | SND_SOC_NOPM, |
662 | 0, |
663 | HP_MUX_MASK, |
664 | hp_in_mux_map, |
665 | hp_in_mux_map_value); |
666 | |
667 | static const struct snd_kcontrol_new hpr_in_mux_control = |
668 | SOC_DAPM_ENUM("HPR Select" , hpr_in_mux_map_enum); |
669 | |
670 | /* RCV MUX */ |
671 | enum { |
672 | RCV_MUX_OPEN = 0, |
673 | RCV_MUX_MUTE, |
674 | RCV_MUX_VOICE_PLAYBACK, |
675 | RCV_MUX_TEST_MODE, |
676 | RCV_MUX_MASK = 0x3, |
677 | }; |
678 | |
679 | static const char * const rcv_in_mux_map[] = { |
680 | "Open" , "Mute" , "Voice Playback" , "Test Mode" |
681 | }; |
682 | |
683 | static int rcv_in_mux_map_value[] = { |
684 | RCV_MUX_OPEN, |
685 | RCV_MUX_MUTE, |
686 | RCV_MUX_VOICE_PLAYBACK, |
687 | RCV_MUX_TEST_MODE, |
688 | }; |
689 | |
690 | static SOC_VALUE_ENUM_SINGLE_DECL(rcv_in_mux_map_enum, |
691 | SND_SOC_NOPM, |
692 | 0, |
693 | RCV_MUX_MASK, |
694 | rcv_in_mux_map, |
695 | rcv_in_mux_map_value); |
696 | |
697 | static const struct snd_kcontrol_new rcv_in_mux_control = |
698 | SOC_DAPM_ENUM("RCV Select" , rcv_in_mux_map_enum); |
699 | |
700 | /* DAC In MUX */ |
701 | static const char * const dac_in_mux_map[] = { |
702 | "Normal Path" , "Sgen" |
703 | }; |
704 | |
705 | static int dac_in_mux_map_value[] = { |
706 | 0x0, 0x1, |
707 | }; |
708 | |
709 | static SOC_VALUE_ENUM_SINGLE_DECL(dac_in_mux_map_enum, |
710 | MT6358_AFE_TOP_CON0, |
711 | DL_SINE_ON_SFT, |
712 | DL_SINE_ON_MASK, |
713 | dac_in_mux_map, |
714 | dac_in_mux_map_value); |
715 | |
716 | static const struct snd_kcontrol_new dac_in_mux_control = |
717 | SOC_DAPM_ENUM("DAC Select" , dac_in_mux_map_enum); |
718 | |
719 | /* AIF Out MUX */ |
720 | static SOC_VALUE_ENUM_SINGLE_DECL(aif_out_mux_map_enum, |
721 | MT6358_AFE_TOP_CON0, |
722 | UL_SINE_ON_SFT, |
723 | UL_SINE_ON_MASK, |
724 | dac_in_mux_map, |
725 | dac_in_mux_map_value); |
726 | |
727 | static const struct snd_kcontrol_new aif_out_mux_control = |
728 | SOC_DAPM_ENUM("AIF Out Select" , aif_out_mux_map_enum); |
729 | |
730 | /* Mic Type MUX */ |
731 | enum { |
732 | MIC_TYPE_MUX_IDLE = 0, |
733 | MIC_TYPE_MUX_ACC, |
734 | MIC_TYPE_MUX_DMIC, |
735 | MIC_TYPE_MUX_DCC, |
736 | MIC_TYPE_MUX_DCC_ECM_DIFF, |
737 | MIC_TYPE_MUX_DCC_ECM_SINGLE, |
738 | MIC_TYPE_MUX_MASK = 0x7, |
739 | }; |
740 | |
741 | #define IS_DCC_BASE(type) ((type) == MIC_TYPE_MUX_DCC || \ |
742 | (type) == MIC_TYPE_MUX_DCC_ECM_DIFF || \ |
743 | (type) == MIC_TYPE_MUX_DCC_ECM_SINGLE) |
744 | |
745 | static const char * const mic_type_mux_map[] = { |
746 | "Idle" , |
747 | "ACC" , |
748 | "DMIC" , |
749 | "DCC" , |
750 | "DCC_ECM_DIFF" , |
751 | "DCC_ECM_SINGLE" , |
752 | }; |
753 | |
754 | static int mic_type_mux_map_value[] = { |
755 | MIC_TYPE_MUX_IDLE, |
756 | MIC_TYPE_MUX_ACC, |
757 | MIC_TYPE_MUX_DMIC, |
758 | MIC_TYPE_MUX_DCC, |
759 | MIC_TYPE_MUX_DCC_ECM_DIFF, |
760 | MIC_TYPE_MUX_DCC_ECM_SINGLE, |
761 | }; |
762 | |
763 | static SOC_VALUE_ENUM_SINGLE_DECL(mic_type_mux_map_enum, |
764 | SND_SOC_NOPM, |
765 | 0, |
766 | MIC_TYPE_MUX_MASK, |
767 | mic_type_mux_map, |
768 | mic_type_mux_map_value); |
769 | |
770 | static const struct snd_kcontrol_new mic_type_mux_control = |
771 | SOC_DAPM_ENUM("Mic Type Select" , mic_type_mux_map_enum); |
772 | |
773 | /* ADC L MUX */ |
774 | enum { |
775 | ADC_MUX_IDLE = 0, |
776 | ADC_MUX_AIN0, |
777 | ADC_MUX_PREAMPLIFIER, |
778 | ADC_MUX_IDLE1, |
779 | ADC_MUX_MASK = 0x3, |
780 | }; |
781 | |
782 | static const char * const adc_left_mux_map[] = { |
783 | "Idle" , "AIN0" , "Left Preamplifier" , "Idle_1" |
784 | }; |
785 | |
786 | static int adc_mux_map_value[] = { |
787 | ADC_MUX_IDLE, |
788 | ADC_MUX_AIN0, |
789 | ADC_MUX_PREAMPLIFIER, |
790 | ADC_MUX_IDLE1, |
791 | }; |
792 | |
793 | static SOC_VALUE_ENUM_SINGLE_DECL(adc_left_mux_map_enum, |
794 | SND_SOC_NOPM, |
795 | 0, |
796 | ADC_MUX_MASK, |
797 | adc_left_mux_map, |
798 | adc_mux_map_value); |
799 | |
800 | static const struct snd_kcontrol_new adc_left_mux_control = |
801 | SOC_DAPM_ENUM("ADC L Select" , adc_left_mux_map_enum); |
802 | |
803 | /* ADC R MUX */ |
804 | static const char * const adc_right_mux_map[] = { |
805 | "Idle" , "AIN0" , "Right Preamplifier" , "Idle_1" |
806 | }; |
807 | |
808 | static SOC_VALUE_ENUM_SINGLE_DECL(adc_right_mux_map_enum, |
809 | SND_SOC_NOPM, |
810 | 0, |
811 | ADC_MUX_MASK, |
812 | adc_right_mux_map, |
813 | adc_mux_map_value); |
814 | |
815 | static const struct snd_kcontrol_new adc_right_mux_control = |
816 | SOC_DAPM_ENUM("ADC R Select" , adc_right_mux_map_enum); |
817 | |
818 | /* PGA L MUX */ |
819 | enum { |
820 | PGA_MUX_NONE = 0, |
821 | PGA_MUX_AIN0, |
822 | PGA_MUX_AIN1, |
823 | PGA_MUX_AIN2, |
824 | PGA_MUX_MASK = 0x3, |
825 | }; |
826 | |
827 | static const char * const pga_mux_map[] = { |
828 | "None" , "AIN0" , "AIN1" , "AIN2" |
829 | }; |
830 | |
831 | static int pga_mux_map_value[] = { |
832 | PGA_MUX_NONE, |
833 | PGA_MUX_AIN0, |
834 | PGA_MUX_AIN1, |
835 | PGA_MUX_AIN2, |
836 | }; |
837 | |
838 | static SOC_VALUE_ENUM_SINGLE_DECL(pga_left_mux_map_enum, |
839 | SND_SOC_NOPM, |
840 | 0, |
841 | PGA_MUX_MASK, |
842 | pga_mux_map, |
843 | pga_mux_map_value); |
844 | |
845 | static const struct snd_kcontrol_new pga_left_mux_control = |
846 | SOC_DAPM_ENUM("PGA L Select" , pga_left_mux_map_enum); |
847 | |
848 | /* PGA R MUX */ |
849 | static SOC_VALUE_ENUM_SINGLE_DECL(pga_right_mux_map_enum, |
850 | SND_SOC_NOPM, |
851 | 0, |
852 | PGA_MUX_MASK, |
853 | pga_mux_map, |
854 | pga_mux_map_value); |
855 | |
856 | static const struct snd_kcontrol_new pga_right_mux_control = |
857 | SOC_DAPM_ENUM("PGA R Select" , pga_right_mux_map_enum); |
858 | |
859 | static int mt_clksq_event(struct snd_soc_dapm_widget *w, |
860 | struct snd_kcontrol *kcontrol, |
861 | int event) |
862 | { |
863 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
864 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
865 | |
866 | dev_dbg(priv->dev, "%s(), event = 0x%x\n" , __func__, event); |
867 | |
868 | switch (event) { |
869 | case SND_SOC_DAPM_PRE_PMU: |
870 | /* audio clk source from internal dcxo */ |
871 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON6, |
872 | RG_CLKSQ_IN_SEL_TEST_MASK_SFT, |
873 | val: 0x0); |
874 | break; |
875 | default: |
876 | break; |
877 | } |
878 | |
879 | return 0; |
880 | } |
881 | |
882 | static int mt_sgen_event(struct snd_soc_dapm_widget *w, |
883 | struct snd_kcontrol *kcontrol, |
884 | int event) |
885 | { |
886 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
887 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
888 | |
889 | dev_dbg(priv->dev, "%s(), event = 0x%x\n" , __func__, event); |
890 | |
891 | switch (event) { |
892 | case SND_SOC_DAPM_PRE_PMU: |
893 | /* sdm audio fifo clock power on */ |
894 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0006); |
895 | /* scrambler clock on enable */ |
896 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON0, val: 0xCBA1); |
897 | /* sdm power on */ |
898 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0003); |
899 | /* sdm fifo enable */ |
900 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x000B); |
901 | |
902 | regmap_update_bits(map: priv->regmap, MT6358_AFE_SGEN_CFG0, |
903 | mask: 0xff3f, |
904 | val: 0x0000); |
905 | regmap_update_bits(map: priv->regmap, MT6358_AFE_SGEN_CFG1, |
906 | mask: 0xffff, |
907 | val: 0x0001); |
908 | break; |
909 | case SND_SOC_DAPM_POST_PMD: |
910 | /* DL scrambler disabling sequence */ |
911 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0000); |
912 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON0, val: 0xcba0); |
913 | break; |
914 | default: |
915 | break; |
916 | } |
917 | |
918 | return 0; |
919 | } |
920 | |
921 | static int mt_aif_in_event(struct snd_soc_dapm_widget *w, |
922 | struct snd_kcontrol *kcontrol, |
923 | int event) |
924 | { |
925 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
926 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
927 | |
928 | dev_info(priv->dev, "%s(), event 0x%x, rate %d\n" , |
929 | __func__, event, priv->dl_rate); |
930 | |
931 | switch (event) { |
932 | case SND_SOC_DAPM_PRE_PMU: |
933 | playback_gpio_set(priv); |
934 | |
935 | /* sdm audio fifo clock power on */ |
936 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0006); |
937 | /* scrambler clock on enable */ |
938 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON0, val: 0xCBA1); |
939 | /* sdm power on */ |
940 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0003); |
941 | /* sdm fifo enable */ |
942 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x000B); |
943 | break; |
944 | case SND_SOC_DAPM_POST_PMD: |
945 | /* DL scrambler disabling sequence */ |
946 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON2, val: 0x0000); |
947 | regmap_write(map: priv->regmap, MT6358_AFUNC_AUD_CON0, val: 0xcba0); |
948 | |
949 | playback_gpio_reset(priv); |
950 | break; |
951 | default: |
952 | break; |
953 | } |
954 | |
955 | return 0; |
956 | } |
957 | |
958 | static int mtk_hp_enable(struct mt6358_priv *priv) |
959 | { |
960 | /* Pull-down HPL/R to AVSS28_AUD */ |
961 | hp_pull_down(priv, enable: true); |
962 | /* release HP CMFB gate rstb */ |
963 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
964 | mask: 0x1 << 6, val: 0x1 << 6); |
965 | |
966 | /* Reduce ESD resistance of AU_REFN */ |
967 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, val: 0x4000); |
968 | |
969 | /* Set HPR/HPL gain as minimum (~ -40dB) */ |
970 | regmap_write(map: priv->regmap, MT6358_ZCD_CON2, DL_GAIN_N_40DB_REG); |
971 | |
972 | /* Turn on DA_600K_NCP_VA18 */ |
973 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON1, val: 0x0001); |
974 | /* Set NCP clock as 604kHz // 26MHz/43 = 604KHz */ |
975 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON2, val: 0x002c); |
976 | /* Toggle RG_DIVCKS_CHG */ |
977 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON0, val: 0x0001); |
978 | /* Set NCP soft start mode as default mode: 100us */ |
979 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON4, val: 0x0003); |
980 | /* Enable NCP */ |
981 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, val: 0x0000); |
982 | usleep_range(min: 250, max: 270); |
983 | |
984 | /* Enable cap-less LDOs (1.5V) */ |
985 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
986 | mask: 0x1055, val: 0x1055); |
987 | /* Enable NV regulator (-1.2V) */ |
988 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, val: 0x0001); |
989 | usleep_range(min: 100, max: 120); |
990 | |
991 | /* Disable AUD_ZCD */ |
992 | hp_zcd_disable(priv); |
993 | |
994 | /* Disable headphone short-circuit protection */ |
995 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x3000); |
996 | |
997 | /* Enable IBIST */ |
998 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
999 | |
1000 | /* Set HP DR bias current optimization, 010: 6uA */ |
1001 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON11, val: 0x4900); |
1002 | /* Set HP & ZCD bias current optimization */ |
1003 | /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ |
1004 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
1005 | /* Set HPP/N STB enhance circuits */ |
1006 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, val: 0x4033); |
1007 | |
1008 | /* Enable HP aux output stage */ |
1009 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x000c); |
1010 | /* Enable HP aux feedback loop */ |
1011 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x003c); |
1012 | /* Enable HP aux CMFB loop */ |
1013 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0c00); |
1014 | /* Enable HP driver bias circuits */ |
1015 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30c0); |
1016 | /* Enable HP driver core circuits */ |
1017 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30f0); |
1018 | /* Short HP main output to HP aux output stage */ |
1019 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x00fc); |
1020 | |
1021 | /* Enable HP main CMFB loop */ |
1022 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0e00); |
1023 | /* Disable HP aux CMFB loop */ |
1024 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0200); |
1025 | |
1026 | /* Select CMFB resistor bulk to AC mode */ |
1027 | /* Selec HS/LO cap size (6.5pF default) */ |
1028 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON10, val: 0x0000); |
1029 | |
1030 | /* Enable HP main output stage */ |
1031 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x00ff); |
1032 | /* Enable HPR/L main output stage step by step */ |
1033 | hp_main_output_ramp(priv, up: true); |
1034 | |
1035 | /* Reduce HP aux feedback loop gain */ |
1036 | hp_aux_feedback_loop_gain_ramp(priv, up: true); |
1037 | /* Disable HP aux feedback loop */ |
1038 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fcf); |
1039 | |
1040 | /* apply volume setting */ |
1041 | headset_volume_ramp(priv, |
1042 | from: DL_GAIN_N_10DB, |
1043 | to: priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL]); |
1044 | |
1045 | /* Disable HP aux output stage */ |
1046 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fc3); |
1047 | /* Unshort HP main output to HP aux output stage */ |
1048 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3f03); |
1049 | usleep_range(min: 100, max: 120); |
1050 | |
1051 | /* Enable AUD_CLK */ |
1052 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, mask: 0x1, val: 0x1); |
1053 | /* Enable Audio DAC */ |
1054 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30ff); |
1055 | /* Enable low-noise mode of DAC */ |
1056 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0xf201); |
1057 | usleep_range(min: 100, max: 120); |
1058 | |
1059 | /* Switch HPL MUX to audio DAC */ |
1060 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x32ff); |
1061 | /* Switch HPR MUX to audio DAC */ |
1062 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x3aff); |
1063 | |
1064 | /* Disable Pull-down HPL/R to AVSS28_AUD */ |
1065 | hp_pull_down(priv, enable: false); |
1066 | |
1067 | return 0; |
1068 | } |
1069 | |
1070 | static int mtk_hp_disable(struct mt6358_priv *priv) |
1071 | { |
1072 | /* Pull-down HPL/R to AVSS28_AUD */ |
1073 | hp_pull_down(priv, enable: true); |
1074 | |
1075 | /* HPR/HPL mux to open */ |
1076 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1077 | mask: 0x0f00, val: 0x0000); |
1078 | |
1079 | /* Disable low-noise mode of DAC */ |
1080 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, |
1081 | mask: 0x0001, val: 0x0000); |
1082 | |
1083 | /* Disable Audio DAC */ |
1084 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1085 | mask: 0x000f, val: 0x0000); |
1086 | |
1087 | /* Disable AUD_CLK */ |
1088 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, mask: 0x1, val: 0x0); |
1089 | |
1090 | /* Short HP main output to HP aux output stage */ |
1091 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fc3); |
1092 | /* Enable HP aux output stage */ |
1093 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fcf); |
1094 | |
1095 | /* decrease HPL/R gain to normal gain step by step */ |
1096 | headset_volume_ramp(priv, |
1097 | from: priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL], |
1098 | to: DL_GAIN_N_40DB); |
1099 | |
1100 | /* Enable HP aux feedback loop */ |
1101 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fff); |
1102 | |
1103 | /* Reduce HP aux feedback loop gain */ |
1104 | hp_aux_feedback_loop_gain_ramp(priv, up: false); |
1105 | |
1106 | /* decrease HPR/L main output stage step by step */ |
1107 | hp_main_output_ramp(priv, up: false); |
1108 | |
1109 | /* Disable HP main output stage */ |
1110 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, mask: 0x3, val: 0x0); |
1111 | |
1112 | /* Enable HP aux CMFB loop */ |
1113 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0e00); |
1114 | |
1115 | /* Disable HP main CMFB loop */ |
1116 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0c00); |
1117 | |
1118 | /* Unshort HP main output to HP aux output stage */ |
1119 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, |
1120 | mask: 0x3 << 6, val: 0x0); |
1121 | |
1122 | /* Disable HP driver core circuits */ |
1123 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1124 | mask: 0x3 << 4, val: 0x0); |
1125 | |
1126 | /* Disable HP driver bias circuits */ |
1127 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1128 | mask: 0x3 << 6, val: 0x0); |
1129 | |
1130 | /* Disable HP aux CMFB loop */ |
1131 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0000); |
1132 | |
1133 | /* Disable HP aux feedback loop */ |
1134 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, |
1135 | mask: 0x3 << 4, val: 0x0); |
1136 | |
1137 | /* Disable HP aux output stage */ |
1138 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, |
1139 | mask: 0x3 << 2, val: 0x0); |
1140 | |
1141 | /* Disable IBIST */ |
1142 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, |
1143 | mask: 0x1 << 8, val: 0x1 << 8); |
1144 | |
1145 | /* Disable NV regulator (-1.2V) */ |
1146 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, mask: 0x1, val: 0x0); |
1147 | /* Disable cap-less LDOs (1.5V) */ |
1148 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1149 | mask: 0x1055, val: 0x0); |
1150 | /* Disable NCP */ |
1151 | regmap_update_bits(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, |
1152 | mask: 0x1, val: 0x1); |
1153 | |
1154 | /* Increase ESD resistance of AU_REFN */ |
1155 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, |
1156 | mask: 0x1 << 14, val: 0x0); |
1157 | |
1158 | /* Set HP CMFB gate rstb */ |
1159 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
1160 | mask: 0x1 << 6, val: 0x0); |
1161 | /* disable Pull-down HPL/R to AVSS28_AUD */ |
1162 | hp_pull_down(priv, enable: false); |
1163 | |
1164 | return 0; |
1165 | } |
1166 | |
1167 | static int mtk_hp_spk_enable(struct mt6358_priv *priv) |
1168 | { |
1169 | /* Pull-down HPL/R to AVSS28_AUD */ |
1170 | hp_pull_down(priv, enable: true); |
1171 | /* release HP CMFB gate rstb */ |
1172 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
1173 | mask: 0x1 << 6, val: 0x1 << 6); |
1174 | |
1175 | /* Reduce ESD resistance of AU_REFN */ |
1176 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, val: 0x4000); |
1177 | |
1178 | /* Set HPR/HPL gain to -10dB */ |
1179 | regmap_write(map: priv->regmap, MT6358_ZCD_CON2, DL_GAIN_N_10DB_REG); |
1180 | |
1181 | /* Turn on DA_600K_NCP_VA18 */ |
1182 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON1, val: 0x0001); |
1183 | /* Set NCP clock as 604kHz // 26MHz/43 = 604KHz */ |
1184 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON2, val: 0x002c); |
1185 | /* Toggle RG_DIVCKS_CHG */ |
1186 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON0, val: 0x0001); |
1187 | /* Set NCP soft start mode as default mode: 100us */ |
1188 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON4, val: 0x0003); |
1189 | /* Enable NCP */ |
1190 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, val: 0x0000); |
1191 | usleep_range(min: 250, max: 270); |
1192 | |
1193 | /* Enable cap-less LDOs (1.5V) */ |
1194 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1195 | mask: 0x1055, val: 0x1055); |
1196 | /* Enable NV regulator (-1.2V) */ |
1197 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, val: 0x0001); |
1198 | usleep_range(min: 100, max: 120); |
1199 | |
1200 | /* Disable AUD_ZCD */ |
1201 | hp_zcd_disable(priv); |
1202 | |
1203 | /* Disable headphone short-circuit protection */ |
1204 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x3000); |
1205 | |
1206 | /* Enable IBIST */ |
1207 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
1208 | |
1209 | /* Set HP DR bias current optimization, 010: 6uA */ |
1210 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON11, val: 0x4900); |
1211 | /* Set HP & ZCD bias current optimization */ |
1212 | /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ |
1213 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
1214 | /* Set HPP/N STB enhance circuits */ |
1215 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, val: 0x4033); |
1216 | |
1217 | /* Disable Pull-down HPL/R to AVSS28_AUD */ |
1218 | hp_pull_down(priv, enable: false); |
1219 | |
1220 | /* Enable HP driver bias circuits */ |
1221 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30c0); |
1222 | /* Enable HP driver core circuits */ |
1223 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30f0); |
1224 | /* Enable HP main CMFB loop */ |
1225 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0200); |
1226 | |
1227 | /* Select CMFB resistor bulk to AC mode */ |
1228 | /* Selec HS/LO cap size (6.5pF default) */ |
1229 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON10, val: 0x0000); |
1230 | |
1231 | /* Enable HP main output stage */ |
1232 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x0003); |
1233 | /* Enable HPR/L main output stage step by step */ |
1234 | hp_main_output_ramp(priv, up: true); |
1235 | |
1236 | /* Set LO gain as minimum (~ -40dB) */ |
1237 | regmap_write(map: priv->regmap, MT6358_ZCD_CON1, DL_GAIN_N_40DB_REG); |
1238 | /* apply volume setting */ |
1239 | headset_volume_ramp(priv, |
1240 | from: DL_GAIN_N_10DB, |
1241 | to: priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL]); |
1242 | |
1243 | /* Set LO STB enhance circuits */ |
1244 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, val: 0x0110); |
1245 | /* Enable LO driver bias circuits */ |
1246 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, val: 0x0112); |
1247 | /* Enable LO driver core circuits */ |
1248 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, val: 0x0113); |
1249 | |
1250 | /* Set LOL gain to normal gain step by step */ |
1251 | regmap_update_bits(map: priv->regmap, MT6358_ZCD_CON1, |
1252 | RG_AUDLOLGAIN_MASK_SFT, |
1253 | val: priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL] << |
1254 | RG_AUDLOLGAIN_SFT); |
1255 | regmap_update_bits(map: priv->regmap, MT6358_ZCD_CON1, |
1256 | RG_AUDLORGAIN_MASK_SFT, |
1257 | val: priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTR] << |
1258 | RG_AUDLORGAIN_SFT); |
1259 | |
1260 | /* Enable AUD_CLK */ |
1261 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, mask: 0x1, val: 0x1); |
1262 | /* Enable Audio DAC */ |
1263 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x30f9); |
1264 | /* Enable low-noise mode of DAC */ |
1265 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0201); |
1266 | /* Switch LOL MUX to audio DAC */ |
1267 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, val: 0x011b); |
1268 | /* Switch HPL/R MUX to Line-out */ |
1269 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x35f9); |
1270 | |
1271 | return 0; |
1272 | } |
1273 | |
1274 | static int mtk_hp_spk_disable(struct mt6358_priv *priv) |
1275 | { |
1276 | /* HPR/HPL mux to open */ |
1277 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1278 | mask: 0x0f00, val: 0x0000); |
1279 | /* LOL mux to open */ |
1280 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, |
1281 | mask: 0x3 << 2, val: 0x0000); |
1282 | |
1283 | /* Disable Audio DAC */ |
1284 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1285 | mask: 0x000f, val: 0x0000); |
1286 | |
1287 | /* Disable AUD_CLK */ |
1288 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, mask: 0x1, val: 0x0); |
1289 | |
1290 | /* decrease HPL/R gain to normal gain step by step */ |
1291 | headset_volume_ramp(priv, |
1292 | from: priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL], |
1293 | to: DL_GAIN_N_40DB); |
1294 | |
1295 | /* decrease LOL gain to minimum gain step by step */ |
1296 | regmap_update_bits(map: priv->regmap, MT6358_ZCD_CON1, |
1297 | DL_GAIN_REG_MASK, DL_GAIN_N_40DB_REG); |
1298 | |
1299 | /* decrease HPR/L main output stage step by step */ |
1300 | hp_main_output_ramp(priv, up: false); |
1301 | |
1302 | /* Disable HP main output stage */ |
1303 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, mask: 0x3, val: 0x0); |
1304 | |
1305 | /* Short HP main output to HP aux output stage */ |
1306 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fc3); |
1307 | /* Enable HP aux output stage */ |
1308 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fcf); |
1309 | |
1310 | /* Enable HP aux feedback loop */ |
1311 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON1, val: 0x3fff); |
1312 | |
1313 | /* Reduce HP aux feedback loop gain */ |
1314 | hp_aux_feedback_loop_gain_ramp(priv, up: false); |
1315 | |
1316 | /* Disable HP driver core circuits */ |
1317 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1318 | mask: 0x3 << 4, val: 0x0); |
1319 | /* Disable LO driver core circuits */ |
1320 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, |
1321 | mask: 0x1, val: 0x0); |
1322 | |
1323 | /* Disable HP driver bias circuits */ |
1324 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1325 | mask: 0x3 << 6, val: 0x0); |
1326 | /* Disable LO driver bias circuits */ |
1327 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, |
1328 | mask: 0x1 << 1, val: 0x0); |
1329 | |
1330 | /* Disable HP aux CMFB loop */ |
1331 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, |
1332 | mask: 0xff << 8, val: 0x0000); |
1333 | |
1334 | /* Disable IBIST */ |
1335 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, |
1336 | mask: 0x1 << 8, val: 0x1 << 8); |
1337 | /* Disable NV regulator (-1.2V) */ |
1338 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, mask: 0x1, val: 0x0); |
1339 | /* Disable cap-less LDOs (1.5V) */ |
1340 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, mask: 0x1055, val: 0x0); |
1341 | /* Disable NCP */ |
1342 | regmap_update_bits(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, mask: 0x1, val: 0x1); |
1343 | |
1344 | /* Set HP CMFB gate rstb */ |
1345 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON4, |
1346 | mask: 0x1 << 6, val: 0x0); |
1347 | /* disable Pull-down HPL/R to AVSS28_AUD */ |
1348 | hp_pull_down(priv, enable: false); |
1349 | |
1350 | return 0; |
1351 | } |
1352 | |
1353 | static int mt_hp_event(struct snd_soc_dapm_widget *w, |
1354 | struct snd_kcontrol *kcontrol, |
1355 | int event) |
1356 | { |
1357 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1358 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1359 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1360 | int device = DEVICE_HP; |
1361 | |
1362 | dev_info(priv->dev, "%s(), event 0x%x, dev_counter[DEV_HP] %d, mux %u\n" , |
1363 | __func__, |
1364 | event, |
1365 | priv->dev_counter[device], |
1366 | mux); |
1367 | |
1368 | switch (event) { |
1369 | case SND_SOC_DAPM_PRE_PMU: |
1370 | priv->dev_counter[device]++; |
1371 | if (priv->dev_counter[device] > 1) |
1372 | break; /* already enabled, do nothing */ |
1373 | else if (priv->dev_counter[device] <= 0) |
1374 | dev_warn(priv->dev, "%s(), dev_counter[DEV_HP] %d <= 0\n" , |
1375 | __func__, |
1376 | priv->dev_counter[device]); |
1377 | |
1378 | priv->mux_select[MUX_HP_L] = mux; |
1379 | |
1380 | if (mux == HP_MUX_HP) |
1381 | mtk_hp_enable(priv); |
1382 | else if (mux == HP_MUX_HPSPK) |
1383 | mtk_hp_spk_enable(priv); |
1384 | break; |
1385 | case SND_SOC_DAPM_PRE_PMD: |
1386 | priv->dev_counter[device]--; |
1387 | if (priv->dev_counter[device] > 0) { |
1388 | break; /* still being used, don't close */ |
1389 | } else if (priv->dev_counter[device] < 0) { |
1390 | dev_warn(priv->dev, "%s(), dev_counter[DEV_HP] %d < 0\n" , |
1391 | __func__, |
1392 | priv->dev_counter[device]); |
1393 | priv->dev_counter[device] = 0; |
1394 | break; |
1395 | } |
1396 | |
1397 | if (priv->mux_select[MUX_HP_L] == HP_MUX_HP) |
1398 | mtk_hp_disable(priv); |
1399 | else if (priv->mux_select[MUX_HP_L] == HP_MUX_HPSPK) |
1400 | mtk_hp_spk_disable(priv); |
1401 | |
1402 | priv->mux_select[MUX_HP_L] = mux; |
1403 | break; |
1404 | default: |
1405 | break; |
1406 | } |
1407 | |
1408 | return 0; |
1409 | } |
1410 | |
1411 | static int mt_rcv_event(struct snd_soc_dapm_widget *w, |
1412 | struct snd_kcontrol *kcontrol, |
1413 | int event) |
1414 | { |
1415 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1416 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1417 | |
1418 | dev_info(priv->dev, "%s(), event 0x%x, mux %u\n" , |
1419 | __func__, |
1420 | event, |
1421 | dapm_kcontrol_get_value(w->kcontrols[0])); |
1422 | |
1423 | switch (event) { |
1424 | case SND_SOC_DAPM_PRE_PMU: |
1425 | /* Reduce ESD resistance of AU_REFN */ |
1426 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON2, val: 0x4000); |
1427 | |
1428 | /* Turn on DA_600K_NCP_VA18 */ |
1429 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON1, val: 0x0001); |
1430 | /* Set NCP clock as 604kHz // 26MHz/43 = 604KHz */ |
1431 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON2, val: 0x002c); |
1432 | /* Toggle RG_DIVCKS_CHG */ |
1433 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON0, val: 0x0001); |
1434 | /* Set NCP soft start mode as default mode: 100us */ |
1435 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON4, val: 0x0003); |
1436 | /* Enable NCP */ |
1437 | regmap_write(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, val: 0x0000); |
1438 | usleep_range(min: 250, max: 270); |
1439 | |
1440 | /* Enable cap-less LDOs (1.5V) */ |
1441 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1442 | mask: 0x1055, val: 0x1055); |
1443 | /* Enable NV regulator (-1.2V) */ |
1444 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, val: 0x0001); |
1445 | usleep_range(min: 100, max: 120); |
1446 | |
1447 | /* Disable AUD_ZCD */ |
1448 | hp_zcd_disable(priv); |
1449 | |
1450 | /* Disable handset short-circuit protection */ |
1451 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, val: 0x0010); |
1452 | |
1453 | /* Enable IBIST */ |
1454 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
1455 | /* Set HP DR bias current optimization, 010: 6uA */ |
1456 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON11, val: 0x4900); |
1457 | /* Set HP & ZCD bias current optimization */ |
1458 | /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ |
1459 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, val: 0x0055); |
1460 | /* Set HS STB enhance circuits */ |
1461 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, val: 0x0090); |
1462 | |
1463 | /* Disable HP main CMFB loop */ |
1464 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0000); |
1465 | /* Select CMFB resistor bulk to AC mode */ |
1466 | /* Selec HS/LO cap size (6.5pF default) */ |
1467 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON10, val: 0x0000); |
1468 | |
1469 | /* Enable HS driver bias circuits */ |
1470 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, val: 0x0092); |
1471 | /* Enable HS driver core circuits */ |
1472 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, val: 0x0093); |
1473 | |
1474 | /* Enable AUD_CLK */ |
1475 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
1476 | mask: 0x1, val: 0x1); |
1477 | |
1478 | /* Enable Audio DAC */ |
1479 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, val: 0x0009); |
1480 | /* Enable low-noise mode of DAC */ |
1481 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, val: 0x0001); |
1482 | /* Switch HS MUX to audio DAC */ |
1483 | regmap_write(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, val: 0x009b); |
1484 | break; |
1485 | case SND_SOC_DAPM_PRE_PMD: |
1486 | /* HS mux to open */ |
1487 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, |
1488 | RG_AUDHSMUXINPUTSEL_VAUDP15_MASK_SFT, |
1489 | val: RCV_MUX_OPEN); |
1490 | |
1491 | /* Disable Audio DAC */ |
1492 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
1493 | mask: 0x000f, val: 0x0000); |
1494 | |
1495 | /* Disable AUD_CLK */ |
1496 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
1497 | mask: 0x1, val: 0x0); |
1498 | |
1499 | /* decrease HS gain to minimum gain step by step */ |
1500 | regmap_write(map: priv->regmap, MT6358_ZCD_CON3, val: DL_GAIN_N_40DB); |
1501 | |
1502 | /* Disable HS driver core circuits */ |
1503 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, |
1504 | mask: 0x1, val: 0x0); |
1505 | |
1506 | /* Disable HS driver bias circuits */ |
1507 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, |
1508 | mask: 0x1 << 1, val: 0x0000); |
1509 | |
1510 | /* Disable HP aux CMFB loop */ |
1511 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, |
1512 | mask: 0xff << 8, val: 0x0); |
1513 | |
1514 | /* Enable HP main CMFB Switch */ |
1515 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON9, |
1516 | mask: 0xff << 8, val: 0x2 << 8); |
1517 | |
1518 | /* Disable IBIST */ |
1519 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON12, |
1520 | mask: 0x1 << 8, val: 0x1 << 8); |
1521 | |
1522 | /* Disable NV regulator (-1.2V) */ |
1523 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON15, |
1524 | mask: 0x1, val: 0x0); |
1525 | /* Disable cap-less LDOs (1.5V) */ |
1526 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1527 | mask: 0x1055, val: 0x0); |
1528 | /* Disable NCP */ |
1529 | regmap_update_bits(map: priv->regmap, MT6358_AUDNCP_CLKDIV_CON3, |
1530 | mask: 0x1, val: 0x1); |
1531 | break; |
1532 | default: |
1533 | break; |
1534 | } |
1535 | |
1536 | return 0; |
1537 | } |
1538 | |
1539 | static int mt_aif_out_event(struct snd_soc_dapm_widget *w, |
1540 | struct snd_kcontrol *kcontrol, |
1541 | int event) |
1542 | { |
1543 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1544 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1545 | |
1546 | dev_dbg(priv->dev, "%s(), event 0x%x, rate %d\n" , |
1547 | __func__, event, priv->ul_rate); |
1548 | |
1549 | switch (event) { |
1550 | case SND_SOC_DAPM_PRE_PMU: |
1551 | capture_gpio_set(priv); |
1552 | break; |
1553 | case SND_SOC_DAPM_POST_PMD: |
1554 | capture_gpio_reset(priv); |
1555 | break; |
1556 | default: |
1557 | break; |
1558 | } |
1559 | |
1560 | return 0; |
1561 | } |
1562 | |
1563 | static int mt_adc_supply_event(struct snd_soc_dapm_widget *w, |
1564 | struct snd_kcontrol *kcontrol, |
1565 | int event) |
1566 | { |
1567 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1568 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1569 | |
1570 | dev_dbg(priv->dev, "%s(), event 0x%x\n" , |
1571 | __func__, event); |
1572 | |
1573 | switch (event) { |
1574 | case SND_SOC_DAPM_PRE_PMU: |
1575 | /* Enable audio ADC CLKGEN */ |
1576 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
1577 | mask: 0x1 << 5, val: 0x1 << 5); |
1578 | /* ADC CLK from CLKGEN (13MHz) */ |
1579 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON3, |
1580 | val: 0x0000); |
1581 | /* Enable LCLDO_ENC 1P8V */ |
1582 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1583 | mask: 0x2500, val: 0x0100); |
1584 | /* LCLDO_ENC remote sense */ |
1585 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1586 | mask: 0x2500, val: 0x2500); |
1587 | break; |
1588 | case SND_SOC_DAPM_POST_PMD: |
1589 | /* LCLDO_ENC remote sense off */ |
1590 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1591 | mask: 0x2500, val: 0x0100); |
1592 | /* disable LCLDO_ENC 1P8V */ |
1593 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON14, |
1594 | mask: 0x2500, val: 0x0000); |
1595 | |
1596 | /* ADC CLK from CLKGEN (13MHz) */ |
1597 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON3, val: 0x0000); |
1598 | /* disable audio ADC CLKGEN */ |
1599 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON13, |
1600 | mask: 0x1 << 5, val: 0x0 << 5); |
1601 | break; |
1602 | default: |
1603 | break; |
1604 | } |
1605 | |
1606 | return 0; |
1607 | } |
1608 | |
1609 | static int mt6358_amic_enable(struct mt6358_priv *priv) |
1610 | { |
1611 | unsigned int mic_type = priv->mux_select[MUX_MIC_TYPE]; |
1612 | unsigned int mux_pga_l = priv->mux_select[MUX_PGA_L]; |
1613 | unsigned int mux_pga_r = priv->mux_select[MUX_PGA_R]; |
1614 | |
1615 | dev_info(priv->dev, "%s(), mux, mic %u, pga l %u, pga r %u\n" , |
1616 | __func__, mic_type, mux_pga_l, mux_pga_r); |
1617 | |
1618 | if (IS_DCC_BASE(mic_type)) { |
1619 | /* DCC 50k CLK (from 26M) */ |
1620 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2062); |
1621 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2062); |
1622 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2060); |
1623 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2061); |
1624 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG1, val: 0x0100); |
1625 | } |
1626 | |
1627 | /* mic bias 0 */ |
1628 | if (mux_pga_l == PGA_MUX_AIN0 || mux_pga_l == PGA_MUX_AIN2 || |
1629 | mux_pga_r == PGA_MUX_AIN0 || mux_pga_r == PGA_MUX_AIN2) { |
1630 | switch (mic_type) { |
1631 | case MIC_TYPE_MUX_DCC_ECM_DIFF: |
1632 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
1633 | mask: 0xff00, val: 0x7700); |
1634 | break; |
1635 | case MIC_TYPE_MUX_DCC_ECM_SINGLE: |
1636 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
1637 | mask: 0xff00, val: 0x1100); |
1638 | break; |
1639 | default: |
1640 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
1641 | mask: 0xff00, val: 0x0000); |
1642 | break; |
1643 | } |
1644 | /* Enable MICBIAS0, MISBIAS0 = 1P9V */ |
1645 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON9, |
1646 | mask: 0xff, val: 0x21); |
1647 | } |
1648 | |
1649 | /* mic bias 1 */ |
1650 | if (mux_pga_l == PGA_MUX_AIN1 || mux_pga_r == PGA_MUX_AIN1) { |
1651 | /* Enable MICBIAS1, MISBIAS1 = 2P6V */ |
1652 | if (mic_type == MIC_TYPE_MUX_DCC_ECM_SINGLE) |
1653 | regmap_write(map: priv->regmap, |
1654 | MT6358_AUDENC_ANA_CON10, val: 0x0161); |
1655 | else |
1656 | regmap_write(map: priv->regmap, |
1657 | MT6358_AUDENC_ANA_CON10, val: 0x0061); |
1658 | } |
1659 | |
1660 | if (IS_DCC_BASE(mic_type)) { |
1661 | /* Audio L/R preamplifier DCC precharge */ |
1662 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1663 | mask: 0xf8ff, val: 0x0004); |
1664 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1665 | mask: 0xf8ff, val: 0x0004); |
1666 | } else { |
1667 | /* reset reg */ |
1668 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1669 | mask: 0xf8ff, val: 0x0000); |
1670 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1671 | mask: 0xf8ff, val: 0x0000); |
1672 | } |
1673 | |
1674 | if (mux_pga_l != PGA_MUX_NONE) { |
1675 | /* L preamplifier input sel */ |
1676 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1677 | RG_AUDPREAMPLINPUTSEL_MASK_SFT, |
1678 | val: mux_pga_l << RG_AUDPREAMPLINPUTSEL_SFT); |
1679 | |
1680 | /* L preamplifier enable */ |
1681 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1682 | RG_AUDPREAMPLON_MASK_SFT, |
1683 | val: 0x1 << RG_AUDPREAMPLON_SFT); |
1684 | |
1685 | if (IS_DCC_BASE(mic_type)) { |
1686 | /* L preamplifier DCCEN */ |
1687 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1688 | RG_AUDPREAMPLDCCEN_MASK_SFT, |
1689 | val: 0x1 << RG_AUDPREAMPLDCCEN_SFT); |
1690 | } |
1691 | |
1692 | /* L ADC input sel : L PGA. Enable audio L ADC */ |
1693 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1694 | RG_AUDADCLINPUTSEL_MASK_SFT, |
1695 | val: ADC_MUX_PREAMPLIFIER << |
1696 | RG_AUDADCLINPUTSEL_SFT); |
1697 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1698 | RG_AUDADCLPWRUP_MASK_SFT, |
1699 | val: 0x1 << RG_AUDADCLPWRUP_SFT); |
1700 | } |
1701 | |
1702 | if (mux_pga_r != PGA_MUX_NONE) { |
1703 | /* R preamplifier input sel */ |
1704 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1705 | RG_AUDPREAMPRINPUTSEL_MASK_SFT, |
1706 | val: mux_pga_r << RG_AUDPREAMPRINPUTSEL_SFT); |
1707 | |
1708 | /* R preamplifier enable */ |
1709 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1710 | RG_AUDPREAMPRON_MASK_SFT, |
1711 | val: 0x1 << RG_AUDPREAMPRON_SFT); |
1712 | |
1713 | if (IS_DCC_BASE(mic_type)) { |
1714 | /* R preamplifier DCCEN */ |
1715 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1716 | RG_AUDPREAMPRDCCEN_MASK_SFT, |
1717 | val: 0x1 << RG_AUDPREAMPRDCCEN_SFT); |
1718 | } |
1719 | |
1720 | /* R ADC input sel : R PGA. Enable audio R ADC */ |
1721 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1722 | RG_AUDADCRINPUTSEL_MASK_SFT, |
1723 | val: ADC_MUX_PREAMPLIFIER << |
1724 | RG_AUDADCRINPUTSEL_SFT); |
1725 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1726 | RG_AUDADCRPWRUP_MASK_SFT, |
1727 | val: 0x1 << RG_AUDADCRPWRUP_SFT); |
1728 | } |
1729 | |
1730 | if (IS_DCC_BASE(mic_type)) { |
1731 | usleep_range(min: 100, max: 150); |
1732 | /* Audio L preamplifier DCC precharge off */ |
1733 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1734 | RG_AUDPREAMPLDCPRECHARGE_MASK_SFT, val: 0x0); |
1735 | /* Audio R preamplifier DCC precharge off */ |
1736 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1737 | RG_AUDPREAMPRDCPRECHARGE_MASK_SFT, val: 0x0); |
1738 | |
1739 | /* Short body to ground in PGA */ |
1740 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON3, |
1741 | mask: 0x1 << 12, val: 0x0); |
1742 | } |
1743 | |
1744 | /* here to set digital part */ |
1745 | mt6358_mtkaif_tx_enable(priv); |
1746 | |
1747 | /* UL dmic setting off */ |
1748 | regmap_write(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_H, val: 0x0000); |
1749 | |
1750 | /* UL turn on */ |
1751 | regmap_write(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_L, val: 0x0001); |
1752 | |
1753 | return 0; |
1754 | } |
1755 | |
1756 | static void mt6358_amic_disable(struct mt6358_priv *priv) |
1757 | { |
1758 | unsigned int mic_type = priv->mux_select[MUX_MIC_TYPE]; |
1759 | unsigned int mux_pga_l = priv->mux_select[MUX_PGA_L]; |
1760 | unsigned int mux_pga_r = priv->mux_select[MUX_PGA_R]; |
1761 | |
1762 | dev_info(priv->dev, "%s(), mux, mic %u, pga l %u, pga r %u\n" , |
1763 | __func__, mic_type, mux_pga_l, mux_pga_r); |
1764 | |
1765 | /* UL turn off */ |
1766 | regmap_update_bits(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_L, |
1767 | mask: 0x0001, val: 0x0000); |
1768 | |
1769 | /* disable aud_pad TX fifos */ |
1770 | mt6358_mtkaif_tx_disable(priv); |
1771 | |
1772 | /* L ADC input sel : off, disable L ADC */ |
1773 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1774 | mask: 0xf000, val: 0x0000); |
1775 | /* L preamplifier DCCEN */ |
1776 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1777 | mask: 0x1 << 1, val: 0x0); |
1778 | /* L preamplifier input sel : off, L PGA 0 dB gain */ |
1779 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1780 | mask: 0xfffb, val: 0x0000); |
1781 | |
1782 | /* disable L preamplifier DCC precharge */ |
1783 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1784 | mask: 0x1 << 2, val: 0x0); |
1785 | |
1786 | /* R ADC input sel : off, disable R ADC */ |
1787 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1788 | mask: 0xf000, val: 0x0000); |
1789 | /* R preamplifier DCCEN */ |
1790 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1791 | mask: 0x1 << 1, val: 0x0); |
1792 | /* R preamplifier input sel : off, R PGA 0 dB gain */ |
1793 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1794 | mask: 0x0ffb, val: 0x0000); |
1795 | |
1796 | /* disable R preamplifier DCC precharge */ |
1797 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1798 | mask: 0x1 << 2, val: 0x0); |
1799 | |
1800 | /* mic bias */ |
1801 | /* Disable MICBIAS0, MISBIAS0 = 1P7V */ |
1802 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON9, val: 0x0000); |
1803 | |
1804 | /* Disable MICBIAS1 */ |
1805 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON10, |
1806 | mask: 0x0001, val: 0x0000); |
1807 | |
1808 | if (IS_DCC_BASE(mic_type)) { |
1809 | /* dcclk_gen_on=1'b0 */ |
1810 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2060); |
1811 | /* dcclk_pdn=1'b1 */ |
1812 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2062); |
1813 | /* dcclk_ref_ck_sel=2'b00 */ |
1814 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2062); |
1815 | /* dcclk_div=11'b00100000011 */ |
1816 | regmap_write(map: priv->regmap, MT6358_AFE_DCCLK_CFG0, val: 0x2062); |
1817 | } |
1818 | } |
1819 | |
1820 | static int mt6358_dmic_enable(struct mt6358_priv *priv) |
1821 | { |
1822 | dev_info(priv->dev, "%s()\n" , __func__); |
1823 | |
1824 | /* mic bias */ |
1825 | /* Enable MICBIAS0, MISBIAS0 = 1P9V */ |
1826 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON9, val: 0x0021); |
1827 | |
1828 | /* RG_BANDGAPGEN=1'b0 */ |
1829 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON10, |
1830 | mask: 0x1 << 12, val: 0x0); |
1831 | |
1832 | /* DMIC enable */ |
1833 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON8, val: 0x0005); |
1834 | |
1835 | /* here to set digital part */ |
1836 | mt6358_mtkaif_tx_enable(priv); |
1837 | |
1838 | /* UL dmic setting */ |
1839 | if (priv->dmic_one_wire_mode) |
1840 | regmap_write(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_H, val: 0x0400); |
1841 | else |
1842 | regmap_write(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_H, val: 0x0080); |
1843 | |
1844 | /* UL turn on */ |
1845 | regmap_write(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_L, val: 0x0003); |
1846 | |
1847 | /* Prevent pop noise form dmic hw */ |
1848 | msleep(msecs: 100); |
1849 | |
1850 | return 0; |
1851 | } |
1852 | |
1853 | static void mt6358_dmic_disable(struct mt6358_priv *priv) |
1854 | { |
1855 | dev_info(priv->dev, "%s()\n" , __func__); |
1856 | |
1857 | /* UL turn off */ |
1858 | regmap_update_bits(map: priv->regmap, MT6358_AFE_UL_SRC_CON0_L, |
1859 | mask: 0x0003, val: 0x0000); |
1860 | |
1861 | /* disable aud_pad TX fifos */ |
1862 | mt6358_mtkaif_tx_disable(priv); |
1863 | |
1864 | /* DMIC disable */ |
1865 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON8, val: 0x0000); |
1866 | |
1867 | /* mic bias */ |
1868 | /* MISBIAS0 = 1P7V */ |
1869 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON9, val: 0x0001); |
1870 | |
1871 | /* RG_BANDGAPGEN=1'b0 */ |
1872 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON10, |
1873 | mask: 0x1 << 12, val: 0x0); |
1874 | |
1875 | /* MICBIA0 disable */ |
1876 | regmap_write(map: priv->regmap, MT6358_AUDENC_ANA_CON9, val: 0x0000); |
1877 | } |
1878 | |
1879 | static void mt6358_restore_pga(struct mt6358_priv *priv) |
1880 | { |
1881 | unsigned int gain_l, gain_r; |
1882 | |
1883 | gain_l = priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP1]; |
1884 | gain_r = priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP2]; |
1885 | |
1886 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON0, |
1887 | RG_AUDPREAMPLGAIN_MASK_SFT, |
1888 | val: gain_l << RG_AUDPREAMPLGAIN_SFT); |
1889 | regmap_update_bits(map: priv->regmap, MT6358_AUDENC_ANA_CON1, |
1890 | RG_AUDPREAMPRGAIN_MASK_SFT, |
1891 | val: gain_r << RG_AUDPREAMPRGAIN_SFT); |
1892 | } |
1893 | |
1894 | static int mt_mic_type_event(struct snd_soc_dapm_widget *w, |
1895 | struct snd_kcontrol *kcontrol, |
1896 | int event) |
1897 | { |
1898 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1899 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1900 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1901 | |
1902 | dev_dbg(priv->dev, "%s(), event 0x%x, mux %u\n" , |
1903 | __func__, event, mux); |
1904 | |
1905 | switch (event) { |
1906 | case SND_SOC_DAPM_WILL_PMU: |
1907 | priv->mux_select[MUX_MIC_TYPE] = mux; |
1908 | break; |
1909 | case SND_SOC_DAPM_PRE_PMU: |
1910 | switch (mux) { |
1911 | case MIC_TYPE_MUX_DMIC: |
1912 | mt6358_dmic_enable(priv); |
1913 | break; |
1914 | default: |
1915 | mt6358_amic_enable(priv); |
1916 | break; |
1917 | } |
1918 | mt6358_restore_pga(priv); |
1919 | |
1920 | break; |
1921 | case SND_SOC_DAPM_POST_PMD: |
1922 | switch (priv->mux_select[MUX_MIC_TYPE]) { |
1923 | case MIC_TYPE_MUX_DMIC: |
1924 | mt6358_dmic_disable(priv); |
1925 | break; |
1926 | default: |
1927 | mt6358_amic_disable(priv); |
1928 | break; |
1929 | } |
1930 | |
1931 | priv->mux_select[MUX_MIC_TYPE] = mux; |
1932 | break; |
1933 | default: |
1934 | break; |
1935 | } |
1936 | |
1937 | return 0; |
1938 | } |
1939 | |
1940 | static int mt_adc_l_event(struct snd_soc_dapm_widget *w, |
1941 | struct snd_kcontrol *kcontrol, |
1942 | int event) |
1943 | { |
1944 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1945 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1946 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1947 | |
1948 | dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n" , |
1949 | __func__, event, mux); |
1950 | |
1951 | priv->mux_select[MUX_ADC_L] = mux; |
1952 | |
1953 | return 0; |
1954 | } |
1955 | |
1956 | static int mt_adc_r_event(struct snd_soc_dapm_widget *w, |
1957 | struct snd_kcontrol *kcontrol, |
1958 | int event) |
1959 | { |
1960 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1961 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1962 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1963 | |
1964 | dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n" , |
1965 | __func__, event, mux); |
1966 | |
1967 | priv->mux_select[MUX_ADC_R] = mux; |
1968 | |
1969 | return 0; |
1970 | } |
1971 | |
1972 | static int mt_pga_left_event(struct snd_soc_dapm_widget *w, |
1973 | struct snd_kcontrol *kcontrol, |
1974 | int event) |
1975 | { |
1976 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1977 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1978 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1979 | |
1980 | dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n" , |
1981 | __func__, event, mux); |
1982 | |
1983 | priv->mux_select[MUX_PGA_L] = mux; |
1984 | |
1985 | return 0; |
1986 | } |
1987 | |
1988 | static int mt_pga_right_event(struct snd_soc_dapm_widget *w, |
1989 | struct snd_kcontrol *kcontrol, |
1990 | int event) |
1991 | { |
1992 | struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm: w->dapm); |
1993 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
1994 | unsigned int mux = dapm_kcontrol_get_value(kcontrol: w->kcontrols[0]); |
1995 | |
1996 | dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n" , |
1997 | __func__, event, mux); |
1998 | |
1999 | priv->mux_select[MUX_PGA_R] = mux; |
2000 | |
2001 | return 0; |
2002 | } |
2003 | |
2004 | static int mt_delay_250_event(struct snd_soc_dapm_widget *w, |
2005 | struct snd_kcontrol *kcontrol, |
2006 | int event) |
2007 | { |
2008 | switch (event) { |
2009 | case SND_SOC_DAPM_POST_PMU: |
2010 | usleep_range(min: 250, max: 270); |
2011 | break; |
2012 | case SND_SOC_DAPM_PRE_PMD: |
2013 | usleep_range(min: 250, max: 270); |
2014 | break; |
2015 | default: |
2016 | break; |
2017 | } |
2018 | |
2019 | return 0; |
2020 | } |
2021 | |
2022 | /* DAPM Widgets */ |
2023 | static const struct snd_soc_dapm_widget mt6358_dapm_widgets[] = { |
2024 | /* Global Supply*/ |
2025 | SND_SOC_DAPM_SUPPLY_S("CLK_BUF" , SUPPLY_SEQ_CLK_BUF, |
2026 | MT6358_DCXO_CW14, |
2027 | RG_XO_AUDIO_EN_M_SFT, 0, NULL, 0), |
2028 | SND_SOC_DAPM_SUPPLY_S("AUDGLB" , SUPPLY_SEQ_AUD_GLB, |
2029 | MT6358_AUDDEC_ANA_CON13, |
2030 | RG_AUDGLB_PWRDN_VA28_SFT, 1, NULL, 0), |
2031 | SND_SOC_DAPM_SUPPLY_S("CLKSQ Audio" , SUPPLY_SEQ_CLKSQ, |
2032 | MT6358_AUDENC_ANA_CON6, |
2033 | RG_CLKSQ_EN_SFT, 0, |
2034 | mt_clksq_event, |
2035 | SND_SOC_DAPM_PRE_PMU), |
2036 | SND_SOC_DAPM_SUPPLY_S("AUDNCP_CK" , SUPPLY_SEQ_TOP_CK, |
2037 | MT6358_AUD_TOP_CKPDN_CON0, |
2038 | RG_AUDNCP_CK_PDN_SFT, 1, NULL, 0), |
2039 | SND_SOC_DAPM_SUPPLY_S("ZCD13M_CK" , SUPPLY_SEQ_TOP_CK, |
2040 | MT6358_AUD_TOP_CKPDN_CON0, |
2041 | RG_ZCD13M_CK_PDN_SFT, 1, NULL, 0), |
2042 | SND_SOC_DAPM_SUPPLY_S("AUD_CK" , SUPPLY_SEQ_TOP_CK_LAST, |
2043 | MT6358_AUD_TOP_CKPDN_CON0, |
2044 | RG_AUD_CK_PDN_SFT, 1, |
2045 | mt_delay_250_event, |
2046 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
2047 | SND_SOC_DAPM_SUPPLY_S("AUDIF_CK" , SUPPLY_SEQ_TOP_CK, |
2048 | MT6358_AUD_TOP_CKPDN_CON0, |
2049 | RG_AUDIF_CK_PDN_SFT, 1, NULL, 0), |
2050 | |
2051 | /* Digital Clock */ |
2052 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_AFE_CTL" , SUPPLY_SEQ_AUD_TOP_LAST, |
2053 | MT6358_AUDIO_TOP_CON0, |
2054 | PDN_AFE_CTL_SFT, 1, |
2055 | mt_delay_250_event, |
2056 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
2057 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_DAC_CTL" , SUPPLY_SEQ_AUD_TOP, |
2058 | MT6358_AUDIO_TOP_CON0, |
2059 | PDN_DAC_CTL_SFT, 1, NULL, 0), |
2060 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_ADC_CTL" , SUPPLY_SEQ_AUD_TOP, |
2061 | MT6358_AUDIO_TOP_CON0, |
2062 | PDN_ADC_CTL_SFT, 1, NULL, 0), |
2063 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_I2S_DL" , SUPPLY_SEQ_AUD_TOP, |
2064 | MT6358_AUDIO_TOP_CON0, |
2065 | PDN_I2S_DL_CTL_SFT, 1, NULL, 0), |
2066 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PWR_CLK" , SUPPLY_SEQ_AUD_TOP, |
2067 | MT6358_AUDIO_TOP_CON0, |
2068 | PWR_CLK_DIS_CTL_SFT, 1, NULL, 0), |
2069 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_AFE_TESTMODEL" , SUPPLY_SEQ_AUD_TOP, |
2070 | MT6358_AUDIO_TOP_CON0, |
2071 | PDN_AFE_TESTMODEL_CTL_SFT, 1, NULL, 0), |
2072 | SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_RESERVED" , SUPPLY_SEQ_AUD_TOP, |
2073 | MT6358_AUDIO_TOP_CON0, |
2074 | PDN_RESERVED_SFT, 1, NULL, 0), |
2075 | |
2076 | SND_SOC_DAPM_SUPPLY("DL Digital Clock" , SND_SOC_NOPM, |
2077 | 0, 0, NULL, 0), |
2078 | |
2079 | /* AFE ON */ |
2080 | SND_SOC_DAPM_SUPPLY_S("AFE_ON" , SUPPLY_SEQ_AFE, |
2081 | MT6358_AFE_UL_DL_CON0, AFE_ON_SFT, 0, |
2082 | NULL, 0), |
2083 | |
2084 | /* AIF Rx*/ |
2085 | SND_SOC_DAPM_AIF_IN_E("AIF_RX" , "AIF1 Playback" , 0, |
2086 | MT6358_AFE_DL_SRC2_CON0_L, |
2087 | DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0, |
2088 | mt_aif_in_event, |
2089 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
2090 | |
2091 | /* DL Supply */ |
2092 | SND_SOC_DAPM_SUPPLY("DL Power Supply" , SND_SOC_NOPM, |
2093 | 0, 0, NULL, 0), |
2094 | |
2095 | /* DAC */ |
2096 | SND_SOC_DAPM_MUX("DAC In Mux" , SND_SOC_NOPM, 0, 0, &dac_in_mux_control), |
2097 | |
2098 | SND_SOC_DAPM_DAC("DACL" , NULL, SND_SOC_NOPM, 0, 0), |
2099 | |
2100 | SND_SOC_DAPM_DAC("DACR" , NULL, SND_SOC_NOPM, 0, 0), |
2101 | |
2102 | /* LOL */ |
2103 | SND_SOC_DAPM_MUX("LOL Mux" , SND_SOC_NOPM, 0, 0, &lo_in_mux_control), |
2104 | |
2105 | SND_SOC_DAPM_SUPPLY("LO Stability Enh" , MT6358_AUDDEC_ANA_CON7, |
2106 | RG_LOOUTPUTSTBENH_VAUDP15_SFT, 0, NULL, 0), |
2107 | |
2108 | SND_SOC_DAPM_OUT_DRV("LOL Buffer" , MT6358_AUDDEC_ANA_CON7, |
2109 | RG_AUDLOLPWRUP_VAUDP15_SFT, 0, NULL, 0), |
2110 | |
2111 | /* Headphone */ |
2112 | SND_SOC_DAPM_MUX_E("HPL Mux" , SND_SOC_NOPM, 0, 0, |
2113 | &hpl_in_mux_control, |
2114 | mt_hp_event, |
2115 | SND_SOC_DAPM_PRE_PMU | |
2116 | SND_SOC_DAPM_PRE_PMD), |
2117 | |
2118 | SND_SOC_DAPM_MUX_E("HPR Mux" , SND_SOC_NOPM, 0, 0, |
2119 | &hpr_in_mux_control, |
2120 | mt_hp_event, |
2121 | SND_SOC_DAPM_PRE_PMU | |
2122 | SND_SOC_DAPM_PRE_PMD), |
2123 | |
2124 | /* Receiver */ |
2125 | SND_SOC_DAPM_MUX_E("RCV Mux" , SND_SOC_NOPM, 0, 0, |
2126 | &rcv_in_mux_control, |
2127 | mt_rcv_event, |
2128 | SND_SOC_DAPM_PRE_PMU | |
2129 | SND_SOC_DAPM_PRE_PMD), |
2130 | |
2131 | /* Outputs */ |
2132 | SND_SOC_DAPM_OUTPUT("Receiver" ), |
2133 | SND_SOC_DAPM_OUTPUT("Headphone L" ), |
2134 | SND_SOC_DAPM_OUTPUT("Headphone R" ), |
2135 | SND_SOC_DAPM_OUTPUT("Headphone L Ext Spk Amp" ), |
2136 | SND_SOC_DAPM_OUTPUT("Headphone R Ext Spk Amp" ), |
2137 | SND_SOC_DAPM_OUTPUT("LINEOUT L" ), |
2138 | SND_SOC_DAPM_OUTPUT("LINEOUT L HSSPK" ), |
2139 | |
2140 | /* SGEN */ |
2141 | SND_SOC_DAPM_SUPPLY("SGEN DL Enable" , MT6358_AFE_SGEN_CFG0, |
2142 | SGEN_DAC_EN_CTL_SFT, 0, NULL, 0), |
2143 | SND_SOC_DAPM_SUPPLY("SGEN MUTE" , MT6358_AFE_SGEN_CFG0, |
2144 | SGEN_MUTE_SW_CTL_SFT, 1, |
2145 | mt_sgen_event, |
2146 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
2147 | SND_SOC_DAPM_SUPPLY("SGEN DL SRC" , MT6358_AFE_DL_SRC2_CON0_L, |
2148 | DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0, NULL, 0), |
2149 | |
2150 | SND_SOC_DAPM_INPUT("SGEN DL" ), |
2151 | |
2152 | /* Uplinks */ |
2153 | SND_SOC_DAPM_AIF_OUT_E("AIF1TX" , "AIF1 Capture" , 0, |
2154 | SND_SOC_NOPM, 0, 0, |
2155 | mt_aif_out_event, |
2156 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
2157 | |
2158 | SND_SOC_DAPM_SUPPLY_S("ADC Supply" , SUPPLY_SEQ_ADC_SUPPLY, |
2159 | SND_SOC_NOPM, 0, 0, |
2160 | mt_adc_supply_event, |
2161 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
2162 | |
2163 | /* Uplinks MUX */ |
2164 | SND_SOC_DAPM_MUX("AIF Out Mux" , SND_SOC_NOPM, 0, 0, |
2165 | &aif_out_mux_control), |
2166 | |
2167 | SND_SOC_DAPM_MUX_E("Mic Type Mux" , SND_SOC_NOPM, 0, 0, |
2168 | &mic_type_mux_control, |
2169 | mt_mic_type_event, |
2170 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD | |
2171 | SND_SOC_DAPM_WILL_PMU), |
2172 | |
2173 | SND_SOC_DAPM_MUX_E("ADC L Mux" , SND_SOC_NOPM, 0, 0, |
2174 | &adc_left_mux_control, |
2175 | mt_adc_l_event, |
2176 | SND_SOC_DAPM_WILL_PMU), |
2177 | SND_SOC_DAPM_MUX_E("ADC R Mux" , SND_SOC_NOPM, 0, 0, |
2178 | &adc_right_mux_control, |
2179 | mt_adc_r_event, |
2180 | SND_SOC_DAPM_WILL_PMU), |
2181 | |
2182 | SND_SOC_DAPM_ADC("ADC L" , NULL, SND_SOC_NOPM, 0, 0), |
2183 | SND_SOC_DAPM_ADC("ADC R" , NULL, SND_SOC_NOPM, 0, 0), |
2184 | |
2185 | SND_SOC_DAPM_MUX_E("PGA L Mux" , SND_SOC_NOPM, 0, 0, |
2186 | &pga_left_mux_control, |
2187 | mt_pga_left_event, |
2188 | SND_SOC_DAPM_WILL_PMU), |
2189 | SND_SOC_DAPM_MUX_E("PGA R Mux" , SND_SOC_NOPM, 0, 0, |
2190 | &pga_right_mux_control, |
2191 | mt_pga_right_event, |
2192 | SND_SOC_DAPM_WILL_PMU), |
2193 | |
2194 | SND_SOC_DAPM_PGA("PGA L" , SND_SOC_NOPM, 0, 0, NULL, 0), |
2195 | SND_SOC_DAPM_PGA("PGA R" , SND_SOC_NOPM, 0, 0, NULL, 0), |
2196 | |
2197 | /* UL input */ |
2198 | SND_SOC_DAPM_INPUT("AIN0" ), |
2199 | SND_SOC_DAPM_INPUT("AIN1" ), |
2200 | SND_SOC_DAPM_INPUT("AIN2" ), |
2201 | }; |
2202 | |
2203 | static const struct snd_soc_dapm_route mt6358_dapm_routes[] = { |
2204 | /* Capture */ |
2205 | {"AIF1TX" , NULL, "AIF Out Mux" }, |
2206 | {"AIF1TX" , NULL, "CLK_BUF" }, |
2207 | {"AIF1TX" , NULL, "AUDGLB" }, |
2208 | {"AIF1TX" , NULL, "CLKSQ Audio" }, |
2209 | |
2210 | {"AIF1TX" , NULL, "AUD_CK" }, |
2211 | {"AIF1TX" , NULL, "AUDIF_CK" }, |
2212 | |
2213 | {"AIF1TX" , NULL, "AUDIO_TOP_AFE_CTL" }, |
2214 | {"AIF1TX" , NULL, "AUDIO_TOP_ADC_CTL" }, |
2215 | {"AIF1TX" , NULL, "AUDIO_TOP_PWR_CLK" }, |
2216 | {"AIF1TX" , NULL, "AUDIO_TOP_PDN_RESERVED" }, |
2217 | {"AIF1TX" , NULL, "AUDIO_TOP_I2S_DL" }, |
2218 | |
2219 | {"AIF1TX" , NULL, "AFE_ON" }, |
2220 | |
2221 | {"AIF Out Mux" , NULL, "Mic Type Mux" }, |
2222 | |
2223 | {"Mic Type Mux" , "ACC" , "ADC L" }, |
2224 | {"Mic Type Mux" , "ACC" , "ADC R" }, |
2225 | {"Mic Type Mux" , "DCC" , "ADC L" }, |
2226 | {"Mic Type Mux" , "DCC" , "ADC R" }, |
2227 | {"Mic Type Mux" , "DCC_ECM_DIFF" , "ADC L" }, |
2228 | {"Mic Type Mux" , "DCC_ECM_DIFF" , "ADC R" }, |
2229 | {"Mic Type Mux" , "DCC_ECM_SINGLE" , "ADC L" }, |
2230 | {"Mic Type Mux" , "DCC_ECM_SINGLE" , "ADC R" }, |
2231 | {"Mic Type Mux" , "DMIC" , "AIN0" }, |
2232 | {"Mic Type Mux" , "DMIC" , "AIN2" }, |
2233 | |
2234 | {"ADC L" , NULL, "ADC L Mux" }, |
2235 | {"ADC L" , NULL, "ADC Supply" }, |
2236 | {"ADC R" , NULL, "ADC R Mux" }, |
2237 | {"ADC R" , NULL, "ADC Supply" }, |
2238 | |
2239 | {"ADC L Mux" , "Left Preamplifier" , "PGA L" }, |
2240 | |
2241 | {"ADC R Mux" , "Right Preamplifier" , "PGA R" }, |
2242 | |
2243 | {"PGA L" , NULL, "PGA L Mux" }, |
2244 | {"PGA R" , NULL, "PGA R Mux" }, |
2245 | |
2246 | {"PGA L Mux" , "AIN0" , "AIN0" }, |
2247 | {"PGA L Mux" , "AIN1" , "AIN1" }, |
2248 | {"PGA L Mux" , "AIN2" , "AIN2" }, |
2249 | |
2250 | {"PGA R Mux" , "AIN0" , "AIN0" }, |
2251 | {"PGA R Mux" , "AIN1" , "AIN1" }, |
2252 | {"PGA R Mux" , "AIN2" , "AIN2" }, |
2253 | |
2254 | /* DL Supply */ |
2255 | {"DL Power Supply" , NULL, "CLK_BUF" }, |
2256 | {"DL Power Supply" , NULL, "AUDGLB" }, |
2257 | {"DL Power Supply" , NULL, "CLKSQ Audio" }, |
2258 | |
2259 | {"DL Power Supply" , NULL, "AUDNCP_CK" }, |
2260 | {"DL Power Supply" , NULL, "ZCD13M_CK" }, |
2261 | {"DL Power Supply" , NULL, "AUD_CK" }, |
2262 | {"DL Power Supply" , NULL, "AUDIF_CK" }, |
2263 | |
2264 | /* DL Digital Supply */ |
2265 | {"DL Digital Clock" , NULL, "AUDIO_TOP_AFE_CTL" }, |
2266 | {"DL Digital Clock" , NULL, "AUDIO_TOP_DAC_CTL" }, |
2267 | {"DL Digital Clock" , NULL, "AUDIO_TOP_PWR_CLK" }, |
2268 | |
2269 | {"DL Digital Clock" , NULL, "AFE_ON" }, |
2270 | |
2271 | {"AIF_RX" , NULL, "DL Digital Clock" }, |
2272 | |
2273 | /* DL Path */ |
2274 | {"DAC In Mux" , "Normal Path" , "AIF_RX" }, |
2275 | |
2276 | {"DAC In Mux" , "Sgen" , "SGEN DL" }, |
2277 | {"SGEN DL" , NULL, "SGEN DL SRC" }, |
2278 | {"SGEN DL" , NULL, "SGEN MUTE" }, |
2279 | {"SGEN DL" , NULL, "SGEN DL Enable" }, |
2280 | {"SGEN DL" , NULL, "DL Digital Clock" }, |
2281 | {"SGEN DL" , NULL, "AUDIO_TOP_PDN_AFE_TESTMODEL" }, |
2282 | |
2283 | {"DACL" , NULL, "DAC In Mux" }, |
2284 | {"DACL" , NULL, "DL Power Supply" }, |
2285 | |
2286 | {"DACR" , NULL, "DAC In Mux" }, |
2287 | {"DACR" , NULL, "DL Power Supply" }, |
2288 | |
2289 | /* Lineout Path */ |
2290 | {"LOL Mux" , "Playback" , "DACL" }, |
2291 | |
2292 | {"LOL Buffer" , NULL, "LOL Mux" }, |
2293 | {"LOL Buffer" , NULL, "LO Stability Enh" }, |
2294 | |
2295 | {"LINEOUT L" , NULL, "LOL Buffer" }, |
2296 | |
2297 | /* Headphone Path */ |
2298 | {"HPL Mux" , "Audio Playback" , "DACL" }, |
2299 | {"HPR Mux" , "Audio Playback" , "DACR" }, |
2300 | {"HPL Mux" , "HP Impedance" , "DACL" }, |
2301 | {"HPR Mux" , "HP Impedance" , "DACR" }, |
2302 | {"HPL Mux" , "LoudSPK Playback" , "DACL" }, |
2303 | {"HPR Mux" , "LoudSPK Playback" , "DACR" }, |
2304 | |
2305 | {"Headphone L" , NULL, "HPL Mux" }, |
2306 | {"Headphone R" , NULL, "HPR Mux" }, |
2307 | {"Headphone L Ext Spk Amp" , NULL, "HPL Mux" }, |
2308 | {"Headphone R Ext Spk Amp" , NULL, "HPR Mux" }, |
2309 | {"LINEOUT L HSSPK" , NULL, "HPL Mux" }, |
2310 | |
2311 | /* Receiver Path */ |
2312 | {"RCV Mux" , "Voice Playback" , "DACL" }, |
2313 | {"Receiver" , NULL, "RCV Mux" }, |
2314 | }; |
2315 | |
2316 | static int mt6358_codec_dai_hw_params(struct snd_pcm_substream *substream, |
2317 | struct snd_pcm_hw_params *params, |
2318 | struct snd_soc_dai *dai) |
2319 | { |
2320 | struct snd_soc_component *cmpnt = dai->component; |
2321 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
2322 | unsigned int rate = params_rate(p: params); |
2323 | |
2324 | dev_info(priv->dev, "%s(), substream->stream %d, rate %d, number %d\n" , |
2325 | __func__, |
2326 | substream->stream, |
2327 | rate, |
2328 | substream->number); |
2329 | |
2330 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
2331 | priv->dl_rate = rate; |
2332 | else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
2333 | priv->ul_rate = rate; |
2334 | |
2335 | return 0; |
2336 | } |
2337 | |
2338 | static const struct snd_soc_dai_ops mt6358_codec_dai_ops = { |
2339 | .hw_params = mt6358_codec_dai_hw_params, |
2340 | }; |
2341 | |
2342 | #define MT6358_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE |\ |
2343 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE |\ |
2344 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) |
2345 | |
2346 | static struct snd_soc_dai_driver mt6358_dai_driver[] = { |
2347 | { |
2348 | .name = "mt6358-snd-codec-aif1" , |
2349 | .playback = { |
2350 | .stream_name = "AIF1 Playback" , |
2351 | .channels_min = 1, |
2352 | .channels_max = 2, |
2353 | .rates = SNDRV_PCM_RATE_8000_48000 | |
2354 | SNDRV_PCM_RATE_96000 | |
2355 | SNDRV_PCM_RATE_192000, |
2356 | .formats = MT6358_FORMATS, |
2357 | }, |
2358 | .capture = { |
2359 | .stream_name = "AIF1 Capture" , |
2360 | .channels_min = 1, |
2361 | .channels_max = 2, |
2362 | .rates = SNDRV_PCM_RATE_8000 | |
2363 | SNDRV_PCM_RATE_16000 | |
2364 | SNDRV_PCM_RATE_32000 | |
2365 | SNDRV_PCM_RATE_48000, |
2366 | .formats = MT6358_FORMATS, |
2367 | }, |
2368 | .ops = &mt6358_codec_dai_ops, |
2369 | }, |
2370 | }; |
2371 | |
2372 | static void mt6358_codec_init_reg(struct mt6358_priv *priv) |
2373 | { |
2374 | /* Disable HeadphoneL/HeadphoneR short circuit protection */ |
2375 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
2376 | RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, |
2377 | val: 0x1 << RG_AUDHPLSCDISABLE_VAUDP15_SFT); |
2378 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON0, |
2379 | RG_AUDHPRSCDISABLE_VAUDP15_MASK_SFT, |
2380 | val: 0x1 << RG_AUDHPRSCDISABLE_VAUDP15_SFT); |
2381 | /* Disable voice short circuit protection */ |
2382 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON6, |
2383 | RG_AUDHSSCDISABLE_VAUDP15_MASK_SFT, |
2384 | val: 0x1 << RG_AUDHSSCDISABLE_VAUDP15_SFT); |
2385 | /* disable LO buffer left short circuit protection */ |
2386 | regmap_update_bits(map: priv->regmap, MT6358_AUDDEC_ANA_CON7, |
2387 | RG_AUDLOLSCDISABLE_VAUDP15_MASK_SFT, |
2388 | val: 0x1 << RG_AUDLOLSCDISABLE_VAUDP15_SFT); |
2389 | |
2390 | /* accdet s/w enable */ |
2391 | regmap_update_bits(map: priv->regmap, MT6358_ACCDET_CON13, |
2392 | mask: 0xFFFF, val: 0x700E); |
2393 | |
2394 | /* gpio miso driving set to 4mA */ |
2395 | regmap_write(map: priv->regmap, MT6358_DRV_CON3, val: 0x8888); |
2396 | |
2397 | /* set gpio */ |
2398 | playback_gpio_reset(priv); |
2399 | capture_gpio_reset(priv); |
2400 | } |
2401 | |
2402 | static int mt6358_codec_probe(struct snd_soc_component *cmpnt) |
2403 | { |
2404 | struct mt6358_priv *priv = snd_soc_component_get_drvdata(c: cmpnt); |
2405 | int ret; |
2406 | |
2407 | snd_soc_component_init_regmap(component: cmpnt, regmap: priv->regmap); |
2408 | |
2409 | mt6358_codec_init_reg(priv); |
2410 | |
2411 | priv->avdd_reg = devm_regulator_get(dev: priv->dev, id: "Avdd" ); |
2412 | if (IS_ERR(ptr: priv->avdd_reg)) { |
2413 | dev_err(priv->dev, "%s() have no Avdd supply" , __func__); |
2414 | return PTR_ERR(ptr: priv->avdd_reg); |
2415 | } |
2416 | |
2417 | ret = regulator_enable(regulator: priv->avdd_reg); |
2418 | if (ret) |
2419 | return ret; |
2420 | |
2421 | return 0; |
2422 | } |
2423 | |
2424 | static const struct snd_soc_component_driver mt6358_soc_component_driver = { |
2425 | .probe = mt6358_codec_probe, |
2426 | .controls = mt6358_snd_controls, |
2427 | .num_controls = ARRAY_SIZE(mt6358_snd_controls), |
2428 | .dapm_widgets = mt6358_dapm_widgets, |
2429 | .num_dapm_widgets = ARRAY_SIZE(mt6358_dapm_widgets), |
2430 | .dapm_routes = mt6358_dapm_routes, |
2431 | .num_dapm_routes = ARRAY_SIZE(mt6358_dapm_routes), |
2432 | .endianness = 1, |
2433 | }; |
2434 | |
2435 | static void mt6358_parse_dt(struct mt6358_priv *priv) |
2436 | { |
2437 | int ret; |
2438 | struct device *dev = priv->dev; |
2439 | |
2440 | ret = of_property_read_u32(np: dev->of_node, propname: "mediatek,dmic-mode" , |
2441 | out_value: &priv->dmic_one_wire_mode); |
2442 | if (ret) { |
2443 | dev_warn(priv->dev, "%s() failed to read dmic-mode\n" , |
2444 | __func__); |
2445 | priv->dmic_one_wire_mode = 0; |
2446 | } |
2447 | } |
2448 | |
2449 | static int mt6358_platform_driver_probe(struct platform_device *pdev) |
2450 | { |
2451 | struct mt6358_priv *priv; |
2452 | struct mt6397_chip *mt6397 = dev_get_drvdata(dev: pdev->dev.parent); |
2453 | |
2454 | priv = devm_kzalloc(dev: &pdev->dev, |
2455 | size: sizeof(struct mt6358_priv), |
2456 | GFP_KERNEL); |
2457 | if (!priv) |
2458 | return -ENOMEM; |
2459 | |
2460 | dev_set_drvdata(dev: &pdev->dev, data: priv); |
2461 | |
2462 | priv->dev = &pdev->dev; |
2463 | |
2464 | priv->regmap = mt6397->regmap; |
2465 | if (IS_ERR(ptr: priv->regmap)) |
2466 | return PTR_ERR(ptr: priv->regmap); |
2467 | |
2468 | mt6358_parse_dt(priv); |
2469 | |
2470 | dev_info(priv->dev, "%s(), dev name %s\n" , |
2471 | __func__, dev_name(&pdev->dev)); |
2472 | |
2473 | return devm_snd_soc_register_component(dev: &pdev->dev, |
2474 | component_driver: &mt6358_soc_component_driver, |
2475 | dai_drv: mt6358_dai_driver, |
2476 | ARRAY_SIZE(mt6358_dai_driver)); |
2477 | } |
2478 | |
2479 | static const struct of_device_id mt6358_of_match[] = { |
2480 | {.compatible = "mediatek,mt6358-sound" ,}, |
2481 | {.compatible = "mediatek,mt6366-sound" ,}, |
2482 | {} |
2483 | }; |
2484 | MODULE_DEVICE_TABLE(of, mt6358_of_match); |
2485 | |
2486 | static struct platform_driver mt6358_platform_driver = { |
2487 | .driver = { |
2488 | .name = "mt6358-sound" , |
2489 | .of_match_table = mt6358_of_match, |
2490 | }, |
2491 | .probe = mt6358_platform_driver_probe, |
2492 | }; |
2493 | |
2494 | module_platform_driver(mt6358_platform_driver) |
2495 | |
2496 | /* Module information */ |
2497 | MODULE_DESCRIPTION("MT6358 ALSA SoC codec driver" ); |
2498 | MODULE_AUTHOR("KaiChieh Chuang <kaichieh.chuang@mediatek.com>" ); |
2499 | MODULE_LICENSE("GPL v2" ); |
2500 | |