1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // mt6359-accdet.c -- ALSA SoC mt6359 accdet driver |
4 | // |
5 | // Copyright (C) 2021 MediaTek Inc. |
6 | // Author: Argus Lin <argus.lin@mediatek.com> |
7 | // |
8 | |
9 | #include <linux/of.h> |
10 | #include <linux/input.h> |
11 | #include <linux/kthread.h> |
12 | #include <linux/io.h> |
13 | #include <linux/sched/clock.h> |
14 | #include <linux/workqueue.h> |
15 | #include <linux/timer.h> |
16 | #include <linux/delay.h> |
17 | #include <linux/module.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/init.h> |
20 | #include <linux/irqdomain.h> |
21 | #include <linux/irq.h> |
22 | #include <linux/regmap.h> |
23 | #include <sound/soc.h> |
24 | #include <sound/jack.h> |
25 | #include <linux/mfd/mt6397/core.h> |
26 | |
27 | #include "mt6359-accdet.h" |
28 | #include "mt6359.h" |
29 | |
30 | /* global variable definitions */ |
31 | #define REGISTER_VAL(x) ((x) - 1) |
32 | |
33 | /* mt6359 accdet capability */ |
34 | #define ACCDET_PMIC_EINT_IRQ BIT(0) |
35 | #define ACCDET_AP_GPIO_EINT BIT(1) |
36 | |
37 | #define ACCDET_PMIC_EINT0 BIT(2) |
38 | #define ACCDET_PMIC_EINT1 BIT(3) |
39 | #define ACCDET_PMIC_BI_EINT BIT(4) |
40 | |
41 | #define ACCDET_PMIC_GPIO_TRIG_EINT BIT(5) |
42 | #define ACCDET_PMIC_INVERTER_TRIG_EINT BIT(6) |
43 | #define ACCDET_PMIC_RSV_EINT BIT(7) |
44 | |
45 | #define ACCDET_THREE_KEY BIT(8) |
46 | #define ACCDET_FOUR_KEY BIT(9) |
47 | #define ACCDET_TRI_KEY_CDD BIT(10) |
48 | #define ACCDET_RSV_KEY BIT(11) |
49 | |
50 | #define ACCDET_ANALOG_FASTDISCHARGE BIT(12) |
51 | #define ACCDET_DIGITAL_FASTDISCHARGE BIT(13) |
52 | #define ACCDET_AD_FASTDISCHRAGE BIT(14) |
53 | |
54 | static struct platform_driver mt6359_accdet_driver; |
55 | static const struct snd_soc_component_driver mt6359_accdet_soc_driver; |
56 | |
57 | /* local function declaration */ |
58 | static void accdet_set_debounce(struct mt6359_accdet *priv, int state, |
59 | unsigned int debounce); |
60 | static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv); |
61 | static void config_digital_init_by_mode(struct mt6359_accdet *priv); |
62 | static void config_eint_init_by_mode(struct mt6359_accdet *priv); |
63 | static inline void mt6359_accdet_init(struct mt6359_accdet *priv); |
64 | static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv); |
65 | static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv); |
66 | static void mt6359_accdet_jack_report(struct mt6359_accdet *priv); |
67 | static void recover_eint_analog_setting(struct mt6359_accdet *priv); |
68 | static void recover_eint_digital_setting(struct mt6359_accdet *priv); |
69 | static void recover_eint_setting(struct mt6359_accdet *priv); |
70 | |
71 | static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv) |
72 | { |
73 | if (priv->data->eint_detect_mode == 0x3 || |
74 | priv->data->eint_detect_mode == 0x4) { |
75 | /* ESD switches off */ |
76 | regmap_update_bits(map: priv->regmap, |
77 | RG_ACCDETSPARE_ADDR, mask: 1 << 8, val: 0); |
78 | } |
79 | if (priv->data->eint_detect_mode == 0x4) { |
80 | if (priv->caps & ACCDET_PMIC_EINT0) { |
81 | /* enable RG_EINT0CONFIGACCDET */ |
82 | regmap_update_bits(map: priv->regmap, |
83 | RG_EINT0CONFIGACCDET_ADDR, |
84 | RG_EINT0CONFIGACCDET_MASK_SFT, |
85 | BIT(RG_EINT0CONFIGACCDET_SFT)); |
86 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
87 | /* enable RG_EINT1CONFIGACCDET */ |
88 | regmap_update_bits(map: priv->regmap, |
89 | RG_EINT1CONFIGACCDET_ADDR, |
90 | RG_EINT1CONFIGACCDET_MASK_SFT, |
91 | BIT(RG_EINT1CONFIGACCDET_SFT)); |
92 | } |
93 | if (priv->data->eint_use_ext_res == 0x3 || |
94 | priv->data->eint_use_ext_res == 0x4) { |
95 | /*select 500k, use internal resistor */ |
96 | regmap_update_bits(map: priv->regmap, |
97 | RG_EINT0HIRENB_ADDR, |
98 | RG_EINT0HIRENB_MASK_SFT, |
99 | BIT(RG_EINT0HIRENB_SFT)); |
100 | } |
101 | } |
102 | return 0; |
103 | } |
104 | |
105 | static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv) |
106 | { |
107 | if (priv->caps & ACCDET_PMIC_EINT0) { |
108 | /* disable inverter */ |
109 | regmap_update_bits(map: priv->regmap, |
110 | ACCDET_EINT0_INVERTER_SW_EN_ADDR, |
111 | ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, val: 0); |
112 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
113 | /* disable inverter */ |
114 | regmap_update_bits(map: priv->regmap, |
115 | ACCDET_EINT1_INVERTER_SW_EN_ADDR, |
116 | ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, val: 0); |
117 | } |
118 | |
119 | if (priv->data->eint_detect_mode == 0x4) { |
120 | if (priv->caps & ACCDET_PMIC_EINT0) { |
121 | /* set DA stable signal */ |
122 | regmap_update_bits(map: priv->regmap, |
123 | ACCDET_DA_STABLE_ADDR, |
124 | ACCDET_EINT0_CEN_STABLE_MASK_SFT, val: 0); |
125 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
126 | /* set DA stable signal */ |
127 | regmap_update_bits(map: priv->regmap, |
128 | ACCDET_DA_STABLE_ADDR, |
129 | ACCDET_EINT1_CEN_STABLE_MASK_SFT, val: 0); |
130 | } |
131 | } |
132 | return 0; |
133 | } |
134 | |
135 | static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv) |
136 | { |
137 | if (priv->jd_sts == M_PLUG_IN) { |
138 | /* adjust digital setting */ |
139 | adjust_eint_digital_setting(priv); |
140 | /* adjust analog setting */ |
141 | adjust_eint_analog_setting(priv); |
142 | } else if (priv->jd_sts == M_PLUG_OUT) { |
143 | /* set debounce to 1ms */ |
144 | accdet_set_debounce(priv, state: eint_state000, |
145 | debounce: priv->data->pwm_deb->eint_debounce0); |
146 | } else { |
147 | dev_dbg(priv->dev, "should not be here %s()\n" , __func__); |
148 | } |
149 | |
150 | return 0; |
151 | } |
152 | |
153 | static void recover_eint_analog_setting(struct mt6359_accdet *priv) |
154 | { |
155 | if (priv->data->eint_detect_mode == 0x3 || |
156 | priv->data->eint_detect_mode == 0x4) { |
157 | /* ESD switches on */ |
158 | regmap_update_bits(map: priv->regmap, RG_ACCDETSPARE_ADDR, |
159 | mask: 1 << 8, val: 1 << 8); |
160 | } |
161 | if (priv->data->eint_detect_mode == 0x4) { |
162 | if (priv->caps & ACCDET_PMIC_EINT0) { |
163 | /* disable RG_EINT0CONFIGACCDET */ |
164 | regmap_update_bits(map: priv->regmap, |
165 | RG_EINT0CONFIGACCDET_ADDR, |
166 | RG_EINT0CONFIGACCDET_MASK_SFT, val: 0); |
167 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
168 | /* disable RG_EINT1CONFIGACCDET */ |
169 | regmap_update_bits(map: priv->regmap, |
170 | RG_EINT1CONFIGACCDET_ADDR, |
171 | RG_EINT1CONFIGACCDET_MASK_SFT, val: 0); |
172 | } |
173 | regmap_update_bits(map: priv->regmap, RG_EINT0HIRENB_ADDR, |
174 | RG_EINT0HIRENB_MASK_SFT, val: 0); |
175 | } |
176 | } |
177 | |
178 | static void recover_eint_digital_setting(struct mt6359_accdet *priv) |
179 | { |
180 | if (priv->caps & ACCDET_PMIC_EINT0) { |
181 | regmap_update_bits(map: priv->regmap, |
182 | ACCDET_EINT0_M_SW_EN_ADDR, |
183 | ACCDET_EINT0_M_SW_EN_MASK_SFT, val: 0); |
184 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
185 | regmap_update_bits(map: priv->regmap, |
186 | ACCDET_EINT1_M_SW_EN_ADDR, |
187 | ACCDET_EINT1_M_SW_EN_MASK_SFT, val: 0); |
188 | } |
189 | if (priv->data->eint_detect_mode == 0x4) { |
190 | /* enable eint0cen */ |
191 | if (priv->caps & ACCDET_PMIC_EINT0) { |
192 | /* enable eint0cen */ |
193 | regmap_update_bits(map: priv->regmap, |
194 | ACCDET_DA_STABLE_ADDR, |
195 | ACCDET_EINT0_CEN_STABLE_MASK_SFT, |
196 | BIT(ACCDET_EINT0_CEN_STABLE_SFT)); |
197 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
198 | /* enable eint1cen */ |
199 | regmap_update_bits(map: priv->regmap, |
200 | ACCDET_DA_STABLE_ADDR, |
201 | ACCDET_EINT1_CEN_STABLE_MASK_SFT, |
202 | BIT(ACCDET_EINT1_CEN_STABLE_SFT)); |
203 | } |
204 | } |
205 | |
206 | if (priv->data->eint_detect_mode != 0x1) { |
207 | if (priv->caps & ACCDET_PMIC_EINT0) { |
208 | /* enable inverter */ |
209 | regmap_update_bits(map: priv->regmap, |
210 | ACCDET_EINT0_INVERTER_SW_EN_ADDR, |
211 | ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, |
212 | BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT)); |
213 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
214 | /* enable inverter */ |
215 | regmap_update_bits(map: priv->regmap, |
216 | ACCDET_EINT1_INVERTER_SW_EN_ADDR, |
217 | ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, |
218 | BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT)); |
219 | } |
220 | } |
221 | } |
222 | |
223 | static void recover_eint_setting(struct mt6359_accdet *priv) |
224 | { |
225 | if (priv->jd_sts == M_PLUG_OUT) { |
226 | recover_eint_analog_setting(priv); |
227 | recover_eint_digital_setting(priv); |
228 | } |
229 | } |
230 | |
231 | static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv) |
232 | { |
233 | int ret; |
234 | unsigned int value = 0; |
235 | |
236 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
237 | ACCDET_IRQ_CLR_MASK_SFT, BIT(ACCDET_IRQ_CLR_SFT)); |
238 | usleep_range(min: 200, max: 300); |
239 | ret = regmap_read_poll_timeout(priv->regmap, |
240 | ACCDET_IRQ_ADDR, |
241 | value, |
242 | (value & ACCDET_IRQ_MASK_SFT) == 0, |
243 | 0, |
244 | 1000); |
245 | if (ret) |
246 | dev_warn(priv->dev, "%s(), ret %d\n" , __func__, ret); |
247 | /* clear accdet int, modify for fix interrupt trigger twice error */ |
248 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
249 | ACCDET_IRQ_CLR_MASK_SFT, val: 0); |
250 | regmap_update_bits(map: priv->regmap, RG_INT_STATUS_ACCDET_ADDR, |
251 | RG_INT_STATUS_ACCDET_MASK_SFT, |
252 | BIT(RG_INT_STATUS_ACCDET_SFT)); |
253 | |
254 | /* recover accdet debounce0,3 */ |
255 | accdet_set_debounce(priv, state: accdet_state000, |
256 | debounce: priv->data->pwm_deb->debounce0); |
257 | accdet_set_debounce(priv, state: accdet_state001, |
258 | debounce: priv->data->pwm_deb->debounce1); |
259 | accdet_set_debounce(priv, state: accdet_state011, |
260 | debounce: priv->data->pwm_deb->debounce3); |
261 | |
262 | priv->jack_type = 0; |
263 | priv->btn_type = 0; |
264 | priv->accdet_status = 0x3; |
265 | mt6359_accdet_jack_report(priv); |
266 | } |
267 | |
268 | static void accdet_set_debounce(struct mt6359_accdet *priv, int state, |
269 | unsigned int debounce) |
270 | { |
271 | switch (state) { |
272 | case accdet_state000: |
273 | regmap_write(map: priv->regmap, ACCDET_DEBOUNCE0_ADDR, val: debounce); |
274 | break; |
275 | case accdet_state001: |
276 | regmap_write(map: priv->regmap, ACCDET_DEBOUNCE1_ADDR, val: debounce); |
277 | break; |
278 | case accdet_state010: |
279 | regmap_write(map: priv->regmap, ACCDET_DEBOUNCE2_ADDR, val: debounce); |
280 | break; |
281 | case accdet_state011: |
282 | regmap_write(map: priv->regmap, ACCDET_DEBOUNCE3_ADDR, val: debounce); |
283 | break; |
284 | case accdet_auxadc: |
285 | regmap_write(map: priv->regmap, |
286 | ACCDET_CONNECT_AUXADC_TIME_DIG_ADDR, val: debounce); |
287 | break; |
288 | case eint_state000: |
289 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_DEBOUNCE0_ADDR, |
290 | mask: 0xF << ACCDET_EINT_DEBOUNCE0_SFT, |
291 | val: debounce << ACCDET_EINT_DEBOUNCE0_SFT); |
292 | break; |
293 | case eint_state001: |
294 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_DEBOUNCE1_ADDR, |
295 | mask: 0xF << ACCDET_EINT_DEBOUNCE1_SFT, |
296 | val: debounce << ACCDET_EINT_DEBOUNCE1_SFT); |
297 | break; |
298 | case eint_state010: |
299 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_DEBOUNCE2_ADDR, |
300 | mask: 0xF << ACCDET_EINT_DEBOUNCE2_SFT, |
301 | val: debounce << ACCDET_EINT_DEBOUNCE2_SFT); |
302 | break; |
303 | case eint_state011: |
304 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_DEBOUNCE3_ADDR, |
305 | mask: 0xF << ACCDET_EINT_DEBOUNCE3_SFT, |
306 | val: debounce << ACCDET_EINT_DEBOUNCE3_SFT); |
307 | break; |
308 | case eint_inverter_state000: |
309 | regmap_write(map: priv->regmap, ACCDET_EINT_INVERTER_DEBOUNCE_ADDR, |
310 | val: debounce); |
311 | break; |
312 | default: |
313 | dev_warn(priv->dev, "Error: %s error state (%d)\n" , __func__, |
314 | state); |
315 | break; |
316 | } |
317 | } |
318 | |
319 | static void mt6359_accdet_jack_report(struct mt6359_accdet *priv) |
320 | { |
321 | int report = 0; |
322 | |
323 | if (!priv->jack) |
324 | return; |
325 | |
326 | report = priv->jack_type | priv->btn_type; |
327 | snd_soc_jack_report(jack: priv->jack, status: report, MT6359_ACCDET_JACK_MASK); |
328 | } |
329 | |
330 | static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v) |
331 | { |
332 | if (priv->caps & ACCDET_FOUR_KEY) { |
333 | if (v < priv->data->four_key.down && |
334 | v >= priv->data->four_key.up) |
335 | priv->btn_type = SND_JACK_BTN_1; |
336 | if (v < priv->data->four_key.up && |
337 | v >= priv->data->four_key.voice) |
338 | priv->btn_type = SND_JACK_BTN_2; |
339 | if (v < priv->data->four_key.voice && |
340 | v >= priv->data->four_key.mid) |
341 | priv->btn_type = SND_JACK_BTN_3; |
342 | if (v < priv->data->four_key.mid) |
343 | priv->btn_type = SND_JACK_BTN_0; |
344 | } else { |
345 | if (v < priv->data->three_key.down && |
346 | v >= priv->data->three_key.up) |
347 | priv->btn_type = SND_JACK_BTN_1; |
348 | if (v < priv->data->three_key.up && |
349 | v >= priv->data->three_key.mid) |
350 | priv->btn_type = SND_JACK_BTN_2; |
351 | if (v < priv->data->three_key.mid) |
352 | priv->btn_type = SND_JACK_BTN_0; |
353 | } |
354 | return 0; |
355 | } |
356 | |
357 | static void is_key_pressed(struct mt6359_accdet *priv, bool pressed) |
358 | { |
359 | priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK; |
360 | |
361 | if (pressed) |
362 | check_button(priv, v: priv->cali_voltage); |
363 | } |
364 | |
365 | static inline void check_jack_btn_type(struct mt6359_accdet *priv) |
366 | { |
367 | unsigned int val = 0; |
368 | |
369 | regmap_read(map: priv->regmap, ACCDET_MEM_IN_ADDR, val: &val); |
370 | |
371 | priv->accdet_status = |
372 | (val >> ACCDET_STATE_MEM_IN_OFFSET) & ACCDET_STATE_AB_MASK; |
373 | |
374 | switch (priv->accdet_status) { |
375 | case 0: |
376 | if (priv->jack_type == SND_JACK_HEADSET) |
377 | is_key_pressed(priv, pressed: true); |
378 | else |
379 | priv->jack_type = SND_JACK_HEADPHONE; |
380 | break; |
381 | case 1: |
382 | if (priv->jack_type == SND_JACK_HEADSET) { |
383 | is_key_pressed(priv, pressed: false); |
384 | } else { |
385 | priv->jack_type = SND_JACK_HEADSET; |
386 | accdet_set_debounce(priv, state: eint_state011, debounce: 0x1); |
387 | } |
388 | break; |
389 | case 3: |
390 | default: |
391 | priv->jack_type = 0; |
392 | break; |
393 | } |
394 | } |
395 | |
396 | static void mt6359_accdet_work(struct work_struct *work) |
397 | { |
398 | struct mt6359_accdet *priv = |
399 | container_of(work, struct mt6359_accdet, accdet_work); |
400 | |
401 | mutex_lock(&priv->res_lock); |
402 | priv->pre_accdet_status = priv->accdet_status; |
403 | check_jack_btn_type(priv); |
404 | |
405 | if (priv->jack_plugged && |
406 | priv->pre_accdet_status != priv->accdet_status) |
407 | mt6359_accdet_jack_report(priv); |
408 | mutex_unlock(lock: &priv->res_lock); |
409 | } |
410 | |
411 | static void mt6359_accdet_jd_work(struct work_struct *work) |
412 | { |
413 | int ret; |
414 | unsigned int value = 0; |
415 | |
416 | struct mt6359_accdet *priv = |
417 | container_of(work, struct mt6359_accdet, jd_work); |
418 | |
419 | mutex_lock(&priv->res_lock); |
420 | if (priv->jd_sts == M_PLUG_IN) { |
421 | priv->jack_plugged = true; |
422 | |
423 | /* set and clear initial bit every eint interrupt */ |
424 | regmap_update_bits(map: priv->regmap, ACCDET_SEQ_INIT_ADDR, |
425 | ACCDET_SEQ_INIT_MASK_SFT, |
426 | BIT(ACCDET_SEQ_INIT_SFT)); |
427 | regmap_update_bits(map: priv->regmap, ACCDET_SEQ_INIT_ADDR, |
428 | ACCDET_SEQ_INIT_MASK_SFT, val: 0); |
429 | ret = regmap_read_poll_timeout(priv->regmap, |
430 | ACCDET_SEQ_INIT_ADDR, |
431 | value, |
432 | (value & ACCDET_SEQ_INIT_MASK_SFT) == 0, |
433 | 0, |
434 | 1000); |
435 | if (ret) |
436 | dev_err(priv->dev, "%s(), ret %d\n" , __func__, ret); |
437 | |
438 | /* enable ACCDET unit */ |
439 | regmap_update_bits(map: priv->regmap, ACCDET_SW_EN_ADDR, |
440 | ACCDET_SW_EN_MASK_SFT, BIT(ACCDET_SW_EN_SFT)); |
441 | } else if (priv->jd_sts == M_PLUG_OUT) { |
442 | priv->jack_plugged = false; |
443 | |
444 | accdet_set_debounce(priv, state: accdet_state011, |
445 | debounce: priv->data->pwm_deb->debounce3); |
446 | regmap_update_bits(map: priv->regmap, ACCDET_SW_EN_ADDR, |
447 | ACCDET_SW_EN_MASK_SFT, val: 0); |
448 | mt6359_accdet_recover_jd_setting(priv); |
449 | } |
450 | |
451 | if (priv->caps & ACCDET_PMIC_EINT_IRQ) |
452 | recover_eint_setting(priv); |
453 | mutex_unlock(lock: &priv->res_lock); |
454 | } |
455 | |
456 | static irqreturn_t mt6359_accdet_irq(int irq, void *data) |
457 | { |
458 | struct mt6359_accdet *priv = data; |
459 | unsigned int irq_val = 0, val = 0, value = 0; |
460 | int ret; |
461 | |
462 | mutex_lock(&priv->res_lock); |
463 | regmap_read(map: priv->regmap, ACCDET_IRQ_ADDR, val: &irq_val); |
464 | |
465 | if (irq_val & ACCDET_IRQ_MASK_SFT) { |
466 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
467 | ACCDET_IRQ_CLR_MASK_SFT, |
468 | BIT(ACCDET_IRQ_CLR_SFT)); |
469 | ret = regmap_read_poll_timeout(priv->regmap, |
470 | ACCDET_IRQ_ADDR, |
471 | value, |
472 | (value & ACCDET_IRQ_MASK_SFT) == 0, |
473 | 0, |
474 | 1000); |
475 | if (ret) { |
476 | dev_err(priv->dev, "%s(), ret %d\n" , __func__, ret); |
477 | mutex_unlock(lock: &priv->res_lock); |
478 | return IRQ_NONE; |
479 | } |
480 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
481 | ACCDET_IRQ_CLR_MASK_SFT, val: 0); |
482 | regmap_update_bits(map: priv->regmap, RG_INT_STATUS_ACCDET_ADDR, |
483 | RG_INT_STATUS_ACCDET_MASK_SFT, |
484 | BIT(RG_INT_STATUS_ACCDET_SFT)); |
485 | |
486 | queue_work(wq: priv->accdet_workqueue, work: &priv->accdet_work); |
487 | } else { |
488 | if (irq_val & ACCDET_EINT0_IRQ_MASK_SFT) { |
489 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
490 | ACCDET_EINT0_IRQ_CLR_MASK_SFT, |
491 | BIT(ACCDET_EINT0_IRQ_CLR_SFT)); |
492 | ret = regmap_read_poll_timeout(priv->regmap, |
493 | ACCDET_IRQ_ADDR, |
494 | value, |
495 | (value & ACCDET_EINT0_IRQ_MASK_SFT) == 0, |
496 | 0, |
497 | 1000); |
498 | if (ret) { |
499 | dev_err(priv->dev, "%s(), ret %d\n" , __func__, |
500 | ret); |
501 | mutex_unlock(lock: &priv->res_lock); |
502 | return IRQ_NONE; |
503 | } |
504 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
505 | ACCDET_EINT0_IRQ_CLR_MASK_SFT, val: 0); |
506 | regmap_update_bits(map: priv->regmap, |
507 | RG_INT_STATUS_ACCDET_ADDR, |
508 | RG_INT_STATUS_ACCDET_EINT0_MASK_SFT, |
509 | BIT(RG_INT_STATUS_ACCDET_EINT0_SFT)); |
510 | } |
511 | if (irq_val & ACCDET_EINT1_IRQ_MASK_SFT) { |
512 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
513 | ACCDET_EINT1_IRQ_CLR_MASK_SFT, |
514 | BIT(ACCDET_EINT1_IRQ_CLR_SFT)); |
515 | ret = regmap_read_poll_timeout(priv->regmap, |
516 | ACCDET_IRQ_ADDR, |
517 | value, |
518 | (value & ACCDET_EINT1_IRQ_MASK_SFT) == 0, |
519 | 0, |
520 | 1000); |
521 | if (ret) { |
522 | dev_err(priv->dev, "%s(), ret %d\n" , __func__, |
523 | ret); |
524 | mutex_unlock(lock: &priv->res_lock); |
525 | return IRQ_NONE; |
526 | } |
527 | regmap_update_bits(map: priv->regmap, ACCDET_IRQ_ADDR, |
528 | ACCDET_EINT1_IRQ_CLR_MASK_SFT, val: 0); |
529 | regmap_update_bits(map: priv->regmap, |
530 | RG_INT_STATUS_ACCDET_ADDR, |
531 | RG_INT_STATUS_ACCDET_EINT1_MASK_SFT, |
532 | BIT(RG_INT_STATUS_ACCDET_EINT1_SFT)); |
533 | } |
534 | /* get jack detection status */ |
535 | regmap_read(map: priv->regmap, ACCDET_EINT0_MEM_IN_ADDR, val: &val); |
536 | priv->jd_sts = ((val >> ACCDET_EINT0_MEM_IN_SFT) & |
537 | ACCDET_EINT0_MEM_IN_MASK); |
538 | /* adjust eint digital/analog setting */ |
539 | mt6359_accdet_jd_setting(priv); |
540 | |
541 | queue_work(wq: priv->jd_workqueue, work: &priv->jd_work); |
542 | } |
543 | mutex_unlock(lock: &priv->res_lock); |
544 | |
545 | return IRQ_HANDLED; |
546 | } |
547 | |
548 | static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv) |
549 | { |
550 | int ret; |
551 | struct device *dev = priv->dev; |
552 | struct device_node *node = NULL; |
553 | int pwm_deb[15] = {0}; |
554 | unsigned int tmp = 0; |
555 | |
556 | node = of_get_child_by_name(node: dev->parent->of_node, name: "accdet" ); |
557 | if (!node) |
558 | return -EINVAL; |
559 | |
560 | ret = of_property_read_u32(np: node, propname: "mediatek,mic-vol" , |
561 | out_value: &priv->data->mic_vol); |
562 | if (ret) |
563 | priv->data->mic_vol = 8; |
564 | |
565 | ret = of_property_read_u32(np: node, propname: "mediatek,plugout-debounce" , |
566 | out_value: &priv->data->plugout_deb); |
567 | if (ret) |
568 | priv->data->plugout_deb = 1; |
569 | |
570 | ret = of_property_read_u32(np: node, propname: "mediatek,mic-mode" , |
571 | out_value: &priv->data->mic_mode); |
572 | if (ret) |
573 | priv->data->mic_mode = 2; |
574 | |
575 | ret = of_property_read_u32_array(np: node, propname: "mediatek,pwm-deb-setting" , |
576 | out_values: pwm_deb, ARRAY_SIZE(pwm_deb)); |
577 | /* debounce8(auxadc debounce) is default, needn't get from dts */ |
578 | if (!ret) |
579 | memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb)); |
580 | |
581 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-level-pol" , |
582 | out_value: &priv->data->eint_pol); |
583 | if (ret) |
584 | priv->data->eint_pol = 8; |
585 | |
586 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-use-ap" , out_value: &tmp); |
587 | if (ret) |
588 | tmp = 0; |
589 | if (tmp == 0) |
590 | priv->caps |= ACCDET_PMIC_EINT_IRQ; |
591 | else if (tmp == 1) |
592 | priv->caps |= ACCDET_AP_GPIO_EINT; |
593 | |
594 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-detect-mode" , |
595 | out_value: &priv->data->eint_detect_mode); |
596 | if (ret) { |
597 | /* eint detection mode equals to EINT HW Mode */ |
598 | priv->data->eint_detect_mode = 0x4; |
599 | } |
600 | |
601 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-num" , out_value: &tmp); |
602 | if (ret) |
603 | tmp = 0; |
604 | if (tmp == 0) |
605 | priv->caps |= ACCDET_PMIC_EINT0; |
606 | else if (tmp == 1) |
607 | priv->caps |= ACCDET_PMIC_EINT1; |
608 | else if (tmp == 2) |
609 | priv->caps |= ACCDET_PMIC_BI_EINT; |
610 | |
611 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-trig-mode" , |
612 | out_value: &tmp); |
613 | if (ret) |
614 | tmp = 0; |
615 | if (tmp == 0) |
616 | priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT; |
617 | else if (tmp == 1) |
618 | priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT; |
619 | |
620 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-use-ext-res" , |
621 | out_value: &priv->data->eint_use_ext_res); |
622 | if (ret) { |
623 | /* eint use internal resister */ |
624 | priv->data->eint_use_ext_res = 0x0; |
625 | } |
626 | |
627 | ret = of_property_read_u32(np: node, propname: "mediatek,eint-comp-vth" , |
628 | out_value: &priv->data->eint_comp_vth); |
629 | if (ret) |
630 | priv->data->eint_comp_vth = 0x0; |
631 | |
632 | ret = of_property_read_u32(np: node, propname: "mediatek,key-mode" , out_value: &tmp); |
633 | if (ret) |
634 | tmp = 0; |
635 | if (tmp == 0) { |
636 | int three_key[4]; |
637 | |
638 | priv->caps |= ACCDET_THREE_KEY; |
639 | ret = of_property_read_u32_array(np: node, |
640 | propname: "mediatek,three-key-thr" , |
641 | out_values: three_key, |
642 | ARRAY_SIZE(three_key)); |
643 | if (!ret) |
644 | memcpy(&priv->data->three_key, three_key + 1, |
645 | sizeof(struct three_key_threshold)); |
646 | } else if (tmp == 1) { |
647 | int four_key[5]; |
648 | |
649 | priv->caps |= ACCDET_FOUR_KEY; |
650 | ret = of_property_read_u32_array(np: node, |
651 | propname: "mediatek,four-key-thr" , |
652 | out_values: four_key, |
653 | ARRAY_SIZE(four_key)); |
654 | if (!ret) { |
655 | memcpy(&priv->data->four_key, four_key + 1, |
656 | sizeof(struct four_key_threshold)); |
657 | } else { |
658 | dev_warn(priv->dev, |
659 | "accdet no 4-key-thrsh dts, use efuse\n" ); |
660 | } |
661 | } else if (tmp == 2) { |
662 | int three_key[4]; |
663 | |
664 | priv->caps |= ACCDET_TRI_KEY_CDD; |
665 | ret = of_property_read_u32_array(np: node, |
666 | propname: "mediatek,tri-key-cdd-thr" , |
667 | out_values: three_key, |
668 | ARRAY_SIZE(three_key)); |
669 | if (!ret) |
670 | memcpy(&priv->data->three_key, three_key + 1, |
671 | sizeof(struct three_key_threshold)); |
672 | } |
673 | |
674 | of_node_put(node); |
675 | dev_warn(priv->dev, "accdet caps=%x\n" , priv->caps); |
676 | |
677 | return 0; |
678 | } |
679 | |
680 | static void config_digital_init_by_mode(struct mt6359_accdet *priv) |
681 | { |
682 | /* enable eint cmpmem pwm */ |
683 | regmap_write(map: priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR, |
684 | val: (priv->data->pwm_deb->eint_pwm_width << 4 | |
685 | priv->data->pwm_deb->eint_pwm_thresh)); |
686 | /* DA signal stable */ |
687 | if (priv->caps & ACCDET_PMIC_EINT0) { |
688 | regmap_write(map: priv->regmap, ACCDET_DA_STABLE_ADDR, |
689 | ACCDET_EINT0_STABLE_VAL); |
690 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
691 | regmap_write(map: priv->regmap, ACCDET_DA_STABLE_ADDR, |
692 | ACCDET_EINT1_STABLE_VAL); |
693 | } |
694 | /* after receive n+1 number, interrupt issued. */ |
695 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR, |
696 | ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT, |
697 | BIT(ACCDET_EINT_M_PLUG_IN_NUM_SFT)); |
698 | /* setting HW mode, enable digital fast discharge |
699 | * if use EINT0 & EINT1 detection, please modify |
700 | * ACCDET_HWMODE_EN_ADDR[2:1] |
701 | */ |
702 | regmap_write(map: priv->regmap, ACCDET_HWMODE_EN_ADDR, val: 0x100); |
703 | |
704 | regmap_update_bits(map: priv->regmap, ACCDET_EINT_M_DETECT_EN_ADDR, |
705 | ACCDET_EINT_M_DETECT_EN_MASK_SFT, val: 0); |
706 | |
707 | /* enable PWM */ |
708 | regmap_write(map: priv->regmap, ACCDET_CMP_PWM_EN_ADDR, val: 0x67); |
709 | /* enable inverter detection */ |
710 | if (priv->data->eint_detect_mode == 0x1) { |
711 | /* disable inverter detection */ |
712 | if (priv->caps & ACCDET_PMIC_EINT0) { |
713 | regmap_update_bits(map: priv->regmap, |
714 | ACCDET_EINT0_INVERTER_SW_EN_ADDR, |
715 | ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, |
716 | val: 0); |
717 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
718 | regmap_update_bits(map: priv->regmap, |
719 | ACCDET_EINT1_INVERTER_SW_EN_ADDR, |
720 | ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, |
721 | val: 0); |
722 | } |
723 | } else { |
724 | if (priv->caps & ACCDET_PMIC_EINT0) { |
725 | regmap_update_bits(map: priv->regmap, |
726 | ACCDET_EINT0_INVERTER_SW_EN_ADDR, |
727 | ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, |
728 | BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT)); |
729 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
730 | regmap_update_bits(map: priv->regmap, |
731 | ACCDET_EINT1_INVERTER_SW_EN_ADDR, |
732 | ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, |
733 | BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT)); |
734 | } |
735 | } |
736 | } |
737 | |
738 | static void config_eint_init_by_mode(struct mt6359_accdet *priv) |
739 | { |
740 | unsigned int val = 0; |
741 | |
742 | if (priv->caps & ACCDET_PMIC_EINT0) { |
743 | regmap_update_bits(map: priv->regmap, RG_EINT0EN_ADDR, |
744 | RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT)); |
745 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
746 | regmap_update_bits(map: priv->regmap, RG_EINT1EN_ADDR, |
747 | RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT)); |
748 | } |
749 | /* ESD switches on */ |
750 | regmap_update_bits(map: priv->regmap, RG_ACCDETSPARE_ADDR, |
751 | mask: 1 << 8, val: 1 << 8); |
752 | /* before playback, set NCP pull low before nagative voltage */ |
753 | regmap_update_bits(map: priv->regmap, RG_NCP_PDDIS_EN_ADDR, |
754 | RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT)); |
755 | |
756 | if (priv->data->eint_detect_mode == 0x1 || |
757 | priv->data->eint_detect_mode == 0x2 || |
758 | priv->data->eint_detect_mode == 0x3) { |
759 | if (priv->data->eint_use_ext_res == 0x1) { |
760 | if (priv->caps & ACCDET_PMIC_EINT0) { |
761 | regmap_update_bits(map: priv->regmap, |
762 | RG_EINT0CONFIGACCDET_ADDR, |
763 | RG_EINT0CONFIGACCDET_MASK_SFT, |
764 | val: 0); |
765 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
766 | regmap_update_bits(map: priv->regmap, |
767 | RG_EINT1CONFIGACCDET_ADDR, |
768 | RG_EINT1CONFIGACCDET_MASK_SFT, |
769 | val: 0); |
770 | } |
771 | } else { |
772 | if (priv->caps & ACCDET_PMIC_EINT0) { |
773 | regmap_update_bits(map: priv->regmap, |
774 | RG_EINT0CONFIGACCDET_ADDR, |
775 | RG_EINT0CONFIGACCDET_MASK_SFT, |
776 | BIT(RG_EINT0CONFIGACCDET_SFT)); |
777 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
778 | regmap_update_bits(map: priv->regmap, |
779 | RG_EINT1CONFIGACCDET_ADDR, |
780 | RG_EINT1CONFIGACCDET_MASK_SFT, |
781 | BIT(RG_EINT1CONFIGACCDET_SFT)); |
782 | } |
783 | } |
784 | } |
785 | |
786 | if (priv->data->eint_detect_mode != 0x1) { |
787 | /* current detect set 0.25uA */ |
788 | regmap_update_bits(map: priv->regmap, RG_ACCDETSPARE_ADDR, |
789 | mask: 0x3 << RG_ACCDETSPARE_SFT, |
790 | val: 0x3 << RG_ACCDETSPARE_SFT); |
791 | } |
792 | regmap_write(map: priv->regmap, RG_EINTCOMPVTH_ADDR, |
793 | val: val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT); |
794 | } |
795 | |
796 | static void mt6359_accdet_init(struct mt6359_accdet *priv) |
797 | { |
798 | unsigned int reg = 0; |
799 | |
800 | regmap_update_bits(map: priv->regmap, ACCDET_SEQ_INIT_ADDR, |
801 | ACCDET_SEQ_INIT_MASK_SFT, BIT(ACCDET_SEQ_INIT_SFT)); |
802 | mdelay(2); |
803 | regmap_update_bits(map: priv->regmap, ACCDET_SEQ_INIT_ADDR, |
804 | ACCDET_SEQ_INIT_MASK_SFT, val: 0); |
805 | mdelay(1); |
806 | /* init the debounce time (debounce/32768)sec */ |
807 | accdet_set_debounce(priv, state: accdet_state000, |
808 | debounce: priv->data->pwm_deb->debounce0); |
809 | accdet_set_debounce(priv, state: accdet_state001, |
810 | debounce: priv->data->pwm_deb->debounce1); |
811 | accdet_set_debounce(priv, state: accdet_state011, |
812 | debounce: priv->data->pwm_deb->debounce3); |
813 | accdet_set_debounce(priv, state: accdet_auxadc, |
814 | debounce: priv->data->pwm_deb->debounce4); |
815 | |
816 | accdet_set_debounce(priv, state: eint_state000, |
817 | debounce: priv->data->pwm_deb->eint_debounce0); |
818 | accdet_set_debounce(priv, state: eint_state001, |
819 | debounce: priv->data->pwm_deb->eint_debounce1); |
820 | accdet_set_debounce(priv, state: eint_state011, |
821 | debounce: priv->data->pwm_deb->eint_debounce3); |
822 | accdet_set_debounce(priv, state: eint_inverter_state000, |
823 | debounce: priv->data->pwm_deb->eint_inverter_debounce); |
824 | |
825 | regmap_update_bits(map: priv->regmap, RG_ACCDET_RST_ADDR, |
826 | RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT)); |
827 | regmap_update_bits(map: priv->regmap, RG_ACCDET_RST_ADDR, |
828 | RG_ACCDET_RST_MASK_SFT, val: 0); |
829 | |
830 | /* clear high micbias1 voltage setting */ |
831 | regmap_update_bits(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
832 | mask: 0x3 << RG_AUDMICBIAS1HVEN_SFT, val: 0); |
833 | regmap_update_bits(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
834 | mask: 0x7 << RG_AUDMICBIAS1VREF_SFT, val: 0); |
835 | |
836 | /* init pwm frequency, duty & rise/falling delay */ |
837 | regmap_write(map: priv->regmap, ACCDET_PWM_WIDTH_ADDR, |
838 | REGISTER_VAL(priv->data->pwm_deb->pwm_width)); |
839 | regmap_write(map: priv->regmap, ACCDET_PWM_THRESH_ADDR, |
840 | REGISTER_VAL(priv->data->pwm_deb->pwm_thresh)); |
841 | regmap_write(map: priv->regmap, ACCDET_RISE_DELAY_ADDR, |
842 | val: (priv->data->pwm_deb->fall_delay << 15 | |
843 | priv->data->pwm_deb->rise_delay)); |
844 | |
845 | regmap_read(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, val: ®); |
846 | if (priv->data->mic_vol <= 7) { |
847 | /* micbias1 <= 2.7V */ |
848 | regmap_write(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
849 | val: reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) | |
850 | RG_AUDMICBIAS1LOWPEN_MASK_SFT); |
851 | } else if (priv->data->mic_vol == 8) { |
852 | /* micbias1 = 2.8v */ |
853 | regmap_write(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
854 | val: reg | (3 << RG_AUDMICBIAS1HVEN_SFT) | |
855 | RG_AUDMICBIAS1LOWPEN_MASK_SFT); |
856 | } else if (priv->data->mic_vol == 9) { |
857 | /* micbias1 = 2.85v */ |
858 | regmap_write(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
859 | val: reg | (1 << RG_AUDMICBIAS1HVEN_SFT) | |
860 | RG_AUDMICBIAS1LOWPEN_MASK_SFT); |
861 | } |
862 | /* mic mode setting */ |
863 | regmap_read(map: priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, val: ®); |
864 | if (priv->data->mic_mode == HEADSET_MODE_1) { |
865 | /* ACC mode*/ |
866 | regmap_write(map: priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, |
867 | val: reg | RG_ACCDET_MODE_ANA11_MODE1); |
868 | /* enable analog fast discharge */ |
869 | regmap_update_bits(map: priv->regmap, RG_ANALOGFDEN_ADDR, |
870 | RG_ANALOGFDEN_MASK_SFT, |
871 | BIT(RG_ANALOGFDEN_SFT)); |
872 | regmap_update_bits(map: priv->regmap, RG_ACCDETSPARE_ADDR, |
873 | mask: 0x3 << 11, val: 0x3 << 11); |
874 | } else if (priv->data->mic_mode == HEADSET_MODE_2) { |
875 | /* DCC mode Low cost mode without internal bias */ |
876 | regmap_write(map: priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, |
877 | val: reg | RG_ACCDET_MODE_ANA11_MODE2); |
878 | /* enable analog fast discharge */ |
879 | regmap_update_bits(map: priv->regmap, RG_ANALOGFDEN_ADDR, |
880 | mask: 0x3 << RG_ANALOGFDEN_SFT, |
881 | val: 0x3 << RG_ANALOGFDEN_SFT); |
882 | } else if (priv->data->mic_mode == HEADSET_MODE_6) { |
883 | /* DCC mode Low cost mode with internal bias, |
884 | * bit8 = 1 to use internal bias |
885 | */ |
886 | regmap_write(map: priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, |
887 | val: reg | RG_ACCDET_MODE_ANA11_MODE6); |
888 | regmap_update_bits(map: priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, |
889 | RG_AUDMICBIAS1DCSW1PEN_MASK_SFT, |
890 | BIT(RG_AUDMICBIAS1DCSW1PEN_SFT)); |
891 | /* enable analog fast discharge */ |
892 | regmap_update_bits(map: priv->regmap, RG_ANALOGFDEN_ADDR, |
893 | mask: 0x3 << RG_ANALOGFDEN_SFT, |
894 | val: 0x3 << RG_ANALOGFDEN_SFT); |
895 | } |
896 | |
897 | if (priv->caps & ACCDET_PMIC_EINT_IRQ) { |
898 | config_eint_init_by_mode(priv); |
899 | config_digital_init_by_mode(priv); |
900 | } |
901 | } |
902 | |
903 | int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, |
904 | struct snd_soc_jack *jack) |
905 | { |
906 | struct mt6359_accdet *priv = |
907 | snd_soc_component_get_drvdata(c: component); |
908 | |
909 | snd_jack_set_key(jack: jack->jack, type: SND_JACK_BTN_0, KEY_PLAYPAUSE); |
910 | snd_jack_set_key(jack: jack->jack, type: SND_JACK_BTN_1, KEY_VOLUMEDOWN); |
911 | snd_jack_set_key(jack: jack->jack, type: SND_JACK_BTN_2, KEY_VOLUMEUP); |
912 | snd_jack_set_key(jack: jack->jack, type: SND_JACK_BTN_3, KEY_VOICECOMMAND); |
913 | |
914 | priv->jack = jack; |
915 | |
916 | mt6359_accdet_jack_report(priv); |
917 | |
918 | return 0; |
919 | } |
920 | EXPORT_SYMBOL_GPL(mt6359_accdet_enable_jack_detect); |
921 | |
922 | static int mt6359_accdet_probe(struct platform_device *pdev) |
923 | { |
924 | struct mt6359_accdet *priv; |
925 | struct mt6397_chip *mt6397 = dev_get_drvdata(dev: pdev->dev.parent); |
926 | int ret; |
927 | |
928 | dev_dbg(&pdev->dev, "%s(), dev name %s\n" , |
929 | __func__, dev_name(&pdev->dev)); |
930 | |
931 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct mt6359_accdet), |
932 | GFP_KERNEL); |
933 | if (!priv) |
934 | return -ENOMEM; |
935 | |
936 | priv->data = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct dts_data), |
937 | GFP_KERNEL); |
938 | if (!priv->data) |
939 | return -ENOMEM; |
940 | |
941 | priv->data->pwm_deb = devm_kzalloc(dev: &pdev->dev, |
942 | size: sizeof(struct pwm_deb_settings), |
943 | GFP_KERNEL); |
944 | if (!priv->data->pwm_deb) |
945 | return -ENOMEM; |
946 | |
947 | priv->regmap = mt6397->regmap; |
948 | if (IS_ERR(ptr: priv->regmap)) { |
949 | ret = PTR_ERR(ptr: priv->regmap); |
950 | dev_err(&pdev->dev, "Failed to allocate register map: %d\n" , |
951 | ret); |
952 | return ret; |
953 | } |
954 | priv->dev = &pdev->dev; |
955 | |
956 | ret = mt6359_accdet_parse_dt(priv); |
957 | if (ret) { |
958 | dev_err(&pdev->dev, "Failed to parse dts\n" ); |
959 | return ret; |
960 | } |
961 | mutex_init(&priv->res_lock); |
962 | |
963 | priv->accdet_irq = platform_get_irq(pdev, 0); |
964 | if (priv->accdet_irq >= 0) { |
965 | ret = devm_request_threaded_irq(dev: &pdev->dev, irq: priv->accdet_irq, |
966 | NULL, thread_fn: mt6359_accdet_irq, |
967 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, |
968 | devname: "ACCDET_IRQ" , dev_id: priv); |
969 | if (ret) { |
970 | dev_err(&pdev->dev, |
971 | "Failed to request IRQ: (%d)\n" , ret); |
972 | return ret; |
973 | } |
974 | } |
975 | |
976 | if (priv->caps & ACCDET_PMIC_EINT0) { |
977 | priv->accdet_eint0 = platform_get_irq(pdev, 1); |
978 | if (priv->accdet_eint0 >= 0) { |
979 | ret = devm_request_threaded_irq(dev: &pdev->dev, |
980 | irq: priv->accdet_eint0, |
981 | NULL, thread_fn: mt6359_accdet_irq, |
982 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, |
983 | devname: "ACCDET_EINT0" , dev_id: priv); |
984 | if (ret) { |
985 | dev_err(&pdev->dev, |
986 | "Failed to request eint0 IRQ (%d)\n" , |
987 | ret); |
988 | return ret; |
989 | } |
990 | } |
991 | } else if (priv->caps & ACCDET_PMIC_EINT1) { |
992 | priv->accdet_eint1 = platform_get_irq(pdev, 2); |
993 | if (priv->accdet_eint1 >= 0) { |
994 | ret = devm_request_threaded_irq(dev: &pdev->dev, |
995 | irq: priv->accdet_eint1, |
996 | NULL, thread_fn: mt6359_accdet_irq, |
997 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, |
998 | devname: "ACCDET_EINT1" , dev_id: priv); |
999 | if (ret) { |
1000 | dev_err(&pdev->dev, |
1001 | "Failed to request eint1 IRQ (%d)\n" , |
1002 | ret); |
1003 | return ret; |
1004 | } |
1005 | } |
1006 | } |
1007 | |
1008 | priv->accdet_workqueue = create_singlethread_workqueue("accdet" ); |
1009 | INIT_WORK(&priv->accdet_work, mt6359_accdet_work); |
1010 | if (!priv->accdet_workqueue) { |
1011 | dev_err(&pdev->dev, "Failed to create accdet workqueue\n" ); |
1012 | ret = -1; |
1013 | goto err_accdet_wq; |
1014 | } |
1015 | |
1016 | priv->jd_workqueue = create_singlethread_workqueue("mt6359_accdet_jd" ); |
1017 | INIT_WORK(&priv->jd_work, mt6359_accdet_jd_work); |
1018 | if (!priv->jd_workqueue) { |
1019 | dev_err(&pdev->dev, "Failed to create jack detect workqueue\n" ); |
1020 | ret = -1; |
1021 | goto err_eint_wq; |
1022 | } |
1023 | |
1024 | platform_set_drvdata(pdev, data: priv); |
1025 | ret = devm_snd_soc_register_component(dev: &pdev->dev, |
1026 | component_driver: &mt6359_accdet_soc_driver, |
1027 | NULL, num_dai: 0); |
1028 | if (ret) { |
1029 | dev_err(&pdev->dev, "Failed to register component\n" ); |
1030 | return ret; |
1031 | } |
1032 | |
1033 | priv->jd_sts = M_PLUG_OUT; |
1034 | priv->jack_type = 0; |
1035 | priv->btn_type = 0; |
1036 | priv->accdet_status = 0x3; |
1037 | mt6359_accdet_init(priv); |
1038 | |
1039 | mt6359_accdet_jack_report(priv); |
1040 | |
1041 | return 0; |
1042 | |
1043 | err_eint_wq: |
1044 | destroy_workqueue(wq: priv->accdet_workqueue); |
1045 | err_accdet_wq: |
1046 | dev_err(&pdev->dev, "%s error. now exit.!\n" , __func__); |
1047 | return ret; |
1048 | } |
1049 | |
1050 | static struct platform_driver mt6359_accdet_driver = { |
1051 | .driver = { |
1052 | .name = "pmic-codec-accdet" , |
1053 | }, |
1054 | .probe = mt6359_accdet_probe, |
1055 | }; |
1056 | |
1057 | module_platform_driver(mt6359_accdet_driver) |
1058 | |
1059 | /* Module information */ |
1060 | MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver" ); |
1061 | MODULE_AUTHOR("Argus Lin <argus.lin@mediatek.com>" ); |
1062 | MODULE_LICENSE("GPL v2" ); |
1063 | |