Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver
0004  *
0005  * Copyright (c) 2015 Dialog Semiconductor Ltd.
0006  *
0007  * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/clk.h>
0013 #include <linux/i2c.h>
0014 #include <linux/property.h>
0015 #include <linux/pm_wakeirq.h>
0016 #include <linux/slab.h>
0017 #include <linux/delay.h>
0018 #include <linux/workqueue.h>
0019 #include <sound/soc.h>
0020 #include <sound/jack.h>
0021 #include <sound/da7219.h>
0022 
0023 #include "da7219.h"
0024 #include "da7219-aad.h"
0025 
0026 
0027 /*
0028  * Detection control
0029  */
0030 
0031 void da7219_aad_jack_det(struct snd_soc_component *component, struct snd_soc_jack *jack)
0032 {
0033     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0034 
0035     da7219->aad->jack = jack;
0036     da7219->aad->jack_inserted = false;
0037 
0038     /* Send an initial empty report */
0039     snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK);
0040 
0041     /* Enable/Disable jack detection */
0042     snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0043                 DA7219_ACCDET_EN_MASK,
0044                 (jack ? DA7219_ACCDET_EN_MASK : 0));
0045 }
0046 EXPORT_SYMBOL_GPL(da7219_aad_jack_det);
0047 
0048 /*
0049  * Button/HPTest work
0050  */
0051 
0052 static void da7219_aad_btn_det_work(struct work_struct *work)
0053 {
0054     struct da7219_aad_priv *da7219_aad =
0055         container_of(work, struct da7219_aad_priv, btn_det_work);
0056     struct snd_soc_component *component = da7219_aad->component;
0057     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0058     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0059     u8 statusa, micbias_ctrl;
0060     bool micbias_up = false;
0061     int retries = 0;
0062 
0063     /* Disable ground switch */
0064     snd_soc_component_update_bits(component, 0xFB, 0x01, 0x00);
0065 
0066     /* Drive headphones/lineout */
0067     snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
0068                 DA7219_HP_L_AMP_OE_MASK,
0069                 DA7219_HP_L_AMP_OE_MASK);
0070     snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
0071                 DA7219_HP_R_AMP_OE_MASK,
0072                 DA7219_HP_R_AMP_OE_MASK);
0073 
0074     /* Make sure mic bias is up */
0075     snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
0076     snd_soc_dapm_sync(dapm);
0077 
0078     do {
0079         statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A);
0080         if (statusa & DA7219_MICBIAS_UP_STS_MASK)
0081             micbias_up = true;
0082         else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES)
0083             msleep(DA7219_AAD_MICBIAS_CHK_DELAY);
0084     } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES));
0085 
0086     if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES)
0087         dev_warn(component->dev, "Mic bias status check timed out");
0088 
0089     da7219->micbias_on_event = true;
0090 
0091     /*
0092      * Mic bias pulse required to enable mic, must be done before enabling
0093      * button detection to prevent erroneous button readings.
0094      */
0095     if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) {
0096         /* Pulse higher level voltage */
0097         micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL);
0098         snd_soc_component_update_bits(component, DA7219_MICBIAS_CTRL,
0099                     DA7219_MICBIAS1_LEVEL_MASK,
0100                     da7219_aad->micbias_pulse_lvl);
0101         msleep(da7219_aad->micbias_pulse_time);
0102         snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_ctrl);
0103 
0104     }
0105 
0106     snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0107                 DA7219_BUTTON_CONFIG_MASK,
0108                 da7219_aad->btn_cfg);
0109 }
0110 
0111 static void da7219_aad_hptest_work(struct work_struct *work)
0112 {
0113     struct da7219_aad_priv *da7219_aad =
0114         container_of(work, struct da7219_aad_priv, hptest_work);
0115     struct snd_soc_component *component = da7219_aad->component;
0116     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0117     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0118 
0119     __le16 tonegen_freq_hptest;
0120     u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8;
0121     int report = 0, ret;
0122 
0123     /* Lock DAPM, Kcontrols affected by this test and the PLL */
0124     snd_soc_dapm_mutex_lock(dapm);
0125     mutex_lock(&da7219->ctrl_lock);
0126     mutex_lock(&da7219->pll_lock);
0127 
0128     /* Ensure MCLK is available for HP test procedure */
0129     if (da7219->mclk) {
0130         ret = clk_prepare_enable(da7219->mclk);
0131         if (ret) {
0132             dev_err(component->dev, "Failed to enable mclk - %d\n", ret);
0133             mutex_unlock(&da7219->pll_lock);
0134             mutex_unlock(&da7219->ctrl_lock);
0135             snd_soc_dapm_mutex_unlock(dapm);
0136             return;
0137         }
0138     }
0139 
0140     /*
0141      * If MCLK not present, then we're using the internal oscillator and
0142      * require different frequency settings to achieve the same result.
0143      *
0144      * If MCLK is present, but PLL is not enabled then we enable it here to
0145      * ensure a consistent detection procedure.
0146      */
0147     pll_srm_sts = snd_soc_component_read(component, DA7219_PLL_SRM_STS);
0148     if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) {
0149         tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
0150 
0151         pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL);
0152         if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS)
0153             da7219_set_pll(component, DA7219_SYSCLK_PLL,
0154                        DA7219_PLL_FREQ_OUT_98304);
0155     } else {
0156         tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC);
0157     }
0158 
0159     /* Disable ground switch */
0160     snd_soc_component_update_bits(component, 0xFB, 0x01, 0x00);
0161 
0162     /* Ensure gain ramping at fastest rate */
0163     gain_ramp_ctrl = snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL);
0164     snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8);
0165 
0166     /* Bypass cache so it saves current settings */
0167     regcache_cache_bypass(da7219->regmap, true);
0168 
0169     /* Make sure Tone Generator is disabled */
0170     snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, 0);
0171 
0172     /* Enable HPTest block, 1KOhms check */
0173     snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_8,
0174                 DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK,
0175                 DA7219_HPTEST_EN_MASK |
0176                 DA7219_HPTEST_RES_SEL_1KOHMS);
0177 
0178     /* Set gains to 0db */
0179     snd_soc_component_write(component, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
0180     snd_soc_component_write(component, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
0181     snd_soc_component_write(component, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB);
0182     snd_soc_component_write(component, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB);
0183 
0184     /* Disable DAC filters, EQs and soft mute */
0185     snd_soc_component_update_bits(component, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK,
0186                 0);
0187     snd_soc_component_update_bits(component, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK,
0188                 0);
0189     snd_soc_component_update_bits(component, DA7219_DAC_FILTERS5,
0190                 DA7219_DAC_SOFTMUTE_EN_MASK, 0);
0191 
0192     /* Enable HP left & right paths */
0193     snd_soc_component_update_bits(component, DA7219_CP_CTRL, DA7219_CP_EN_MASK,
0194                 DA7219_CP_EN_MASK);
0195     snd_soc_component_update_bits(component, DA7219_DIG_ROUTING_DAC,
0196                 DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK,
0197                 DA7219_DAC_L_SRC_TONEGEN |
0198                 DA7219_DAC_R_SRC_TONEGEN);
0199     snd_soc_component_update_bits(component, DA7219_DAC_L_CTRL,
0200                 DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK,
0201                 DA7219_DAC_L_EN_MASK);
0202     snd_soc_component_update_bits(component, DA7219_DAC_R_CTRL,
0203                 DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK,
0204                 DA7219_DAC_R_EN_MASK);
0205     snd_soc_component_update_bits(component, DA7219_MIXOUT_L_SELECT,
0206                 DA7219_MIXOUT_L_MIX_SELECT_MASK,
0207                 DA7219_MIXOUT_L_MIX_SELECT_MASK);
0208     snd_soc_component_update_bits(component, DA7219_MIXOUT_R_SELECT,
0209                 DA7219_MIXOUT_R_MIX_SELECT_MASK,
0210                 DA7219_MIXOUT_R_MIX_SELECT_MASK);
0211     snd_soc_component_update_bits(component, DA7219_DROUTING_ST_OUTFILT_1L,
0212                 DA7219_OUTFILT_ST_1L_SRC_MASK,
0213                 DA7219_DMIX_ST_SRC_OUTFILT1L);
0214     snd_soc_component_update_bits(component, DA7219_DROUTING_ST_OUTFILT_1R,
0215                 DA7219_OUTFILT_ST_1R_SRC_MASK,
0216                 DA7219_DMIX_ST_SRC_OUTFILT1R);
0217     snd_soc_component_update_bits(component, DA7219_MIXOUT_L_CTRL,
0218                 DA7219_MIXOUT_L_AMP_EN_MASK,
0219                 DA7219_MIXOUT_L_AMP_EN_MASK);
0220     snd_soc_component_update_bits(component, DA7219_MIXOUT_R_CTRL,
0221                 DA7219_MIXOUT_R_AMP_EN_MASK,
0222                 DA7219_MIXOUT_R_AMP_EN_MASK);
0223     snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
0224                 DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK,
0225                 DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK);
0226     snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
0227                 DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK,
0228                 DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
0229     msleep(DA7219_SETTLING_DELAY);
0230     snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
0231                 DA7219_HP_L_AMP_MUTE_EN_MASK |
0232                 DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, 0);
0233     snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
0234                 DA7219_HP_R_AMP_MUTE_EN_MASK |
0235                 DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, 0);
0236 
0237     /*
0238      * If we're running from the internal oscillator then give audio paths
0239      * time to settle before running test.
0240      */
0241     if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
0242         msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
0243 
0244     /* Configure & start Tone Generator */
0245     snd_soc_component_write(component, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK);
0246     regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
0247              &tonegen_freq_hptest, sizeof(tonegen_freq_hptest));
0248     snd_soc_component_update_bits(component, DA7219_TONE_GEN_CFG2,
0249                 DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK,
0250                 DA7219_SWG_SEL_SRAMP |
0251                 DA7219_TONE_GEN_GAIN_MINUS_15DB);
0252     snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK);
0253 
0254     msleep(DA7219_AAD_HPTEST_PERIOD);
0255 
0256     /* Grab comparator reading */
0257     accdet_cfg8 = snd_soc_component_read(component, DA7219_ACCDET_CONFIG_8);
0258     if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK)
0259         report |= SND_JACK_HEADPHONE;
0260     else
0261         report |= SND_JACK_LINEOUT;
0262 
0263     /* Stop tone generator */
0264     snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, 0);
0265 
0266     msleep(DA7219_AAD_HPTEST_PERIOD);
0267 
0268     /* Restore original settings from cache */
0269     regcache_mark_dirty(da7219->regmap);
0270     regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL,
0271                  DA7219_HP_R_CTRL);
0272     msleep(DA7219_SETTLING_DELAY);
0273     regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL,
0274                  DA7219_MIXOUT_R_CTRL);
0275     regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L,
0276                  DA7219_DROUTING_ST_OUTFILT_1R);
0277     regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT,
0278                  DA7219_MIXOUT_R_SELECT);
0279     regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL,
0280                  DA7219_DAC_R_CTRL);
0281     regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC,
0282                  DA7219_DIG_ROUTING_DAC);
0283     regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL);
0284     regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5,
0285                  DA7219_DAC_FILTERS5);
0286     regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4,
0287                  DA7219_DAC_FILTERS1);
0288     regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN,
0289                  DA7219_HP_R_GAIN);
0290     regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN,
0291                  DA7219_DAC_R_GAIN);
0292     regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER,
0293                  DA7219_TONE_GEN_ON_PER);
0294     regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
0295                  DA7219_TONE_GEN_FREQ1_U);
0296     regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1,
0297                  DA7219_TONE_GEN_CFG2);
0298 
0299     regcache_cache_bypass(da7219->regmap, false);
0300 
0301     /* Disable HPTest block */
0302     snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_8,
0303                 DA7219_HPTEST_EN_MASK, 0);
0304 
0305     /*
0306      * If we're running from the internal oscillator then give audio paths
0307      * time to settle before allowing headphones to be driven as required.
0308      */
0309     if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
0310         msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
0311 
0312     /* Restore gain ramping rate */
0313     snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl);
0314 
0315     /* Drive Headphones/lineout */
0316     snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK,
0317                 DA7219_HP_L_AMP_OE_MASK);
0318     snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK,
0319                 DA7219_HP_R_AMP_OE_MASK);
0320 
0321     /* Restore PLL to previous configuration, if re-configured */
0322     if ((pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) &&
0323         ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS))
0324         da7219_set_pll(component, DA7219_SYSCLK_MCLK, 0);
0325 
0326     /* Remove MCLK, if previously enabled */
0327     if (da7219->mclk)
0328         clk_disable_unprepare(da7219->mclk);
0329 
0330     mutex_unlock(&da7219->pll_lock);
0331     mutex_unlock(&da7219->ctrl_lock);
0332     snd_soc_dapm_mutex_unlock(dapm);
0333 
0334     /*
0335      * Only send report if jack hasn't been removed during process,
0336      * otherwise it's invalid and we drop it.
0337      */
0338     if (da7219_aad->jack_inserted)
0339         snd_soc_jack_report(da7219_aad->jack, report,
0340                     SND_JACK_HEADSET | SND_JACK_LINEOUT);
0341 }
0342 
0343 
0344 /*
0345  * IRQ
0346  */
0347 
0348 static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
0349 {
0350     struct da7219_aad_priv *da7219_aad = data;
0351     struct snd_soc_component *component = da7219_aad->component;
0352     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0353     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0354     u8 events[DA7219_AAD_IRQ_REG_MAX];
0355     u8 statusa;
0356     int i, report = 0, mask = 0;
0357 
0358     /* Read current IRQ events */
0359     regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
0360              events, DA7219_AAD_IRQ_REG_MAX);
0361 
0362     if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B])
0363         return IRQ_NONE;
0364 
0365     /* Read status register for jack insertion & type status */
0366     statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A);
0367 
0368     /* Clear events */
0369     regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
0370               events, DA7219_AAD_IRQ_REG_MAX);
0371 
0372     dev_dbg(component->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n",
0373         events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
0374         statusa);
0375 
0376     if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
0377         /* Jack Insertion */
0378         if (events[DA7219_AAD_IRQ_REG_A] &
0379             DA7219_E_JACK_INSERTED_MASK) {
0380             report |= SND_JACK_MECHANICAL;
0381             mask |= SND_JACK_MECHANICAL;
0382             da7219_aad->jack_inserted = true;
0383         }
0384 
0385         /* Jack type detection */
0386         if (events[DA7219_AAD_IRQ_REG_A] &
0387             DA7219_E_JACK_DETECT_COMPLETE_MASK) {
0388             /*
0389              * If 4-pole, then enable button detection, else perform
0390              * HP impedance test to determine output type to report.
0391              *
0392              * We schedule work here as the tasks themselves can
0393              * take time to complete, and in particular for hptest
0394              * we want to be able to check if the jack was removed
0395              * during the procedure as this will invalidate the
0396              * result. By doing this as work, the IRQ thread can
0397              * handle a removal, and we can check at the end of
0398              * hptest if we have a valid result or not.
0399              */
0400             if (statusa & DA7219_JACK_TYPE_STS_MASK) {
0401                 report |= SND_JACK_HEADSET;
0402                 mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT;
0403                 schedule_work(&da7219_aad->btn_det_work);
0404             } else {
0405                 schedule_work(&da7219_aad->hptest_work);
0406             }
0407         }
0408 
0409         /* Button support for 4-pole jack */
0410         if (statusa & DA7219_JACK_TYPE_STS_MASK) {
0411             for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
0412                 /* Button Press */
0413                 if (events[DA7219_AAD_IRQ_REG_B] &
0414                     (DA7219_E_BUTTON_A_PRESSED_MASK << i)) {
0415                     report |= SND_JACK_BTN_0 >> i;
0416                     mask |= SND_JACK_BTN_0 >> i;
0417                 }
0418             }
0419             snd_soc_jack_report(da7219_aad->jack, report, mask);
0420 
0421             for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
0422                 /* Button Release */
0423                 if (events[DA7219_AAD_IRQ_REG_B] &
0424                     (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) {
0425                     report &= ~(SND_JACK_BTN_0 >> i);
0426                     mask |= SND_JACK_BTN_0 >> i;
0427                 }
0428             }
0429         }
0430     } else {
0431         /* Jack removal */
0432         if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) {
0433             report = 0;
0434             mask |= DA7219_AAD_REPORT_ALL_MASK;
0435             da7219_aad->jack_inserted = false;
0436 
0437             /* Cancel any pending work */
0438             cancel_work_sync(&da7219_aad->btn_det_work);
0439             cancel_work_sync(&da7219_aad->hptest_work);
0440 
0441             /* Un-drive headphones/lineout */
0442             snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
0443                         DA7219_HP_R_AMP_OE_MASK, 0);
0444             snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
0445                         DA7219_HP_L_AMP_OE_MASK, 0);
0446 
0447             /* Ensure button detection disabled */
0448             snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0449                         DA7219_BUTTON_CONFIG_MASK, 0);
0450 
0451             da7219->micbias_on_event = false;
0452 
0453             /* Disable mic bias */
0454             snd_soc_dapm_disable_pin(dapm, "Mic Bias");
0455             snd_soc_dapm_sync(dapm);
0456 
0457             /* Enable ground switch */
0458             snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);
0459         }
0460     }
0461 
0462     snd_soc_jack_report(da7219_aad->jack, report, mask);
0463 
0464     return IRQ_HANDLED;
0465 }
0466 
0467 /*
0468  * DT/ACPI to pdata conversion
0469  */
0470 
0471 static enum da7219_aad_micbias_pulse_lvl
0472     da7219_aad_fw_micbias_pulse_lvl(struct device *dev, u32 val)
0473 {
0474     switch (val) {
0475     case 2800:
0476         return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V;
0477     case 2900:
0478         return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V;
0479     default:
0480         dev_warn(dev, "Invalid micbias pulse level");
0481         return DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
0482     }
0483 }
0484 
0485 static enum da7219_aad_btn_cfg
0486     da7219_aad_fw_btn_cfg(struct device *dev, u32 val)
0487 {
0488     switch (val) {
0489     case 2:
0490         return DA7219_AAD_BTN_CFG_2MS;
0491     case 5:
0492         return DA7219_AAD_BTN_CFG_5MS;
0493     case 10:
0494         return DA7219_AAD_BTN_CFG_10MS;
0495     case 50:
0496         return DA7219_AAD_BTN_CFG_50MS;
0497     case 100:
0498         return DA7219_AAD_BTN_CFG_100MS;
0499     case 200:
0500         return DA7219_AAD_BTN_CFG_200MS;
0501     case 500:
0502         return DA7219_AAD_BTN_CFG_500MS;
0503     default:
0504         dev_warn(dev, "Invalid button config");
0505         return DA7219_AAD_BTN_CFG_10MS;
0506     }
0507 }
0508 
0509 static enum da7219_aad_mic_det_thr
0510     da7219_aad_fw_mic_det_thr(struct device *dev, u32 val)
0511 {
0512     switch (val) {
0513     case 200:
0514         return DA7219_AAD_MIC_DET_THR_200_OHMS;
0515     case 500:
0516         return DA7219_AAD_MIC_DET_THR_500_OHMS;
0517     case 750:
0518         return DA7219_AAD_MIC_DET_THR_750_OHMS;
0519     case 1000:
0520         return DA7219_AAD_MIC_DET_THR_1000_OHMS;
0521     default:
0522         dev_warn(dev, "Invalid mic detect threshold");
0523         return DA7219_AAD_MIC_DET_THR_500_OHMS;
0524     }
0525 }
0526 
0527 static enum da7219_aad_jack_ins_deb
0528     da7219_aad_fw_jack_ins_deb(struct device *dev, u32 val)
0529 {
0530     switch (val) {
0531     case 5:
0532         return DA7219_AAD_JACK_INS_DEB_5MS;
0533     case 10:
0534         return DA7219_AAD_JACK_INS_DEB_10MS;
0535     case 20:
0536         return DA7219_AAD_JACK_INS_DEB_20MS;
0537     case 50:
0538         return DA7219_AAD_JACK_INS_DEB_50MS;
0539     case 100:
0540         return DA7219_AAD_JACK_INS_DEB_100MS;
0541     case 200:
0542         return DA7219_AAD_JACK_INS_DEB_200MS;
0543     case 500:
0544         return DA7219_AAD_JACK_INS_DEB_500MS;
0545     case 1000:
0546         return DA7219_AAD_JACK_INS_DEB_1S;
0547     default:
0548         dev_warn(dev, "Invalid jack insert debounce");
0549         return DA7219_AAD_JACK_INS_DEB_20MS;
0550     }
0551 }
0552 
0553 static enum da7219_aad_jack_det_rate
0554     da7219_aad_fw_jack_det_rate(struct device *dev, const char *str)
0555 {
0556     if (!strcmp(str, "32ms_64ms")) {
0557         return DA7219_AAD_JACK_DET_RATE_32_64MS;
0558     } else if (!strcmp(str, "64ms_128ms")) {
0559         return DA7219_AAD_JACK_DET_RATE_64_128MS;
0560     } else if (!strcmp(str, "128ms_256ms")) {
0561         return DA7219_AAD_JACK_DET_RATE_128_256MS;
0562     } else if (!strcmp(str, "256ms_512ms")) {
0563         return DA7219_AAD_JACK_DET_RATE_256_512MS;
0564     } else {
0565         dev_warn(dev, "Invalid jack detect rate");
0566         return DA7219_AAD_JACK_DET_RATE_256_512MS;
0567     }
0568 }
0569 
0570 static enum da7219_aad_jack_rem_deb
0571     da7219_aad_fw_jack_rem_deb(struct device *dev, u32 val)
0572 {
0573     switch (val) {
0574     case 1:
0575         return DA7219_AAD_JACK_REM_DEB_1MS;
0576     case 5:
0577         return DA7219_AAD_JACK_REM_DEB_5MS;
0578     case 10:
0579         return DA7219_AAD_JACK_REM_DEB_10MS;
0580     case 20:
0581         return DA7219_AAD_JACK_REM_DEB_20MS;
0582     default:
0583         dev_warn(dev, "Invalid jack removal debounce");
0584         return DA7219_AAD_JACK_REM_DEB_1MS;
0585     }
0586 }
0587 
0588 static enum da7219_aad_btn_avg
0589     da7219_aad_fw_btn_avg(struct device *dev, u32 val)
0590 {
0591     switch (val) {
0592     case 1:
0593         return DA7219_AAD_BTN_AVG_1;
0594     case 2:
0595         return DA7219_AAD_BTN_AVG_2;
0596     case 4:
0597         return DA7219_AAD_BTN_AVG_4;
0598     case 8:
0599         return DA7219_AAD_BTN_AVG_8;
0600     default:
0601         dev_warn(dev, "Invalid button average value");
0602         return DA7219_AAD_BTN_AVG_2;
0603     }
0604 }
0605 
0606 static enum da7219_aad_adc_1bit_rpt
0607     da7219_aad_fw_adc_1bit_rpt(struct device *dev, u32 val)
0608 {
0609     switch (val) {
0610     case 1:
0611         return DA7219_AAD_ADC_1BIT_RPT_1;
0612     case 2:
0613         return DA7219_AAD_ADC_1BIT_RPT_2;
0614     case 4:
0615         return DA7219_AAD_ADC_1BIT_RPT_4;
0616     case 8:
0617         return DA7219_AAD_ADC_1BIT_RPT_8;
0618     default:
0619         dev_warn(dev, "Invalid ADC 1-bit repeat value");
0620         return DA7219_AAD_ADC_1BIT_RPT_1;
0621     }
0622 }
0623 
0624 static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
0625 {
0626     struct i2c_client *i2c = to_i2c_client(dev);
0627     struct fwnode_handle *aad_np;
0628     struct da7219_aad_pdata *aad_pdata;
0629     const char *fw_str;
0630     u32 fw_val32;
0631 
0632     aad_np = device_get_named_child_node(dev, "da7219_aad");
0633     if (!aad_np)
0634         return NULL;
0635 
0636     aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
0637     if (!aad_pdata)
0638         return NULL;
0639 
0640     aad_pdata->irq = i2c->irq;
0641 
0642     if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-lvl",
0643                      &fw_val32) >= 0)
0644         aad_pdata->micbias_pulse_lvl =
0645             da7219_aad_fw_micbias_pulse_lvl(dev, fw_val32);
0646     else
0647         aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
0648 
0649     if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-time",
0650                      &fw_val32) >= 0)
0651         aad_pdata->micbias_pulse_time = fw_val32;
0652 
0653     if (fwnode_property_read_u32(aad_np, "dlg,btn-cfg", &fw_val32) >= 0)
0654         aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(dev, fw_val32);
0655     else
0656         aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS;
0657 
0658     if (fwnode_property_read_u32(aad_np, "dlg,mic-det-thr", &fw_val32) >= 0)
0659         aad_pdata->mic_det_thr =
0660             da7219_aad_fw_mic_det_thr(dev, fw_val32);
0661     else
0662         aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
0663 
0664     if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
0665         aad_pdata->jack_ins_deb =
0666             da7219_aad_fw_jack_ins_deb(dev, fw_val32);
0667     else
0668         aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS;
0669 
0670     if (!fwnode_property_read_string(aad_np, "dlg,jack-det-rate", &fw_str))
0671         aad_pdata->jack_det_rate =
0672             da7219_aad_fw_jack_det_rate(dev, fw_str);
0673     else
0674         aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS;
0675 
0676     if (fwnode_property_read_u32(aad_np, "dlg,jack-rem-deb", &fw_val32) >= 0)
0677         aad_pdata->jack_rem_deb =
0678             da7219_aad_fw_jack_rem_deb(dev, fw_val32);
0679     else
0680         aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS;
0681 
0682     if (fwnode_property_read_u32(aad_np, "dlg,a-d-btn-thr", &fw_val32) >= 0)
0683         aad_pdata->a_d_btn_thr = (u8) fw_val32;
0684     else
0685         aad_pdata->a_d_btn_thr = 0xA;
0686 
0687     if (fwnode_property_read_u32(aad_np, "dlg,d-b-btn-thr", &fw_val32) >= 0)
0688         aad_pdata->d_b_btn_thr = (u8) fw_val32;
0689     else
0690         aad_pdata->d_b_btn_thr = 0x16;
0691 
0692     if (fwnode_property_read_u32(aad_np, "dlg,b-c-btn-thr", &fw_val32) >= 0)
0693         aad_pdata->b_c_btn_thr = (u8) fw_val32;
0694     else
0695         aad_pdata->b_c_btn_thr = 0x21;
0696 
0697     if (fwnode_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &fw_val32) >= 0)
0698         aad_pdata->c_mic_btn_thr = (u8) fw_val32;
0699     else
0700         aad_pdata->c_mic_btn_thr = 0x3E;
0701 
0702     if (fwnode_property_read_u32(aad_np, "dlg,btn-avg", &fw_val32) >= 0)
0703         aad_pdata->btn_avg = da7219_aad_fw_btn_avg(dev, fw_val32);
0704     else
0705         aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2;
0706 
0707     if (fwnode_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &fw_val32) >= 0)
0708         aad_pdata->adc_1bit_rpt =
0709             da7219_aad_fw_adc_1bit_rpt(dev, fw_val32);
0710     else
0711         aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
0712 
0713     return aad_pdata;
0714 }
0715 
0716 static void da7219_aad_handle_pdata(struct snd_soc_component *component)
0717 {
0718     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0719     struct da7219_aad_priv *da7219_aad = da7219->aad;
0720     struct da7219_pdata *pdata = da7219->pdata;
0721 
0722     if ((pdata) && (pdata->aad_pdata)) {
0723         struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata;
0724         u8 cfg, mask;
0725 
0726         da7219_aad->irq = aad_pdata->irq;
0727 
0728         switch (aad_pdata->micbias_pulse_lvl) {
0729         case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V:
0730         case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V:
0731             da7219_aad->micbias_pulse_lvl =
0732                 (aad_pdata->micbias_pulse_lvl <<
0733                  DA7219_MICBIAS1_LEVEL_SHIFT);
0734             break;
0735         default:
0736             break;
0737         }
0738 
0739         da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time;
0740 
0741         switch (aad_pdata->btn_cfg) {
0742         case DA7219_AAD_BTN_CFG_2MS:
0743         case DA7219_AAD_BTN_CFG_5MS:
0744         case DA7219_AAD_BTN_CFG_10MS:
0745         case DA7219_AAD_BTN_CFG_50MS:
0746         case DA7219_AAD_BTN_CFG_100MS:
0747         case DA7219_AAD_BTN_CFG_200MS:
0748         case DA7219_AAD_BTN_CFG_500MS:
0749             da7219_aad->btn_cfg  = (aad_pdata->btn_cfg <<
0750                         DA7219_BUTTON_CONFIG_SHIFT);
0751         }
0752 
0753         cfg = 0;
0754         mask = 0;
0755         switch (aad_pdata->mic_det_thr) {
0756         case DA7219_AAD_MIC_DET_THR_200_OHMS:
0757         case DA7219_AAD_MIC_DET_THR_500_OHMS:
0758         case DA7219_AAD_MIC_DET_THR_750_OHMS:
0759         case DA7219_AAD_MIC_DET_THR_1000_OHMS:
0760             cfg |= (aad_pdata->mic_det_thr <<
0761                 DA7219_MIC_DET_THRESH_SHIFT);
0762             mask |= DA7219_MIC_DET_THRESH_MASK;
0763         }
0764         snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, mask, cfg);
0765 
0766         cfg = 0;
0767         mask = 0;
0768         switch (aad_pdata->jack_ins_deb) {
0769         case DA7219_AAD_JACK_INS_DEB_5MS:
0770         case DA7219_AAD_JACK_INS_DEB_10MS:
0771         case DA7219_AAD_JACK_INS_DEB_20MS:
0772         case DA7219_AAD_JACK_INS_DEB_50MS:
0773         case DA7219_AAD_JACK_INS_DEB_100MS:
0774         case DA7219_AAD_JACK_INS_DEB_200MS:
0775         case DA7219_AAD_JACK_INS_DEB_500MS:
0776         case DA7219_AAD_JACK_INS_DEB_1S:
0777             cfg |= (aad_pdata->jack_ins_deb <<
0778                 DA7219_JACKDET_DEBOUNCE_SHIFT);
0779             mask |= DA7219_JACKDET_DEBOUNCE_MASK;
0780         }
0781         switch (aad_pdata->jack_det_rate) {
0782         case DA7219_AAD_JACK_DET_RATE_32_64MS:
0783         case DA7219_AAD_JACK_DET_RATE_64_128MS:
0784         case DA7219_AAD_JACK_DET_RATE_128_256MS:
0785         case DA7219_AAD_JACK_DET_RATE_256_512MS:
0786             cfg |= (aad_pdata->jack_det_rate <<
0787                 DA7219_JACK_DETECT_RATE_SHIFT);
0788             mask |= DA7219_JACK_DETECT_RATE_MASK;
0789         }
0790         switch (aad_pdata->jack_rem_deb) {
0791         case DA7219_AAD_JACK_REM_DEB_1MS:
0792         case DA7219_AAD_JACK_REM_DEB_5MS:
0793         case DA7219_AAD_JACK_REM_DEB_10MS:
0794         case DA7219_AAD_JACK_REM_DEB_20MS:
0795             cfg |= (aad_pdata->jack_rem_deb <<
0796                 DA7219_JACKDET_REM_DEB_SHIFT);
0797             mask |= DA7219_JACKDET_REM_DEB_MASK;
0798         }
0799         snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_2, mask, cfg);
0800 
0801         snd_soc_component_write(component, DA7219_ACCDET_CONFIG_3,
0802                   aad_pdata->a_d_btn_thr);
0803         snd_soc_component_write(component, DA7219_ACCDET_CONFIG_4,
0804                   aad_pdata->d_b_btn_thr);
0805         snd_soc_component_write(component, DA7219_ACCDET_CONFIG_5,
0806                   aad_pdata->b_c_btn_thr);
0807         snd_soc_component_write(component, DA7219_ACCDET_CONFIG_6,
0808                   aad_pdata->c_mic_btn_thr);
0809 
0810         cfg = 0;
0811         mask = 0;
0812         switch (aad_pdata->btn_avg) {
0813         case DA7219_AAD_BTN_AVG_1:
0814         case DA7219_AAD_BTN_AVG_2:
0815         case DA7219_AAD_BTN_AVG_4:
0816         case DA7219_AAD_BTN_AVG_8:
0817             cfg |= (aad_pdata->btn_avg <<
0818                 DA7219_BUTTON_AVERAGE_SHIFT);
0819             mask |= DA7219_BUTTON_AVERAGE_MASK;
0820         }
0821         switch (aad_pdata->adc_1bit_rpt) {
0822         case DA7219_AAD_ADC_1BIT_RPT_1:
0823         case DA7219_AAD_ADC_1BIT_RPT_2:
0824         case DA7219_AAD_ADC_1BIT_RPT_4:
0825         case DA7219_AAD_ADC_1BIT_RPT_8:
0826             cfg |= (aad_pdata->adc_1bit_rpt <<
0827                    DA7219_ADC_1_BIT_REPEAT_SHIFT);
0828             mask |= DA7219_ADC_1_BIT_REPEAT_MASK;
0829         }
0830         snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_7, mask, cfg);
0831     }
0832 }
0833 
0834 
0835 /*
0836  * Suspend/Resume
0837  */
0838 
0839 void da7219_aad_suspend(struct snd_soc_component *component)
0840 {
0841     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0842     struct da7219_aad_priv *da7219_aad = da7219->aad;
0843     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0844     u8 micbias_ctrl;
0845 
0846     if (da7219_aad->jack) {
0847         /* Disable jack detection during suspend */
0848         snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0849                     DA7219_ACCDET_EN_MASK, 0);
0850 
0851         /*
0852          * If we have a 4-pole jack inserted, then micbias will be
0853          * enabled. We can disable micbias here, and keep a note to
0854          * re-enable it on resume. If jack removal occurred during
0855          * suspend then this will be dealt with through the IRQ handler.
0856          */
0857         if (da7219_aad->jack_inserted) {
0858             micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL);
0859             if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
0860                 snd_soc_dapm_disable_pin(dapm, "Mic Bias");
0861                 snd_soc_dapm_sync(dapm);
0862                 da7219_aad->micbias_resume_enable = true;
0863             }
0864         }
0865     }
0866 }
0867 
0868 void da7219_aad_resume(struct snd_soc_component *component)
0869 {
0870     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0871     struct da7219_aad_priv *da7219_aad = da7219->aad;
0872     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0873 
0874     if (da7219_aad->jack) {
0875         /* Re-enable micbias if previously enabled for 4-pole jack */
0876         if (da7219_aad->jack_inserted &&
0877             da7219_aad->micbias_resume_enable) {
0878             snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
0879             snd_soc_dapm_sync(dapm);
0880             da7219_aad->micbias_resume_enable = false;
0881         }
0882 
0883         /* Re-enable jack detection */
0884         snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0885                     DA7219_ACCDET_EN_MASK,
0886                     DA7219_ACCDET_EN_MASK);
0887     }
0888 }
0889 
0890 
0891 /*
0892  * Init/Exit
0893  */
0894 
0895 int da7219_aad_init(struct snd_soc_component *component)
0896 {
0897     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0898     struct da7219_aad_priv *da7219_aad = da7219->aad;
0899     u8 mask[DA7219_AAD_IRQ_REG_MAX];
0900     int ret;
0901 
0902     da7219_aad->component = component;
0903 
0904     /* Handle any DT/ACPI/platform data */
0905     da7219_aad_handle_pdata(component);
0906 
0907     /* Disable button detection */
0908     snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
0909                 DA7219_BUTTON_CONFIG_MASK, 0);
0910 
0911     /* Enable ground switch */
0912     snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);
0913 
0914     INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
0915     INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
0916 
0917     ret = request_threaded_irq(da7219_aad->irq, NULL,
0918                    da7219_aad_irq_thread,
0919                    IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0920                    "da7219-aad", da7219_aad);
0921     if (ret) {
0922         dev_err(component->dev, "Failed to request IRQ: %d\n", ret);
0923         return ret;
0924     }
0925 
0926     /* Unmask AAD IRQs */
0927     memset(mask, 0, DA7219_AAD_IRQ_REG_MAX);
0928     regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
0929               &mask, DA7219_AAD_IRQ_REG_MAX);
0930 
0931     return 0;
0932 }
0933 EXPORT_SYMBOL_GPL(da7219_aad_init);
0934 
0935 void da7219_aad_exit(struct snd_soc_component *component)
0936 {
0937     struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
0938     struct da7219_aad_priv *da7219_aad = da7219->aad;
0939     u8 mask[DA7219_AAD_IRQ_REG_MAX];
0940 
0941     /* Mask off AAD IRQs */
0942     memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX);
0943     regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
0944               mask, DA7219_AAD_IRQ_REG_MAX);
0945 
0946     free_irq(da7219_aad->irq, da7219_aad);
0947 
0948     cancel_work_sync(&da7219_aad->btn_det_work);
0949     cancel_work_sync(&da7219_aad->hptest_work);
0950 }
0951 EXPORT_SYMBOL_GPL(da7219_aad_exit);
0952 
0953 /*
0954  * AAD related I2C probe handling
0955  */
0956 
0957 int da7219_aad_probe(struct i2c_client *i2c)
0958 {
0959     struct da7219_priv *da7219 = i2c_get_clientdata(i2c);
0960     struct device *dev = &i2c->dev;
0961     struct da7219_aad_priv *da7219_aad;
0962 
0963     da7219_aad = devm_kzalloc(dev, sizeof(*da7219_aad), GFP_KERNEL);
0964     if (!da7219_aad)
0965         return -ENOMEM;
0966 
0967     da7219->aad = da7219_aad;
0968 
0969     /* Retrieve any DT/ACPI/platform data */
0970     if (da7219->pdata && !da7219->pdata->aad_pdata)
0971         da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(dev);
0972 
0973     return 0;
0974 }
0975 EXPORT_SYMBOL_GPL(da7219_aad_probe);
0976 
0977 MODULE_DESCRIPTION("ASoC DA7219 AAD Driver");
0978 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
0979 MODULE_LICENSE("GPL");