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