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