Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: AMD: Restore PME_EN state at Power On

PME_EN state needs to restored to the value set by fmw.
For the devices which are not using I2S wake event which gets
enabled by PME_EN bit, keeping PME_EN enabled burns considerable amount
of power as it blocks low power state.
For the devices using I2S wake event, PME_EN gets enabled in fmw and the
state should be maintained after ACP Power On.

Signed-off-by: Akshu Agrawal <akshu.agrawal@amd.com>
Link: https://lore.kernel.org/r/20200724195600.11798-1-akshu.agrawal@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Akshu Agrawal and committed by
Mark Brown
1255296c 3aecfc72

+13 -8
+13 -8
sound/soc/amd/raven/pci-acp3x.c
··· 19 19 bool acp3x_audio_mode; 20 20 struct resource *res; 21 21 struct platform_device *pdev[ACP3x_DEVS]; 22 + u32 pme_en; 22 23 }; 23 24 24 - static int acp3x_power_on(void __iomem *acp3x_base) 25 + static int acp3x_power_on(struct acp3x_dev_data *adata) 25 26 { 27 + void __iomem *acp3x_base = adata->acp3x_base; 26 28 u32 val; 27 29 int timeout; 28 30 ··· 41 39 while (++timeout < 500) { 42 40 val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); 43 41 if (!val) { 44 - /* Set PME_EN as after ACP power On, 45 - * PME_EN gets cleared 42 + /* ACP power On clears PME_EN. 43 + * Restore the value to its prior state 46 44 */ 47 - rv_writel(0x1, acp3x_base + mmACP_PME_EN); 45 + rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN); 48 46 return 0; 49 47 } 50 48 udelay(1); ··· 76 74 return -ETIMEDOUT; 77 75 } 78 76 79 - static int acp3x_init(void __iomem *acp3x_base) 77 + static int acp3x_init(struct acp3x_dev_data *adata) 80 78 { 79 + void __iomem *acp3x_base = adata->acp3x_base; 81 80 int ret; 82 81 83 82 /* power on */ 84 - ret = acp3x_power_on(acp3x_base); 83 + ret = acp3x_power_on(adata); 85 84 if (ret) { 86 85 pr_err("ACP3x power on failed\n"); 87 86 return ret; ··· 154 151 } 155 152 pci_set_master(pci); 156 153 pci_set_drvdata(pci, adata); 157 - ret = acp3x_init(adata->acp3x_base); 154 + /* Save ACP_PME_EN state */ 155 + adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN); 156 + ret = acp3x_init(adata); 158 157 if (ret) 159 158 goto disable_msi; 160 159 ··· 279 274 struct acp3x_dev_data *adata; 280 275 281 276 adata = dev_get_drvdata(dev); 282 - ret = acp3x_init(adata->acp3x_base); 277 + ret = acp3x_init(adata); 283 278 if (ret) { 284 279 dev_err(dev, "ACP init failed\n"); 285 280 return ret;