From patchwork Tue Feb 14 16:14:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 13140474 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B1C28C05027 for ; Tue, 14 Feb 2023 16:18:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=mMgFXJ7Wp4XNDV7SrEK0IaaKU1GDP0Xel/MwXcsTk1Q=; b=MIIHFQ/SE2wVRk CTDPqUHKYv26qW7wZXpuNMNrkk1N4DC/AlU4neRqfqV/QxNDaLIq2cRrYHIOkiw3oT4St+9g61nV9 a76NyzRSvMJC0WoraLqUkHCY/Aq8RkzWsF4/ZwX6drWc/o9nUvHeaXmd2AdHL2UYNXlcwQVqq4NAS hnfGMV/pWPxHnU5cjfaUWqx8J1QylrZRKpaXcbtm6QDVOoUPgjC545LtU/pnvMwLEoaGw35HmV60R LSJnLBlPRuEa4vZ9fQH0uaSz9CsRl2oJsGhV+h7lHi0chmDO1GEDhji0/zUddlIkSCdzW25HgOdX/ zUH5YaeJs9YiOIWOFKkw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pRxzq-002lKW-EM; Tue, 14 Feb 2023 16:17:36 +0000 Received: from esa.microchip.iphmx.com ([68.232.154.123]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pRxzc-002lCn-6D for linux-arm-kernel@lists.infradead.org; Tue, 14 Feb 2023 16:17:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1676391440; x=1707927440; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uALPcs3Vx7BPrxo0UgAKw4uy0dcv8BW3De7tw3ZgiME=; b=t4JY7/upbIvwslGvqbQW4m3Qpt3zwsXYc8F9FpbCYchlAnvmn0CSK9lX wVVjWViWUxge5nq2D+DvCKPw9ZYdD4+RhwrYtjcYQpXYA6E1bQ70/msqc PTj3DwPaaccH6mZJLaOfM8rAL4v/wBOz2Mu/4LESwIKgRD2TJ2PBuu9DQ FtP3amgOBggEQ7EFt8/pfWU+6JxCRkZTbEtbd1kbMSJyQLoLO2e5Fc4cS zjz8I0zzgQYqcw5K78acXC6iGrMv8nYEHDDvovVEbdcNXi2V0Tvh1Svgl UvISJ9Muf+Izoi3AyE5cCUVF0/2WP2cnsqWTcuWrVyJopRScwoj6h8txP A==; X-IronPort-AV: E=Sophos;i="5.97,297,1669100400"; d="scan'208";a="196891478" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 14 Feb 2023 09:17:19 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Tue, 14 Feb 2023 09:17:07 -0700 Received: from m18063-ThinkPad-T460p.mchp-main.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Tue, 14 Feb 2023 09:17:03 -0700 From: Claudiu Beznea To: , , , , , , , , CC: , , , , Claudiu Beznea Subject: [PATCH 3/3] ASoC: mchp-pdmc: fix poc noise at capture startup Date: Tue, 14 Feb 2023 18:14:35 +0200 Message-ID: <20230214161435.1088246-4-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230214161435.1088246-1-claudiu.beznea@microchip.com> References: <20230214161435.1088246-1-claudiu.beznea@microchip.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230214_081720_365389_DBD3DCE6 X-CRM114-Status: GOOD ( 18.17 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Microchip PDMC IP doesn't filter microphone noises on startup. By default, it captures data received from digital microphones after the MCHP_PDMC_MR.EN bits are set. Thus when enable is set on PDMC side the digital microphones might not be ready yet and PDMC captures data from then in this time. This data captured is poc noise. To avoid this the software workaround is to the following: 1/ enable PDMC channel 2/ wait 150ms (on SAMA7G5-EK setup) 3/ execute 16 dummy reads from RHR 4/ clear interrupts 5/ enable interrupts 6/ enable DMA channel Fixes: 50291652af52 ("ASoC: atmel: mchp-pdmc: add PDMC driver") Signed-off-by: Claudiu Beznea --- sound/soc/atmel/mchp-pdmc.c | 55 +++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index cf4084dcbd5e..c5f597ebfa47 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -114,6 +114,7 @@ struct mchp_pdmc { struct clk *gclk; u32 pdmcen; u32 suspend_irq; + u32 startup_delay_us; int mic_no; int sinc_order; bool audio_filter_en; @@ -632,6 +633,29 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream, return 0; } +static void mchp_pdmc_noise_filter_workaround(struct mchp_pdmc *dd) +{ + u32 tmp, steps = 16; + + /* + * PDMC doesn't wait for microphones' startup time thus the acquisition + * may start before the microphones are ready leading to poc noises at + * the beginning of capture. To avoid this, we need to wait 50ms (in + * normal startup procedure) or 150 ms (worst case after resume from sleep + * states) after microphones are enabled and then clear the FIFOs (by + * reading the RHR 16 times) and possible interrupts before continuing. + * Also, for this to work the DMA needs to be started after interrupts + * are enabled. + */ + usleep_range(dd->startup_delay_us, dd->startup_delay_us + 5); + + while (steps--) + regmap_read(dd->regmap, MCHP_PDMC_RHR, &tmp); + + /* Clear interrupts. */ + regmap_read(dd->regmap, MCHP_PDMC_ISR, &tmp); +} + static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -644,15 +668,17 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: - /* Enable overrun and underrun error interrupts */ - regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq | - MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR); - dd->suspend_irq = 0; - fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_soc_component_update_bits(cpu, MCHP_PDMC_MR, MCHP_PDMC_MR_PDMCEN_MASK, dd->pdmcen); + + mchp_pdmc_noise_filter_workaround(dd); + + /* Enable interrupts. */ + regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq | + MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR); + dd->suspend_irq = 0; break; case SNDRV_PCM_TRIGGER_SUSPEND: regmap_read(dd->regmap, MCHP_PDMC_IMR, &dd->suspend_irq); @@ -796,6 +822,7 @@ static bool mchp_pdmc_readable_reg(struct device *dev, unsigned int reg) case MCHP_PDMC_CFGR: case MCHP_PDMC_IMR: case MCHP_PDMC_ISR: + case MCHP_PDMC_RHR: case MCHP_PDMC_VER: return true; default: @@ -817,6 +844,17 @@ static bool mchp_pdmc_writeable_reg(struct device *dev, unsigned int reg) } } +static bool mchp_pdmc_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MCHP_PDMC_ISR: + case MCHP_PDMC_RHR: + return true; + default: + return false; + } +} + static bool mchp_pdmc_precious_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -836,6 +874,7 @@ static const struct regmap_config mchp_pdmc_regmap_config = { .readable_reg = mchp_pdmc_readable_reg, .writeable_reg = mchp_pdmc_writeable_reg, .precious_reg = mchp_pdmc_precious_reg, + .volatile_reg = mchp_pdmc_volatile_reg, .cache_type = REGCACHE_FLAT, }; @@ -918,6 +957,11 @@ static int mchp_pdmc_dt_init(struct mchp_pdmc *dd) dd->channel_mic_map[i].clk_edge = edge; } + ret = of_property_read_u32(np, "microchip,startup-delay-us", + &dd->startup_delay_us); + if (ret) + dd->startup_delay_us = 150000; + return 0; } @@ -941,6 +985,7 @@ static int mchp_pdmc_process(struct snd_pcm_substream *substream, static struct snd_dmaengine_pcm_config mchp_pdmc_config = { .process = mchp_pdmc_process, .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .start_dma_last = 1, }; static int mchp_pdmc_runtime_suspend(struct device *dev)