aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/nau8825.c45
-rw-r--r--sound/soc/codecs/nau8825.h1
2 files changed, 32 insertions, 14 deletions
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 5778eadbf9e6..2aea642b4a5d 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -194,10 +194,10 @@ static const struct reg_default nau8825_reg_defaults[] = {
194 194
195/* register backup table when cross talk detection */ 195/* register backup table when cross talk detection */
196static struct reg_default nau8825_xtalk_baktab[] = { 196static struct reg_default nau8825_xtalk_baktab[] = {
197 { NAU8825_REG_ADC_DGAIN_CTRL, 0 }, 197 { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf },
198 { NAU8825_REG_HSVOL_CTRL, 0 }, 198 { NAU8825_REG_HSVOL_CTRL, 0 },
199 { NAU8825_REG_DACL_CTRL, 0 }, 199 { NAU8825_REG_DACL_CTRL, 0x00cf },
200 { NAU8825_REG_DACR_CTRL, 0 }, 200 { NAU8825_REG_DACR_CTRL, 0x02cf },
201}; 201};
202 202
203static const unsigned short logtable[256] = { 203static const unsigned short logtable[256] = {
@@ -455,22 +455,32 @@ static void nau8825_xtalk_backup(struct nau8825 *nau8825)
455{ 455{
456 int i; 456 int i;
457 457
458 if (nau8825->xtalk_baktab_initialized)
459 return;
460
458 /* Backup some register values to backup table */ 461 /* Backup some register values to backup table */
459 for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) 462 for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++)
460 regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg, 463 regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
461 &nau8825_xtalk_baktab[i].def); 464 &nau8825_xtalk_baktab[i].def);
465
466 nau8825->xtalk_baktab_initialized = true;
462} 467}
463 468
464static void nau8825_xtalk_restore(struct nau8825 *nau8825) 469static void nau8825_xtalk_restore(struct nau8825 *nau8825, bool cause_cancel)
465{ 470{
466 int i, volume; 471 int i, volume;
467 472
473 if (!nau8825->xtalk_baktab_initialized)
474 return;
475
468 /* Restore register values from backup table; When the driver restores 476 /* Restore register values from backup table; When the driver restores
469 * the headphone volumem, it needs recover to original level gradually 477 * the headphone volume in XTALK_DONE state, it needs recover to
470 * with 3dB per step for less pop noise. 478 * original level gradually with 3dB per step for less pop noise.
479 * Otherwise, the restore should do ASAP.
471 */ 480 */
472 for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) { 481 for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) {
473 if (nau8825_xtalk_baktab[i].reg == NAU8825_REG_HSVOL_CTRL) { 482 if (!cause_cancel && nau8825_xtalk_baktab[i].reg ==
483 NAU8825_REG_HSVOL_CTRL) {
474 /* Ramping up the volume change to reduce pop noise */ 484 /* Ramping up the volume change to reduce pop noise */
475 volume = nau8825_xtalk_baktab[i].def & 485 volume = nau8825_xtalk_baktab[i].def &
476 NAU8825_HPR_VOL_MASK; 486 NAU8825_HPR_VOL_MASK;
@@ -480,6 +490,8 @@ static void nau8825_xtalk_restore(struct nau8825 *nau8825)
480 regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg, 490 regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
481 nau8825_xtalk_baktab[i].def); 491 nau8825_xtalk_baktab[i].def);
482 } 492 }
493
494 nau8825->xtalk_baktab_initialized = false;
483} 495}
484 496
485static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825) 497static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825)
@@ -645,7 +657,7 @@ static void nau8825_xtalk_clean_adc(struct nau8825 *nau8825)
645 NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0); 657 NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0);
646} 658}
647 659
648static void nau8825_xtalk_clean(struct nau8825 *nau8825) 660static void nau8825_xtalk_clean(struct nau8825 *nau8825, bool cause_cancel)
649{ 661{
650 /* Enable internal VCO needed for interruptions */ 662 /* Enable internal VCO needed for interruptions */
651 nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0); 663 nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0);
@@ -661,7 +673,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825)
661 NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK | 673 NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK |
662 NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE); 674 NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE);
663 /* Restore value of specific register for cross talk */ 675 /* Restore value of specific register for cross talk */
664 nau8825_xtalk_restore(nau8825); 676 nau8825_xtalk_restore(nau8825, cause_cancel);
665} 677}
666 678
667static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol) 679static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol)
@@ -780,7 +792,7 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825)
780 dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone); 792 dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone);
781 regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL, 793 regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL,
782 (sidetone << 8) | sidetone); 794 (sidetone << 8) | sidetone);
783 nau8825_xtalk_clean(nau8825); 795 nau8825_xtalk_clean(nau8825, false);
784 nau8825->xtalk_state = NAU8825_XTALK_DONE; 796 nau8825->xtalk_state = NAU8825_XTALK_DONE;
785 break; 797 break;
786 default: 798 default:
@@ -823,7 +835,7 @@ static void nau8825_xtalk_cancel(struct nau8825 *nau8825)
823 if (nau8825->xtalk_enable && nau8825->xtalk_state != 835 if (nau8825->xtalk_enable && nau8825->xtalk_state !=
824 NAU8825_XTALK_DONE) { 836 NAU8825_XTALK_DONE) {
825 cancel_work_sync(&nau8825->xtalk_work); 837 cancel_work_sync(&nau8825->xtalk_work);
826 nau8825_xtalk_clean(nau8825); 838 nau8825_xtalk_clean(nau8825, true);
827 } 839 }
828 /* Reset parameters for cross talk suppression function */ 840 /* Reset parameters for cross talk suppression function */
829 nau8825_sema_reset(nau8825); 841 nau8825_sema_reset(nau8825);
@@ -1713,8 +1725,11 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
1713 nau8825->xtalk_protect = false; 1725 nau8825->xtalk_protect = false;
1714 } 1726 }
1715 /* Startup cross talk detection process */ 1727 /* Startup cross talk detection process */
1716 nau8825->xtalk_state = NAU8825_XTALK_PREPARE; 1728 if (nau8825->xtalk_protect) {
1717 schedule_work(&nau8825->xtalk_work); 1729 nau8825->xtalk_state =
1730 NAU8825_XTALK_PREPARE;
1731 schedule_work(&nau8825->xtalk_work);
1732 }
1718 } else { 1733 } else {
1719 /* The cross talk suppression shouldn't apply 1734 /* The cross talk suppression shouldn't apply
1720 * in the headset with high impedance. Thus, 1735 * in the headset with high impedance. Thus,
@@ -1741,7 +1756,8 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
1741 nau8825->xtalk_event_mask = event_mask; 1756 nau8825->xtalk_event_mask = event_mask;
1742 } 1757 }
1743 } else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) { 1758 } else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) {
1744 if (nau8825->xtalk_enable) 1759 /* crosstalk detection enable and process on going */
1760 if (nau8825->xtalk_enable && nau8825->xtalk_protect)
1745 schedule_work(&nau8825->xtalk_work); 1761 schedule_work(&nau8825->xtalk_work);
1746 clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ; 1762 clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ;
1747 } else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) == 1763 } else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) ==
@@ -2578,6 +2594,7 @@ static int nau8825_i2c_probe(struct i2c_client *i2c,
2578 */ 2594 */
2579 nau8825->xtalk_state = NAU8825_XTALK_DONE; 2595 nau8825->xtalk_state = NAU8825_XTALK_DONE;
2580 nau8825->xtalk_protect = false; 2596 nau8825->xtalk_protect = false;
2597 nau8825->xtalk_baktab_initialized = false;
2581 sema_init(&nau8825->xtalk_sem, 1); 2598 sema_init(&nau8825->xtalk_sem, 1);
2582 INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work); 2599 INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work);
2583 2600
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h
index 199d6ea4dcdc..f7e732125882 100644
--- a/sound/soc/codecs/nau8825.h
+++ b/sound/soc/codecs/nau8825.h
@@ -477,6 +477,7 @@ struct nau8825 {
477 bool xtalk_protect; 477 bool xtalk_protect;
478 int imp_rms[NAU8825_XTALK_IMM]; 478 int imp_rms[NAU8825_XTALK_IMM];
479 int xtalk_enable; 479 int xtalk_enable;
480 bool xtalk_baktab_initialized; /* True if initialized. */
480}; 481};
481 482
482int nau8825_enable_jack_detect(struct snd_soc_codec *codec, 483int nau8825_enable_jack_detect(struct snd_soc_codec *codec,