MLK-15960-3: ASoC: fsl_spdif: refine pm runtime function
authorShengjiu Wang <shengjiu.wang@freescale.com>
Wed, 12 Jul 2017 10:01:07 +0000 (18:01 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:33:35 +0000 (15:33 -0500)
In imx8qm/imx8qxp, the power domain of IP is enabled when
pm_runtime_get_sync() is called, and disabled when pm_runtime
_put_sync() is called. when power domain is disabled, the value
of registers will lost, so we need to use the regcache_sync()
to restore the registers in fsl_spdif_runtime_resume.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
sound/soc/fsl/fsl_spdif.c

index f99934e..2d39362 100644 (file)
@@ -493,8 +493,6 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
        int i;
        int ret;
 
-       pm_runtime_get_sync(cpu_dai->dev);
-
        /* Reset module and interrupts only for first initialization */
        if (!cpu_dai->active) {
                ret = clk_prepare_enable(spdif_priv->coreclk);
@@ -604,7 +602,6 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
                clk_disable_unprepare(spdif_priv->coreclk);
        }
 
-       pm_runtime_put_sync(cpu_dai->dev);
 }
 
 static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
@@ -1437,6 +1434,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
 
+       regcache_cache_only(spdif_priv->regmap, true);
        /* Register with ASoC */
        dev_set_drvdata(&pdev->dev, spdif_priv);
 
@@ -1485,12 +1483,27 @@ static int fsl_spdif_resume(struct device *dev)
 #ifdef CONFIG_PM
 static int fsl_spdif_runtime_resume(struct device *dev)
 {
+       struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
+
        request_bus_freq(BUS_FREQ_HIGH);
-       return 0;
+
+       regcache_cache_only(spdif_priv->regmap, false);
+       regcache_mark_dirty(spdif_priv->regmap);
+
+       regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC,
+                       SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK,
+                       spdif_priv->regcache_srpc);
+
+       return regcache_sync(spdif_priv->regmap);
 }
 
 static int fsl_spdif_runtime_suspend(struct device *dev)
 {
+       struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
+
+       regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC,
+                       &spdif_priv->regcache_srpc);
+       regcache_cache_only(spdif_priv->regmap, true);
        release_bus_freq(BUS_FREQ_HIGH);
        return 0;
 }