diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h index 39e19de120ba92..bac2fe9c1dc3a0 100644 --- a/sound/soc/sof/amd/acp-dsp-offset.h +++ b/sound/soc/sof/amd/acp-dsp-offset.h @@ -102,4 +102,7 @@ /* Cache window registers */ #define ACP_DSP0_CACHE_OFFSET0 0x0420 #define ACP_DSP0_CACHE_SIZE0 0x0424 + +#define ACP_SW0_EN 0x3000 +#define ACP_SW1_EN 0x3C00 #endif diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index c02b0da9d5eaa2..d79b8bc27f945e 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -468,6 +468,31 @@ static int acp_reset(struct snd_sof_dev *sdev) return ret; } +static int acp_dsp_reset(struct snd_sof_dev *sdev) +{ + unsigned int val; + int ret; + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SOFT_RESET, ACP_DSP_ASSERT_RESET); + + ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SOFT_RESET, val, + val & ACP_DSP_SOFT_RESET_DONE_MASK, + ACP_REG_POLL_INTERVAL, ACP_REG_POLL_TIMEOUT_US); + if (ret < 0) { + dev_err(sdev->dev, "timeout asserting reset\n"); + return ret; + } + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SOFT_RESET, ACP_DSP_RELEASE_RESET); + + ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SOFT_RESET, val, !val, + ACP_REG_POLL_INTERVAL, ACP_REG_POLL_TIMEOUT_US); + if (ret < 0) + dev_err(sdev->dev, "timeout in releasing reset\n"); + + return ret; +} + static int acp_init(struct snd_sof_dev *sdev) { int ret; @@ -484,10 +509,28 @@ static int acp_init(struct snd_sof_dev *sdev) return acp_reset(sdev); } +static bool check_acp_sdw_enable_status(struct snd_sof_dev *sdev) +{ + u32 sdw0_en, sdw1_en; + struct acp_dev_data *acp_data; + + acp_data = sdev->pdata->hw_pdata; + if (!acp_data->sdw) + return false; + + sdw0_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW0_EN); + sdw1_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW1_EN); + acp_data->sdw_en_stat = sdw0_en || sdw1_en; + return acp_data->sdw_en_stat; +} + int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state) { int ret; + if (check_acp_sdw_enable_status(sdev)) + return acp_dsp_reset(sdev); + ret = acp_reset(sdev); if (ret) { dev_err(sdev->dev, "ACP Reset failed\n"); @@ -503,13 +546,19 @@ EXPORT_SYMBOL_NS(amd_sof_acp_suspend, SND_SOC_SOF_AMD_COMMON); int amd_sof_acp_resume(struct snd_sof_dev *sdev) { int ret; + struct acp_dev_data *acp_data; - ret = acp_init(sdev); - if (ret) { - dev_err(sdev->dev, "ACP Init failed\n"); - return ret; + acp_data = sdev->pdata->hw_pdata; + if (!acp_data->sdw_en_stat) { + ret = acp_init(sdev); + if (ret) { + dev_err(sdev->dev, "ACP Init failed\n"); + return ret; + } + return acp_memory_init(sdev); + } else { + return acp_dsp_reset(sdev); } - return acp_memory_init(sdev); } EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 238a393e1ba75c..af255ea09dadd8 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -32,6 +32,9 @@ #define ACP_ASSERT_RESET 0x01 #define ACP_RELEASE_RESET 0x00 #define ACP_SOFT_RESET_DONE_MASK 0x00010001 +#define ACP_DSP_ASSERT_RESET 0x04 +#define ACP_DSP_RELEASE_RESET 0x00 +#define ACP_DSP_SOFT_RESET_DONE_MASK 0x00050004 #define ACP_DSP_INTR_EN_MASK 0x00000001 #define ACP3X_SRAM_PTE_OFFSET 0x02050000 @@ -238,6 +241,7 @@ struct acp_dev_data { bool enable_fw_debug; bool is_dram_in_use; bool is_sram_in_use; + bool sdw_en_stat; }; void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes);