ASoC: fsl_asrc: sound is wrong after suspend/resume
authorZidan Wang <zidan.wang@freescale.com>
Thu, 24 Dec 2015 03:42:11 +0000 (11:42 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 5 Jan 2016 13:19:11 +0000 (13:19 +0000)
The register ASRCFG is volatile, but some bits need to be recovered
after suspend/resume.

Signed-off-by: Zidan Wang <zidan.wang@freescale.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/fsl/fsl_asrc.c
sound/soc/fsl/fsl_asrc.h

index 7b811485a8e5e38674facb28c17836e622c3f2da..73fd2c683b78f65b4e94d8c2e369831be8001af4 100644 (file)
@@ -996,6 +996,9 @@ static int fsl_asrc_suspend(struct device *dev)
 {
        struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
 
+       regmap_read(asrc_priv->regmap, REG_ASRCFG,
+                   &asrc_priv->regcache_cfg);
+
        regcache_cache_only(asrc_priv->regmap, true);
        regcache_mark_dirty(asrc_priv->regmap);
 
@@ -1016,6 +1019,10 @@ static int fsl_asrc_resume(struct device *dev)
        regcache_cache_only(asrc_priv->regmap, false);
        regcache_sync(asrc_priv->regmap);
 
+       regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
+                          ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
+                          ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
+
        /* Restart enabled pairs */
        regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
                           ASRCTR_ASRCEi_ALL_MASK, asrctr);
index 68802cdc3f287b241b1af79f3c994c770b957061..0f163abe4ba37d93bec022afd0842b20423f2361 100644 (file)
 #define ASRCFG_INIRQi                  (1 << ASRCFG_INIRQi_SHIFT(i))
 #define ASRCFG_NDPRi_SHIFT(i)          (18 + i)
 #define ASRCFG_NDPRi_MASK(i)           (1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_NDPRi_ALL_SHIFT         18
+#define ASRCFG_NDPRi_ALL_MASK          (7 << ASRCFG_NDPRi_ALL_SHIFT)
 #define ASRCFG_NDPRi                   (1 << ASRCFG_NDPRi_SHIFT(i))
 #define ASRCFG_POSTMODi_SHIFT(i)       (8 + (i << 2))
 #define ASRCFG_POSTMODi_WIDTH          2
 #define ASRCFG_POSTMODi_MASK(i)                (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_ALL_MASK       (ASRCFG_POSTMODi_MASK(0) | ASRCFG_POSTMODi_MASK(1) | ASRCFG_POSTMODi_MASK(2))
 #define ASRCFG_POSTMOD(i, v)           ((v) << ASRCFG_POSTMODi_SHIFT(i))
 #define ASRCFG_POSTMODi_UP(i)          (0 << ASRCFG_POSTMODi_SHIFT(i))
 #define ASRCFG_POSTMODi_DCON(i)                (1 << ASRCFG_POSTMODi_SHIFT(i))
 #define ASRCFG_PREMODi_SHIFT(i)                (6 + (i << 2))
 #define ASRCFG_PREMODi_WIDTH           2
 #define ASRCFG_PREMODi_MASK(i)         (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_ALL_MASK                (ASRCFG_PREMODi_MASK(0) | ASRCFG_PREMODi_MASK(1) | ASRCFG_PREMODi_MASK(2))
 #define ASRCFG_PREMOD(i, v)            ((v) << ASRCFG_PREMODi_SHIFT(i))
 #define ASRCFG_PREMODi_UP(i)           (0 << ASRCFG_PREMODi_SHIFT(i))
 #define ASRCFG_PREMODi_DCON(i)         (1 << ASRCFG_PREMODi_SHIFT(i))
@@ -434,6 +438,7 @@ struct fsl_asrc_pair {
  * @channel_avail: non-occupied channel numbers
  * @asrc_rate: default sample rate for ASoC Back-Ends
  * @asrc_width: default sample width for ASoC Back-Ends
+ * @regcache_cfg: store register value of REG_ASRCFG
  */
 struct fsl_asrc {
        struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -453,6 +458,8 @@ struct fsl_asrc {
 
        int asrc_rate;
        int asrc_width;
+
+       u32 regcache_cfg;
 };
 
 extern struct snd_soc_platform_driver fsl_asrc_platform;