From patchwork Fri Dec 1 02:01:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AS50 KCHSU0 X-Patchwork-Id: 10086029 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7838660327 for ; Fri, 1 Dec 2017 02:10:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 655FA2A4E4 for ; Fri, 1 Dec 2017 02:10:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5A5462A4E8; Fri, 1 Dec 2017 02:10:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0AB7A2A4E6 for ; Fri, 1 Dec 2017 02:10:05 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id DFA29266E5F; Fri, 1 Dec 2017 03:01:51 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 00A18267B6B; Fri, 1 Dec 2017 03:01:50 +0100 (CET) Received: from maillog.nuvoton.com (maillog.nuvoton.com [202.39.227.15]) by alsa0.perex.cz (Postfix) with ESMTP id E419D266DF0 for ; Fri, 1 Dec 2017 03:01:46 +0100 (CET) Received: from NTHCCAS01.nuvoton.com (nthccas01.nuvoton.com [10.1.8.28]) by maillog.nuvoton.com (Postfix) with ESMTP id B44711C80A4F; Fri, 1 Dec 2017 10:01:42 +0800 (CST) Received: from NTHCML01A.nuvoton.com (10.1.8.177) by NTHCCAS01.nuvoton.com (10.1.8.28) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Fri, 1 Dec 2017 10:01:42 +0800 Received: from NTHCCAS01.nuvoton.com (10.1.8.28) by NTHCML01A.nuvoton.com (10.1.8.177) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Fri, 1 Dec 2017 10:01:42 +0800 Received: from localhost.localdomain (10.4.36.27) by NTHCCAS01.nuvoton.com (10.1.12.25) with Microsoft SMTP Server id 15.0.1130.7 via Frontend Transport; Fri, 1 Dec 2017 10:01:42 +0800 From: John Hsu To: Date: Fri, 1 Dec 2017 10:01:37 +0800 Message-ID: <1512093697-11043-1-git-send-email-KCHSU0@nuvoton.com> X-Mailer: git-send-email 2.6.4 MIME-Version: 1.0 Cc: alsa-devel@alsa-project.org, cychiang@google.com, anatol.pomozov@gmail.com, WTLI@nuvoton.com, wuchengli@google.com, John Hsu , lgirdwood@gmail.com, YHCHuang@nuvoton.com, mac.chiang@intel.com, CTLIN0@nuvoton.com, mhkuo@nuvoton.com Subject: [alsa-devel] ASoC: nau8825: improve crosstalk measurement protection X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP The sequence of crosstalk measurement is not robust. The driver add more protections to make it stronger. The improvements as follows: (1)Give backup table the default value. The values are the same with the default of hardware registers. The impact will decline once restoring the backup table in the wrong way. (2)Add xtalk_baktab_initialized flag. The flag can keep the initiation status of backup table. It helps to backup and restore the backup-table correctly. (3)Add cancel parameter in the restore function. The volume ramping should do in crosstalk DONE state only. Otherwise, the delay action is not allowed because the restore may happen during the jack eject interruption. (4)Add xtalk_protect condition check before scheduling work in ISR. It makes sure the semaphore hold during the crosstalk measurement. The sequence is still under protection from playback interference. Signed-off-by: John Hsu --- sound/soc/codecs/nau8825.c | 45 +++++++++++++++++++++++++++++++-------------- 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 603cd72..7947b11 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[] = { /* register backup table when cross talk detection */ static struct reg_default nau8825_xtalk_baktab[] = { - { NAU8825_REG_ADC_DGAIN_CTRL, 0 }, + { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf }, { NAU8825_REG_HSVOL_CTRL, 0 }, - { NAU8825_REG_DACL_CTRL, 0 }, - { NAU8825_REG_DACR_CTRL, 0 }, + { NAU8825_REG_DACL_CTRL, 0x00cf }, + { NAU8825_REG_DACR_CTRL, 0x02cf }, }; static const unsigned short logtable[256] = { @@ -454,22 +454,32 @@ static void nau8825_xtalk_backup(struct nau8825 *nau8825) { int i; + if (nau8825->xtalk_baktab_initialized) + return; + /* Backup some register values to backup table */ for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg, &nau8825_xtalk_baktab[i].def); + + nau8825->xtalk_baktab_initialized = true; } -static void nau8825_xtalk_restore(struct nau8825 *nau8825) +static void nau8825_xtalk_restore(struct nau8825 *nau8825, bool cause_cancel) { int i, volume; + if (!nau8825->xtalk_baktab_initialized) + return; + /* Restore register values from backup table; When the driver restores - * the headphone volumem, it needs recover to original level gradually - * with 3dB per step for less pop noise. + * the headphone volume in XTALK_DONE state, it needs recover to + * original level gradually with 3dB per step for less pop noise. + * Otherwise, the restore should do ASAP. */ for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) { - if (nau8825_xtalk_baktab[i].reg == NAU8825_REG_HSVOL_CTRL) { + if (!cause_cancel && nau8825_xtalk_baktab[i].reg == + NAU8825_REG_HSVOL_CTRL) { /* Ramping up the volume change to reduce pop noise */ volume = nau8825_xtalk_baktab[i].def & NAU8825_HPR_VOL_MASK; @@ -479,6 +489,8 @@ static void nau8825_xtalk_restore(struct nau8825 *nau8825) regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg, nau8825_xtalk_baktab[i].def); } + + nau8825->xtalk_baktab_initialized = false; } static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825) @@ -644,7 +656,7 @@ static void nau8825_xtalk_clean_adc(struct nau8825 *nau8825) NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0); } -static void nau8825_xtalk_clean(struct nau8825 *nau8825) +static void nau8825_xtalk_clean(struct nau8825 *nau8825, bool cause_cancel) { /* Enable internal VCO needed for interruptions */ nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0); @@ -660,7 +672,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825) NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE); /* Restore value of specific register for cross talk */ - nau8825_xtalk_restore(nau8825); + nau8825_xtalk_restore(nau8825, cause_cancel); } static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol) @@ -779,7 +791,7 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825) dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone); regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL, (sidetone << 8) | sidetone); - nau8825_xtalk_clean(nau8825); + nau8825_xtalk_clean(nau8825, false); nau8825->xtalk_state = NAU8825_XTALK_DONE; break; default: @@ -822,7 +834,7 @@ static void nau8825_xtalk_cancel(struct nau8825 *nau8825) if (nau8825->xtalk_enable && nau8825->xtalk_state != NAU8825_XTALK_DONE) { cancel_work_sync(&nau8825->xtalk_work); - nau8825_xtalk_clean(nau8825); + nau8825_xtalk_clean(nau8825, true); } /* Reset parameters for cross talk suppression function */ nau8825_sema_reset(nau8825); @@ -1705,8 +1717,11 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) nau8825->xtalk_protect = false; } /* Startup cross talk detection process */ - nau8825->xtalk_state = NAU8825_XTALK_PREPARE; - schedule_work(&nau8825->xtalk_work); + if (nau8825->xtalk_protect) { + nau8825->xtalk_state = + NAU8825_XTALK_PREPARE; + schedule_work(&nau8825->xtalk_work); + } } else { /* The cross talk suppression shouldn't apply * in the headset with high impedance. Thus, @@ -1733,7 +1748,8 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) nau8825->xtalk_event_mask = event_mask; } } else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) { - if (nau8825->xtalk_enable) + /* crosstalk detection enable and process on going */ + if (nau8825->xtalk_enable && nau8825->xtalk_protect) schedule_work(&nau8825->xtalk_work); clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ; } else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) == @@ -2570,6 +2586,7 @@ static int nau8825_i2c_probe(struct i2c_client *i2c, */ nau8825->xtalk_state = NAU8825_XTALK_DONE; nau8825->xtalk_protect = false; + nau8825->xtalk_baktab_initialized = false; sema_init(&nau8825->xtalk_sem, 1); INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work); diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 199d6ea..f7e7321 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -477,6 +477,7 @@ struct nau8825 { bool xtalk_protect; int imp_rms[NAU8825_XTALK_IMM]; int xtalk_enable; + bool xtalk_baktab_initialized; /* True if initialized. */ }; int nau8825_enable_jack_detect(struct snd_soc_codec *codec,