ASoC: AMD: Restore PME_EN state at Power On
authorAkshu Agrawal <akshu.agrawal@amd.com>
Fri, 24 Jul 2020 19:55:52 +0000 (01:25 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 27 Jul 2020 13:21:08 +0000 (14:21 +0100)
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>
sound/soc/amd/raven/pci-acp3x.c

index ebf4388..31b797c 100644 (file)
@@ -19,10 +19,12 @@ struct acp3x_dev_data {
        bool acp3x_audio_mode;
        struct resource *res;
        struct platform_device *pdev[ACP3x_DEVS];
+       u32 pme_en;
 };
 
-static int acp3x_power_on(void __iomem *acp3x_base)
+static int acp3x_power_on(struct acp3x_dev_data *adata)
 {
+       void __iomem *acp3x_base = adata->acp3x_base;
        u32 val;
        int timeout;
 
@@ -39,10 +41,10 @@ static int acp3x_power_on(void __iomem *acp3x_base)
        while (++timeout < 500) {
                val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
                if (!val) {
-                       /* Set PME_EN as after ACP power On,
-                        * PME_EN gets cleared
+                       /* ACP power On clears PME_EN.
+                        * Restore the value to its prior state
                         */
-                       rv_writel(0x1, acp3x_base + mmACP_PME_EN);
+                       rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN);
                        return 0;
                }
                udelay(1);
@@ -74,12 +76,13 @@ static int acp3x_reset(void __iomem *acp3x_base)
        return -ETIMEDOUT;
 }
 
-static int acp3x_init(void __iomem *acp3x_base)
+static int acp3x_init(struct acp3x_dev_data *adata)
 {
+       void __iomem *acp3x_base = adata->acp3x_base;
        int ret;
 
        /* power on */
-       ret = acp3x_power_on(acp3x_base);
+       ret = acp3x_power_on(adata);
        if (ret) {
                pr_err("ACP3x power on failed\n");
                return ret;
@@ -151,7 +154,9 @@ static int snd_acp3x_probe(struct pci_dev *pci,
        }
        pci_set_master(pci);
        pci_set_drvdata(pci, adata);
-       ret = acp3x_init(adata->acp3x_base);
+       /* Save ACP_PME_EN state */
+       adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN);
+       ret = acp3x_init(adata);
        if (ret)
                goto disable_msi;
 
@@ -274,7 +279,7 @@ static int snd_acp3x_resume(struct device *dev)
        struct acp3x_dev_data *adata;
 
        adata = dev_get_drvdata(dev);
-       ret = acp3x_init(adata->acp3x_base);
+       ret = acp3x_init(adata);
        if (ret) {
                dev_err(dev, "ACP init failed\n");
                return ret;