Merge remote-tracking branches 'asoc/topic/tpa6130a2', 'asoc/topic/ux500', 'asoc...
[sfrench/cifs-2.6.git] / sound / soc / codecs / da7219-aad.c
1 /*
2  * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver
3  *
4  * Copyright (c) 2015 Dialog Semiconductor Ltd.
5  *
6  * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/clk.h>
17 #include <linux/i2c.h>
18 #include <linux/property.h>
19 #include <linux/pm_wakeirq.h>
20 #include <linux/slab.h>
21 #include <linux/delay.h>
22 #include <linux/workqueue.h>
23 #include <sound/soc.h>
24 #include <sound/jack.h>
25 #include <sound/da7219.h>
26
27 #include "da7219.h"
28 #include "da7219-aad.h"
29
30
31 /*
32  * Detection control
33  */
34
35 void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
36 {
37         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
38
39         da7219->aad->jack = jack;
40         da7219->aad->jack_inserted = false;
41
42         /* Send an initial empty report */
43         snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK);
44
45         /* Enable/Disable jack detection */
46         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
47                             DA7219_ACCDET_EN_MASK,
48                             (jack ? DA7219_ACCDET_EN_MASK : 0));
49 }
50 EXPORT_SYMBOL_GPL(da7219_aad_jack_det);
51
52 /*
53  * Button/HPTest work
54  */
55
56 static void da7219_aad_btn_det_work(struct work_struct *work)
57 {
58         struct da7219_aad_priv *da7219_aad =
59                 container_of(work, struct da7219_aad_priv, btn_det_work);
60         struct snd_soc_codec *codec = da7219_aad->codec;
61         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
62         u8 statusa, micbias_ctrl;
63         bool micbias_up = false;
64         int retries = 0;
65
66         /* Drive headphones/lineout */
67         snd_soc_update_bits(codec, DA7219_HP_L_CTRL,
68                             DA7219_HP_L_AMP_OE_MASK,
69                             DA7219_HP_L_AMP_OE_MASK);
70         snd_soc_update_bits(codec, DA7219_HP_R_CTRL,
71                             DA7219_HP_R_AMP_OE_MASK,
72                             DA7219_HP_R_AMP_OE_MASK);
73
74         /* Make sure mic bias is up */
75         snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
76         snd_soc_dapm_sync(dapm);
77
78         do {
79                 statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A);
80                 if (statusa & DA7219_MICBIAS_UP_STS_MASK)
81                         micbias_up = true;
82                 else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES)
83                         msleep(DA7219_AAD_MICBIAS_CHK_DELAY);
84         } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES));
85
86         if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES)
87                 dev_warn(codec->dev, "Mic bias status check timed out");
88
89         /*
90          * Mic bias pulse required to enable mic, must be done before enabling
91          * button detection to prevent erroneous button readings.
92          */
93         if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) {
94                 /* Pulse higher level voltage */
95                 micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL);
96                 snd_soc_update_bits(codec, DA7219_MICBIAS_CTRL,
97                                     DA7219_MICBIAS1_LEVEL_MASK,
98                                     da7219_aad->micbias_pulse_lvl);
99                 msleep(da7219_aad->micbias_pulse_time);
100                 snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_ctrl);
101
102         }
103
104         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
105                             DA7219_BUTTON_CONFIG_MASK,
106                             da7219_aad->btn_cfg);
107 }
108
109 static void da7219_aad_hptest_work(struct work_struct *work)
110 {
111         struct da7219_aad_priv *da7219_aad =
112                 container_of(work, struct da7219_aad_priv, hptest_work);
113         struct snd_soc_codec *codec = da7219_aad->codec;
114         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
115         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
116
117         u16 tonegen_freq_hptest;
118         u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8;
119         int report = 0, ret = 0;
120
121         /* Lock DAPM and any Kcontrols that are affected by this test */
122         snd_soc_dapm_mutex_lock(dapm);
123         mutex_lock(&da7219->lock);
124
125         /* Ensure MCLK is available for HP test procedure */
126         if (da7219->mclk) {
127                 ret = clk_prepare_enable(da7219->mclk);
128                 if (ret) {
129                         dev_err(codec->dev, "Failed to enable mclk - %d\n", ret);
130                         mutex_unlock(&da7219->lock);
131                         snd_soc_dapm_mutex_unlock(dapm);
132                         return;
133                 }
134         }
135
136         /*
137          * If MCLK not present, then we're using the internal oscillator and
138          * require different frequency settings to achieve the same result.
139          */
140         pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS);
141         if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)
142                 tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
143         else
144                 tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC);
145
146         /* Ensure gain ramping at fastest rate */
147         gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL);
148         snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8);
149
150         /* Bypass cache so it saves current settings */
151         regcache_cache_bypass(da7219->regmap, true);
152
153         /* Make sure Tone Generator is disabled */
154         snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0);
155
156         /* Enable HPTest block, 1KOhms check */
157         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8,
158                             DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK,
159                             DA7219_HPTEST_EN_MASK |
160                             DA7219_HPTEST_RES_SEL_1KOHMS);
161
162         /* Set gains to 0db */
163         snd_soc_write(codec, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
164         snd_soc_write(codec, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
165         snd_soc_write(codec, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB);
166         snd_soc_write(codec, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB);
167
168         /* Disable DAC filters, EQs and soft mute */
169         snd_soc_update_bits(codec, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK,
170                             0);
171         snd_soc_update_bits(codec, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK,
172                             0);
173         snd_soc_update_bits(codec, DA7219_DAC_FILTERS5,
174                             DA7219_DAC_SOFTMUTE_EN_MASK, 0);
175
176         /* Enable HP left & right paths */
177         snd_soc_update_bits(codec, DA7219_CP_CTRL, DA7219_CP_EN_MASK,
178                             DA7219_CP_EN_MASK);
179         snd_soc_update_bits(codec, DA7219_DIG_ROUTING_DAC,
180                             DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK,
181                             DA7219_DAC_L_SRC_TONEGEN |
182                             DA7219_DAC_R_SRC_TONEGEN);
183         snd_soc_update_bits(codec, DA7219_DAC_L_CTRL,
184                             DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK,
185                             DA7219_DAC_L_EN_MASK);
186         snd_soc_update_bits(codec, DA7219_DAC_R_CTRL,
187                             DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK,
188                             DA7219_DAC_R_EN_MASK);
189         snd_soc_update_bits(codec, DA7219_MIXOUT_L_SELECT,
190                             DA7219_MIXOUT_L_MIX_SELECT_MASK,
191                             DA7219_MIXOUT_L_MIX_SELECT_MASK);
192         snd_soc_update_bits(codec, DA7219_MIXOUT_R_SELECT,
193                             DA7219_MIXOUT_R_MIX_SELECT_MASK,
194                             DA7219_MIXOUT_R_MIX_SELECT_MASK);
195         snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1L,
196                             DA7219_OUTFILT_ST_1L_SRC_MASK,
197                             DA7219_DMIX_ST_SRC_OUTFILT1L);
198         snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1R,
199                             DA7219_OUTFILT_ST_1R_SRC_MASK,
200                             DA7219_DMIX_ST_SRC_OUTFILT1R);
201         snd_soc_update_bits(codec, DA7219_MIXOUT_L_CTRL,
202                             DA7219_MIXOUT_L_AMP_EN_MASK,
203                             DA7219_MIXOUT_L_AMP_EN_MASK);
204         snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL,
205                             DA7219_MIXOUT_R_AMP_EN_MASK,
206                             DA7219_MIXOUT_R_AMP_EN_MASK);
207         snd_soc_write(codec, DA7219_HP_L_CTRL,
208                       DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK);
209         snd_soc_write(codec, DA7219_HP_R_CTRL,
210                       DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
211
212         /*
213          * If we're running from the internal oscillator then give audio paths
214          * time to settle before running test.
215          */
216         if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
217                 msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
218
219         /* Configure & start Tone Generator */
220         snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK);
221         regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
222                          &tonegen_freq_hptest, sizeof(tonegen_freq_hptest));
223         snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2,
224                             DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK,
225                             DA7219_SWG_SEL_SRAMP |
226                             DA7219_TONE_GEN_GAIN_MINUS_15DB);
227         snd_soc_write(codec, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK);
228
229         msleep(DA7219_AAD_HPTEST_PERIOD);
230
231         /* Grab comparator reading */
232         accdet_cfg8 = snd_soc_read(codec, DA7219_ACCDET_CONFIG_8);
233         if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK)
234                 report |= SND_JACK_HEADPHONE;
235         else
236                 report |= SND_JACK_LINEOUT;
237
238         /* Stop tone generator */
239         snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0);
240
241         msleep(DA7219_AAD_HPTEST_PERIOD);
242
243         /* Restore original settings from cache */
244         regcache_mark_dirty(da7219->regmap);
245         regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL,
246                              DA7219_HP_R_CTRL);
247         regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL,
248                              DA7219_MIXOUT_R_CTRL);
249         regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L,
250                              DA7219_DROUTING_ST_OUTFILT_1R);
251         regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT,
252                              DA7219_MIXOUT_R_SELECT);
253         regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL,
254                              DA7219_DAC_R_CTRL);
255         regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC,
256                              DA7219_DIG_ROUTING_DAC);
257         regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL);
258         regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5,
259                              DA7219_DAC_FILTERS5);
260         regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4,
261                              DA7219_DAC_FILTERS1);
262         regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN,
263                              DA7219_HP_R_GAIN);
264         regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN,
265                              DA7219_DAC_R_GAIN);
266         regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER,
267                              DA7219_TONE_GEN_ON_PER);
268         regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
269                              DA7219_TONE_GEN_FREQ1_U);
270         regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1,
271                              DA7219_TONE_GEN_CFG2);
272
273         regcache_cache_bypass(da7219->regmap, false);
274
275         /* Disable HPTest block */
276         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8,
277                             DA7219_HPTEST_EN_MASK, 0);
278
279         /*
280          * If we're running from the internal oscillator then give audio paths
281          * time to settle before allowing headphones to be driven as required.
282          */
283         if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
284                 msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
285
286         /* Restore gain ramping rate */
287         snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl);
288
289         /* Drive Headphones/lineout */
290         snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK,
291                             DA7219_HP_L_AMP_OE_MASK);
292         snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK,
293                             DA7219_HP_R_AMP_OE_MASK);
294
295         /* Remove MCLK, if previously enabled */
296         if (da7219->mclk)
297                 clk_disable_unprepare(da7219->mclk);
298
299         mutex_unlock(&da7219->lock);
300         snd_soc_dapm_mutex_unlock(dapm);
301
302         /*
303          * Only send report if jack hasn't been removed during process,
304          * otherwise it's invalid and we drop it.
305          */
306         if (da7219_aad->jack_inserted)
307                 snd_soc_jack_report(da7219_aad->jack, report,
308                                     SND_JACK_HEADSET | SND_JACK_LINEOUT);
309 }
310
311
312 /*
313  * IRQ
314  */
315
316 static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
317 {
318         struct da7219_aad_priv *da7219_aad = data;
319         struct snd_soc_codec *codec = da7219_aad->codec;
320         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
321         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
322         u8 events[DA7219_AAD_IRQ_REG_MAX];
323         u8 statusa;
324         int i, report = 0, mask = 0;
325
326         /* Read current IRQ events */
327         regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
328                          events, DA7219_AAD_IRQ_REG_MAX);
329
330         if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B])
331                 return IRQ_NONE;
332
333         /* Read status register for jack insertion & type status */
334         statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A);
335
336         /* Clear events */
337         regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
338                           events, DA7219_AAD_IRQ_REG_MAX);
339
340         dev_dbg(codec->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n",
341                 events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
342                 statusa);
343
344         if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
345                 /* Jack Insertion */
346                 if (events[DA7219_AAD_IRQ_REG_A] &
347                     DA7219_E_JACK_INSERTED_MASK) {
348                         report |= SND_JACK_MECHANICAL;
349                         mask |= SND_JACK_MECHANICAL;
350                         da7219_aad->jack_inserted = true;
351                 }
352
353                 /* Jack type detection */
354                 if (events[DA7219_AAD_IRQ_REG_A] &
355                     DA7219_E_JACK_DETECT_COMPLETE_MASK) {
356                         /*
357                          * If 4-pole, then enable button detection, else perform
358                          * HP impedance test to determine output type to report.
359                          *
360                          * We schedule work here as the tasks themselves can
361                          * take time to complete, and in particular for hptest
362                          * we want to be able to check if the jack was removed
363                          * during the procedure as this will invalidate the
364                          * result. By doing this as work, the IRQ thread can
365                          * handle a removal, and we can check at the end of
366                          * hptest if we have a valid result or not.
367                          */
368                         if (statusa & DA7219_JACK_TYPE_STS_MASK) {
369                                 report |= SND_JACK_HEADSET;
370                                 mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT;
371                                 schedule_work(&da7219_aad->btn_det_work);
372                         } else {
373                                 schedule_work(&da7219_aad->hptest_work);
374                         }
375                 }
376
377                 /* Button support for 4-pole jack */
378                 if (statusa & DA7219_JACK_TYPE_STS_MASK) {
379                         for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
380                                 /* Button Press */
381                                 if (events[DA7219_AAD_IRQ_REG_B] &
382                                     (DA7219_E_BUTTON_A_PRESSED_MASK << i)) {
383                                         report |= SND_JACK_BTN_0 >> i;
384                                         mask |= SND_JACK_BTN_0 >> i;
385                                 }
386                         }
387                         snd_soc_jack_report(da7219_aad->jack, report, mask);
388
389                         for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
390                                 /* Button Release */
391                                 if (events[DA7219_AAD_IRQ_REG_B] &
392                                     (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) {
393                                         report &= ~(SND_JACK_BTN_0 >> i);
394                                         mask |= SND_JACK_BTN_0 >> i;
395                                 }
396                         }
397                 }
398         } else {
399                 /* Jack removal */
400                 if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) {
401                         report = 0;
402                         mask |= DA7219_AAD_REPORT_ALL_MASK;
403                         da7219_aad->jack_inserted = false;
404
405                         /* Un-drive headphones/lineout */
406                         snd_soc_update_bits(codec, DA7219_HP_R_CTRL,
407                                             DA7219_HP_R_AMP_OE_MASK, 0);
408                         snd_soc_update_bits(codec, DA7219_HP_L_CTRL,
409                                             DA7219_HP_L_AMP_OE_MASK, 0);
410
411                         /* Ensure button detection disabled */
412                         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
413                                             DA7219_BUTTON_CONFIG_MASK, 0);
414
415                         /* Disable mic bias */
416                         snd_soc_dapm_disable_pin(dapm, "Mic Bias");
417                         snd_soc_dapm_sync(dapm);
418
419                         /* Cancel any pending work */
420                         cancel_work_sync(&da7219_aad->btn_det_work);
421                         cancel_work_sync(&da7219_aad->hptest_work);
422                 }
423         }
424
425         snd_soc_jack_report(da7219_aad->jack, report, mask);
426
427         return IRQ_HANDLED;
428 }
429
430 /*
431  * DT/ACPI to pdata conversion
432  */
433
434 static enum da7219_aad_micbias_pulse_lvl
435         da7219_aad_fw_micbias_pulse_lvl(struct snd_soc_codec *codec, u32 val)
436 {
437         switch (val) {
438         case 2800:
439                 return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V;
440         case 2900:
441                 return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V;
442         default:
443                 dev_warn(codec->dev, "Invalid micbias pulse level");
444                 return DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
445         }
446 }
447
448 static enum da7219_aad_btn_cfg
449         da7219_aad_fw_btn_cfg(struct snd_soc_codec *codec, u32 val)
450 {
451         switch (val) {
452         case 2:
453                 return DA7219_AAD_BTN_CFG_2MS;
454         case 5:
455                 return DA7219_AAD_BTN_CFG_5MS;
456         case 10:
457                 return DA7219_AAD_BTN_CFG_10MS;
458         case 50:
459                 return DA7219_AAD_BTN_CFG_50MS;
460         case 100:
461                 return DA7219_AAD_BTN_CFG_100MS;
462         case 200:
463                 return DA7219_AAD_BTN_CFG_200MS;
464         case 500:
465                 return DA7219_AAD_BTN_CFG_500MS;
466         default:
467                 dev_warn(codec->dev, "Invalid button config");
468                 return DA7219_AAD_BTN_CFG_10MS;
469         }
470 }
471
472 static enum da7219_aad_mic_det_thr
473         da7219_aad_fw_mic_det_thr(struct snd_soc_codec *codec, u32 val)
474 {
475         switch (val) {
476         case 200:
477                 return DA7219_AAD_MIC_DET_THR_200_OHMS;
478         case 500:
479                 return DA7219_AAD_MIC_DET_THR_500_OHMS;
480         case 750:
481                 return DA7219_AAD_MIC_DET_THR_750_OHMS;
482         case 1000:
483                 return DA7219_AAD_MIC_DET_THR_1000_OHMS;
484         default:
485                 dev_warn(codec->dev, "Invalid mic detect threshold");
486                 return DA7219_AAD_MIC_DET_THR_500_OHMS;
487         }
488 }
489
490 static enum da7219_aad_jack_ins_deb
491         da7219_aad_fw_jack_ins_deb(struct snd_soc_codec *codec, u32 val)
492 {
493         switch (val) {
494         case 5:
495                 return DA7219_AAD_JACK_INS_DEB_5MS;
496         case 10:
497                 return DA7219_AAD_JACK_INS_DEB_10MS;
498         case 20:
499                 return DA7219_AAD_JACK_INS_DEB_20MS;
500         case 50:
501                 return DA7219_AAD_JACK_INS_DEB_50MS;
502         case 100:
503                 return DA7219_AAD_JACK_INS_DEB_100MS;
504         case 200:
505                 return DA7219_AAD_JACK_INS_DEB_200MS;
506         case 500:
507                 return DA7219_AAD_JACK_INS_DEB_500MS;
508         case 1000:
509                 return DA7219_AAD_JACK_INS_DEB_1S;
510         default:
511                 dev_warn(codec->dev, "Invalid jack insert debounce");
512                 return DA7219_AAD_JACK_INS_DEB_20MS;
513         }
514 }
515
516 static enum da7219_aad_jack_det_rate
517         da7219_aad_fw_jack_det_rate(struct snd_soc_codec *codec, const char *str)
518 {
519         if (!strcmp(str, "32ms_64ms")) {
520                 return DA7219_AAD_JACK_DET_RATE_32_64MS;
521         } else if (!strcmp(str, "64ms_128ms")) {
522                 return DA7219_AAD_JACK_DET_RATE_64_128MS;
523         } else if (!strcmp(str, "128ms_256ms")) {
524                 return DA7219_AAD_JACK_DET_RATE_128_256MS;
525         } else if (!strcmp(str, "256ms_512ms")) {
526                 return DA7219_AAD_JACK_DET_RATE_256_512MS;
527         } else {
528                 dev_warn(codec->dev, "Invalid jack detect rate");
529                 return DA7219_AAD_JACK_DET_RATE_256_512MS;
530         }
531 }
532
533 static enum da7219_aad_jack_rem_deb
534         da7219_aad_fw_jack_rem_deb(struct snd_soc_codec *codec, u32 val)
535 {
536         switch (val) {
537         case 1:
538                 return DA7219_AAD_JACK_REM_DEB_1MS;
539         case 5:
540                 return DA7219_AAD_JACK_REM_DEB_5MS;
541         case 10:
542                 return DA7219_AAD_JACK_REM_DEB_10MS;
543         case 20:
544                 return DA7219_AAD_JACK_REM_DEB_20MS;
545         default:
546                 dev_warn(codec->dev, "Invalid jack removal debounce");
547                 return DA7219_AAD_JACK_REM_DEB_1MS;
548         }
549 }
550
551 static enum da7219_aad_btn_avg
552         da7219_aad_fw_btn_avg(struct snd_soc_codec *codec, u32 val)
553 {
554         switch (val) {
555         case 1:
556                 return DA7219_AAD_BTN_AVG_1;
557         case 2:
558                 return DA7219_AAD_BTN_AVG_2;
559         case 4:
560                 return DA7219_AAD_BTN_AVG_4;
561         case 8:
562                 return DA7219_AAD_BTN_AVG_8;
563         default:
564                 dev_warn(codec->dev, "Invalid button average value");
565                 return DA7219_AAD_BTN_AVG_2;
566         }
567 }
568
569 static enum da7219_aad_adc_1bit_rpt
570         da7219_aad_fw_adc_1bit_rpt(struct snd_soc_codec *codec, u32 val)
571 {
572         switch (val) {
573         case 1:
574                 return DA7219_AAD_ADC_1BIT_RPT_1;
575         case 2:
576                 return DA7219_AAD_ADC_1BIT_RPT_2;
577         case 4:
578                 return DA7219_AAD_ADC_1BIT_RPT_4;
579         case 8:
580                 return DA7219_AAD_ADC_1BIT_RPT_8;
581         default:
582                 dev_warn(codec->dev, "Invalid ADC 1-bit repeat value");
583                 return DA7219_AAD_ADC_1BIT_RPT_1;
584         }
585 }
586
587 static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_codec *codec)
588 {
589         struct device *dev = codec->dev;
590         struct i2c_client *i2c = to_i2c_client(dev);
591         struct fwnode_handle *aad_np;
592         struct da7219_aad_pdata *aad_pdata;
593         const char *fw_str;
594         u32 fw_val32;
595
596         aad_np = device_get_named_child_node(dev, "da7219_aad");
597         if (!aad_np)
598                 return NULL;
599
600         aad_pdata = devm_kzalloc(codec->dev, sizeof(*aad_pdata), GFP_KERNEL);
601         if (!aad_pdata)
602                 return NULL;
603
604         aad_pdata->irq = i2c->irq;
605
606         if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-lvl",
607                                      &fw_val32) >= 0)
608                 aad_pdata->micbias_pulse_lvl =
609                         da7219_aad_fw_micbias_pulse_lvl(codec, fw_val32);
610         else
611                 aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
612
613         if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-time",
614                                      &fw_val32) >= 0)
615                 aad_pdata->micbias_pulse_time = fw_val32;
616
617         if (fwnode_property_read_u32(aad_np, "dlg,btn-cfg", &fw_val32) >= 0)
618                 aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(codec, fw_val32);
619         else
620                 aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS;
621
622         if (fwnode_property_read_u32(aad_np, "dlg,mic-det-thr", &fw_val32) >= 0)
623                 aad_pdata->mic_det_thr =
624                         da7219_aad_fw_mic_det_thr(codec, fw_val32);
625         else
626                 aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
627
628         if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
629                 aad_pdata->jack_ins_deb =
630                         da7219_aad_fw_jack_ins_deb(codec, fw_val32);
631         else
632                 aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS;
633
634         if (!fwnode_property_read_string(aad_np, "dlg,jack-det-rate", &fw_str))
635                 aad_pdata->jack_det_rate =
636                         da7219_aad_fw_jack_det_rate(codec, fw_str);
637         else
638                 aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS;
639
640         if (fwnode_property_read_u32(aad_np, "dlg,jack-rem-deb", &fw_val32) >= 0)
641                 aad_pdata->jack_rem_deb =
642                         da7219_aad_fw_jack_rem_deb(codec, fw_val32);
643         else
644                 aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS;
645
646         if (fwnode_property_read_u32(aad_np, "dlg,a-d-btn-thr", &fw_val32) >= 0)
647                 aad_pdata->a_d_btn_thr = (u8) fw_val32;
648         else
649                 aad_pdata->a_d_btn_thr = 0xA;
650
651         if (fwnode_property_read_u32(aad_np, "dlg,d-b-btn-thr", &fw_val32) >= 0)
652                 aad_pdata->d_b_btn_thr = (u8) fw_val32;
653         else
654                 aad_pdata->d_b_btn_thr = 0x16;
655
656         if (fwnode_property_read_u32(aad_np, "dlg,b-c-btn-thr", &fw_val32) >= 0)
657                 aad_pdata->b_c_btn_thr = (u8) fw_val32;
658         else
659                 aad_pdata->b_c_btn_thr = 0x21;
660
661         if (fwnode_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &fw_val32) >= 0)
662                 aad_pdata->c_mic_btn_thr = (u8) fw_val32;
663         else
664                 aad_pdata->c_mic_btn_thr = 0x3E;
665
666         if (fwnode_property_read_u32(aad_np, "dlg,btn-avg", &fw_val32) >= 0)
667                 aad_pdata->btn_avg = da7219_aad_fw_btn_avg(codec, fw_val32);
668         else
669                 aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2;
670
671         if (fwnode_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &fw_val32) >= 0)
672                 aad_pdata->adc_1bit_rpt =
673                         da7219_aad_fw_adc_1bit_rpt(codec, fw_val32);
674         else
675                 aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
676
677         return aad_pdata;
678 }
679
680 static void da7219_aad_handle_pdata(struct snd_soc_codec *codec)
681 {
682         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
683         struct da7219_aad_priv *da7219_aad = da7219->aad;
684         struct da7219_pdata *pdata = da7219->pdata;
685
686         if ((pdata) && (pdata->aad_pdata)) {
687                 struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata;
688                 u8 cfg, mask;
689
690                 da7219_aad->irq = aad_pdata->irq;
691
692                 switch (aad_pdata->micbias_pulse_lvl) {
693                 case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V:
694                 case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V:
695                         da7219_aad->micbias_pulse_lvl =
696                                 (aad_pdata->micbias_pulse_lvl <<
697                                  DA7219_MICBIAS1_LEVEL_SHIFT);
698                         break;
699                 default:
700                         break;
701                 }
702
703                 da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time;
704
705                 switch (aad_pdata->btn_cfg) {
706                 case DA7219_AAD_BTN_CFG_2MS:
707                 case DA7219_AAD_BTN_CFG_5MS:
708                 case DA7219_AAD_BTN_CFG_10MS:
709                 case DA7219_AAD_BTN_CFG_50MS:
710                 case DA7219_AAD_BTN_CFG_100MS:
711                 case DA7219_AAD_BTN_CFG_200MS:
712                 case DA7219_AAD_BTN_CFG_500MS:
713                         da7219_aad->btn_cfg  = (aad_pdata->btn_cfg <<
714                                                 DA7219_BUTTON_CONFIG_SHIFT);
715                 }
716
717                 cfg = 0;
718                 mask = 0;
719                 switch (aad_pdata->mic_det_thr) {
720                 case DA7219_AAD_MIC_DET_THR_200_OHMS:
721                 case DA7219_AAD_MIC_DET_THR_500_OHMS:
722                 case DA7219_AAD_MIC_DET_THR_750_OHMS:
723                 case DA7219_AAD_MIC_DET_THR_1000_OHMS:
724                         cfg |= (aad_pdata->mic_det_thr <<
725                                 DA7219_MIC_DET_THRESH_SHIFT);
726                         mask |= DA7219_MIC_DET_THRESH_MASK;
727                 }
728                 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, mask, cfg);
729
730                 cfg = 0;
731                 mask = 0;
732                 switch (aad_pdata->jack_ins_deb) {
733                 case DA7219_AAD_JACK_INS_DEB_5MS:
734                 case DA7219_AAD_JACK_INS_DEB_10MS:
735                 case DA7219_AAD_JACK_INS_DEB_20MS:
736                 case DA7219_AAD_JACK_INS_DEB_50MS:
737                 case DA7219_AAD_JACK_INS_DEB_100MS:
738                 case DA7219_AAD_JACK_INS_DEB_200MS:
739                 case DA7219_AAD_JACK_INS_DEB_500MS:
740                 case DA7219_AAD_JACK_INS_DEB_1S:
741                         cfg |= (aad_pdata->jack_ins_deb <<
742                                 DA7219_JACKDET_DEBOUNCE_SHIFT);
743                         mask |= DA7219_JACKDET_DEBOUNCE_MASK;
744                 }
745                 switch (aad_pdata->jack_det_rate) {
746                 case DA7219_AAD_JACK_DET_RATE_32_64MS:
747                 case DA7219_AAD_JACK_DET_RATE_64_128MS:
748                 case DA7219_AAD_JACK_DET_RATE_128_256MS:
749                 case DA7219_AAD_JACK_DET_RATE_256_512MS:
750                         cfg |= (aad_pdata->jack_det_rate <<
751                                 DA7219_JACK_DETECT_RATE_SHIFT);
752                         mask |= DA7219_JACK_DETECT_RATE_MASK;
753                 }
754                 switch (aad_pdata->jack_rem_deb) {
755                 case DA7219_AAD_JACK_REM_DEB_1MS:
756                 case DA7219_AAD_JACK_REM_DEB_5MS:
757                 case DA7219_AAD_JACK_REM_DEB_10MS:
758                 case DA7219_AAD_JACK_REM_DEB_20MS:
759                         cfg |= (aad_pdata->jack_rem_deb <<
760                                 DA7219_JACKDET_REM_DEB_SHIFT);
761                         mask |= DA7219_JACKDET_REM_DEB_MASK;
762                 }
763                 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_2, mask, cfg);
764
765                 snd_soc_write(codec, DA7219_ACCDET_CONFIG_3,
766                               aad_pdata->a_d_btn_thr);
767                 snd_soc_write(codec, DA7219_ACCDET_CONFIG_4,
768                               aad_pdata->d_b_btn_thr);
769                 snd_soc_write(codec, DA7219_ACCDET_CONFIG_5,
770                               aad_pdata->b_c_btn_thr);
771                 snd_soc_write(codec, DA7219_ACCDET_CONFIG_6,
772                               aad_pdata->c_mic_btn_thr);
773
774                 cfg = 0;
775                 mask = 0;
776                 switch (aad_pdata->btn_avg) {
777                 case DA7219_AAD_BTN_AVG_1:
778                 case DA7219_AAD_BTN_AVG_2:
779                 case DA7219_AAD_BTN_AVG_4:
780                 case DA7219_AAD_BTN_AVG_8:
781                         cfg |= (aad_pdata->btn_avg <<
782                                 DA7219_BUTTON_AVERAGE_SHIFT);
783                         mask |= DA7219_BUTTON_AVERAGE_MASK;
784                 }
785                 switch (aad_pdata->adc_1bit_rpt) {
786                 case DA7219_AAD_ADC_1BIT_RPT_1:
787                 case DA7219_AAD_ADC_1BIT_RPT_2:
788                 case DA7219_AAD_ADC_1BIT_RPT_4:
789                 case DA7219_AAD_ADC_1BIT_RPT_8:
790                         cfg |= (aad_pdata->adc_1bit_rpt <<
791                                DA7219_ADC_1_BIT_REPEAT_SHIFT);
792                         mask |= DA7219_ADC_1_BIT_REPEAT_MASK;
793                 }
794                 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_7, mask, cfg);
795         }
796 }
797
798
799 /*
800  * Suspend/Resume
801  */
802
803 void da7219_aad_suspend(struct snd_soc_codec *codec)
804 {
805         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
806         struct da7219_aad_priv *da7219_aad = da7219->aad;
807         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
808         u8 micbias_ctrl;
809
810         if (da7219_aad->jack) {
811                 /* Disable jack detection during suspend */
812                 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
813                                     DA7219_ACCDET_EN_MASK, 0);
814
815                 /*
816                  * If we have a 4-pole jack inserted, then micbias will be
817                  * enabled. We can disable micbias here, and keep a note to
818                  * re-enable it on resume. If jack removal occurred during
819                  * suspend then this will be dealt with through the IRQ handler.
820                  */
821                 if (da7219_aad->jack_inserted) {
822                         micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL);
823                         if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
824                                 snd_soc_dapm_disable_pin(dapm, "Mic Bias");
825                                 snd_soc_dapm_sync(dapm);
826                                 da7219_aad->micbias_resume_enable = true;
827                         }
828                 }
829         }
830 }
831
832 void da7219_aad_resume(struct snd_soc_codec *codec)
833 {
834         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
835         struct da7219_aad_priv *da7219_aad = da7219->aad;
836         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
837
838         if (da7219_aad->jack) {
839                 /* Re-enable micbias if previously enabled for 4-pole jack */
840                 if (da7219_aad->jack_inserted &&
841                     da7219_aad->micbias_resume_enable) {
842                         snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
843                         snd_soc_dapm_sync(dapm);
844                         da7219_aad->micbias_resume_enable = false;
845                 }
846
847                 /* Re-enable jack detection */
848                 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
849                                     DA7219_ACCDET_EN_MASK,
850                                     DA7219_ACCDET_EN_MASK);
851         }
852 }
853
854
855 /*
856  * Init/Exit
857  */
858
859 int da7219_aad_init(struct snd_soc_codec *codec)
860 {
861         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
862         struct da7219_aad_priv *da7219_aad;
863         u8 mask[DA7219_AAD_IRQ_REG_MAX];
864         int ret;
865
866         da7219_aad = devm_kzalloc(codec->dev, sizeof(*da7219_aad), GFP_KERNEL);
867         if (!da7219_aad)
868                 return -ENOMEM;
869
870         da7219->aad = da7219_aad;
871         da7219_aad->codec = codec;
872
873         /* Handle any DT/ACPI/platform data */
874         if (da7219->pdata && !da7219->pdata->aad_pdata)
875                 da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(codec);
876
877         da7219_aad_handle_pdata(codec);
878
879         /* Disable button detection */
880         snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
881                             DA7219_BUTTON_CONFIG_MASK, 0);
882
883         INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
884         INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
885
886         ret = request_threaded_irq(da7219_aad->irq, NULL,
887                                    da7219_aad_irq_thread,
888                                    IRQF_TRIGGER_LOW | IRQF_ONESHOT,
889                                    "da7219-aad", da7219_aad);
890         if (ret) {
891                 dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
892                 return ret;
893         }
894
895         /* Unmask AAD IRQs */
896         memset(mask, 0, DA7219_AAD_IRQ_REG_MAX);
897         regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
898                           &mask, DA7219_AAD_IRQ_REG_MAX);
899
900         return 0;
901 }
902 EXPORT_SYMBOL_GPL(da7219_aad_init);
903
904 void da7219_aad_exit(struct snd_soc_codec *codec)
905 {
906         struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
907         struct da7219_aad_priv *da7219_aad = da7219->aad;
908         u8 mask[DA7219_AAD_IRQ_REG_MAX];
909
910         /* Mask off AAD IRQs */
911         memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX);
912         regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
913                           mask, DA7219_AAD_IRQ_REG_MAX);
914
915         free_irq(da7219_aad->irq, da7219_aad);
916
917         cancel_work_sync(&da7219_aad->btn_det_work);
918         cancel_work_sync(&da7219_aad->hptest_work);
919 }
920 EXPORT_SYMBOL_GPL(da7219_aad_exit);
921
922 MODULE_DESCRIPTION("ASoC DA7219 AAD Driver");
923 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
924 MODULE_LICENSE("GPL");