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