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, |
