diff options
-rw-r--r-- | sound/soc/codecs/nau8825.c | 45 | ||||
-rw-r--r-- | sound/soc/codecs/nau8825.h | 1 |
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 */ |
196 | static struct reg_default nau8825_xtalk_baktab[] = { | 196 | static 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 | ||
203 | static const unsigned short logtable[256] = { | 203 | static 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 | ||
464 | static void nau8825_xtalk_restore(struct nau8825 *nau8825) | 469 | static 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 | ||
485 | static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825) | 497 | static 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 | ||
648 | static void nau8825_xtalk_clean(struct nau8825 *nau8825) | 660 | static 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 | ||
667 | static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol) | 679 | static 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 | ||
482 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, | 483 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, |