[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <feed5d33-63a5-4657-b9d8-34bd7f969ed3@amd.com>
Date: Sat, 21 Jun 2025 18:09:51 +0530
From: "Mukunda,Vijendar" <vijendar.mukunda@....com>
To: broonie@...nel.org
Cc: alsa-devel@...a-project.org, lgirdwood@...il.com, perex@...ex.cz,
tiwai@...e.com, Basavaraj.Hiregoudar@....com, Sunil-kumar.Dommati@....com,
venkataprasad.potturu@....com, Syed.SabaKareem@....com,
linux-sound@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] ASoC: amd: ps: fix for soundwire failures during
hibernation exit sequence
On 21/06/25 15:17, Vijendar Mukunda wrote:
> During the hibernate entry sequence, ACP registers will be reset to
> default values and acp ip will be completely powered off including acp
> SoundWire pads. During resume sequence, if acp SoundWire pad keeper enable
> register is not restored along with pad pulldown control register value,
> then SoundWire manager links won't be powered on correctly results in
> peripheral register access failures and completely audio function is
> broken.
>
> Add code to store the acp SoundWire pad keeper enable register and acp pad
> pulldown ctrl register values before entering into suspend state and
> restore the register values during resume sequence based on condition check
> for acp SoundWire pad keeper enable register for ACP6.3, ACP7.0 & ACP7.1
> platforms.
>
> Fixes: 491628388005 ("ASoC: amd: ps: add callback functions for acp pci driver pm ops")
> Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@....com>
> ---
> sound/soc/amd/ps/acp63.h | 5 +++++
> sound/soc/amd/ps/ps-common.c | 18 ++++++++++++++++++
> 2 files changed, 23 insertions(+)
>
> diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h
> index 85feae45c44c..babf2fa7ea27 100644
> --- a/sound/soc/amd/ps/acp63.h
> +++ b/sound/soc/amd/ps/acp63.h
> @@ -82,6 +82,7 @@
> #define ACP63_SDW0_DMA_MAX_STREAMS 6
> #define ACP63_SDW1_DMA_MAX_STREAMS 2
> #define ACP63_P1_AUDIO_TX_THRESHOLD 6
> +#define ACP_SW_PAD_KEEPER_EN 0x0001454
>
> /*
> * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping
> @@ -334,6 +335,8 @@ struct acp_hw_ops {
> * @addr: pci ioremap address
> * @reg_range: ACP reigister range
> * @acp_rev: ACP PCI revision id
> + * @acp_sw_pad_keeper_en: store acp SoundWire pad keeper enable register value
> + * @acp_pad_pulldown_ctrl: store acp pad pulldown control register value
> * @acp63_sdw0-dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire
> * manager-SW0 instance
> * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire
> @@ -367,6 +370,8 @@ struct acp63_dev_data {
> u32 addr;
> u32 reg_range;
> u32 acp_rev;
> + u32 acp_sw_pad_keeper_en;
> + u32 acp_pad_pulldown_ctrl;
> u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
> u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
> u16 acp70_sdw0_dma_intr_stat[ACP70_SDW0_DMA_MAX_STREAMS];
> diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c
> index 1c89fb5fe1da..f18d2a0d83aa 100644
> --- a/sound/soc/amd/ps/ps-common.c
> +++ b/sound/soc/amd/ps/ps-common.c
> @@ -160,6 +160,8 @@ static int __maybe_unused snd_acp63_suspend(struct device *dev)
>
> adata = dev_get_drvdata(dev);
> if (adata->is_sdw_dev) {
> + adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW_PAD_KEEPER_EN);
> + adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
> adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
> if (adata->sdw_en_stat) {
> writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
> @@ -197,6 +199,7 @@ static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
> static int __maybe_unused snd_acp63_resume(struct device *dev)
> {
> struct acp63_dev_data *adata;
> + u32 acp_sw_pad_keeper_en;
> int ret;
>
> adata = dev_get_drvdata(dev);
> @@ -209,6 +212,12 @@ static int __maybe_unused snd_acp63_resume(struct device *dev)
> if (ret)
> dev_err(dev, "ACP init failed\n");
>
> + acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW_PAD_KEEPER_EN);
> + dev_dbg(dev, "ACP_SW_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
> + if (!acp_sw_pad_keeper_en) {
> + writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW_PAD_KEEPER_EN);
> + writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
> + }
> return ret;
> }
>
> @@ -408,6 +417,8 @@ static int __maybe_unused snd_acp70_suspend(struct device *dev)
>
> adata = dev_get_drvdata(dev);
> if (adata->is_sdw_dev) {
> + adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
As register offsets, ACP_SW_PAD_KEEPER_EN & ACP_SW0_PAD_KEEPER_EN
are same, will use the same register macro and post the v2 version.
> + adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
> adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
> if (adata->sdw_en_stat) {
> writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
> @@ -445,6 +456,7 @@ static int __maybe_unused snd_acp70_runtime_resume(struct device *dev)
> static int __maybe_unused snd_acp70_resume(struct device *dev)
> {
> struct acp63_dev_data *adata;
> + u32 acp_sw_pad_keeper_en;
> int ret;
>
> adata = dev_get_drvdata(dev);
> @@ -459,6 +471,12 @@ static int __maybe_unused snd_acp70_resume(struct device *dev)
> if (ret)
> dev_err(dev, "ACP init failed\n");
>
> + acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW_PAD_KEEPER_EN);
> + dev_dbg(dev, "ACP_SW_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
> + if (!acp_sw_pad_keeper_en) {
> + writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
> + writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
> + }
> return ret;
> }
>
Powered by blists - more mailing lists