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