ASoC: amd: vangogh: refactor i2s master mode clock sequence code
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Wed, 23 Feb 2022 07:19:31 +0000 (12:49 +0530)
committerMark Brown <broonie@kernel.org>
Thu, 24 Feb 2022 02:04:26 +0000 (02:04 +0000)
Refactor I2S Master mode clock programming sequence code.
This will also fix the i2s clocks restore issue during system level
resume.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://lore.kernel.org/r/20220223071959.13539-2-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/vangogh/acp5x-i2s.c
sound/soc/amd/vangogh/acp5x.h

index 002db39..59a98f8 100644 (file)
@@ -88,10 +88,9 @@ static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
        struct snd_soc_card *card;
        struct acp5x_platform_info *pinfo;
        struct i2s_dev_data *adata;
-       union acp_i2stdm_mstrclkgen mclkgen;
 
        u32 val;
-       u32 reg_val, frmt_reg, master_reg;
+       u32 reg_val, frmt_reg;
        u32 lrclk_div_val, bclk_div_val;
 
        lrclk_div_val = 0;
@@ -160,20 +159,6 @@ static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
        acp_writel(val, rtd->acp5x_base + reg_val);
 
        if (adata->master_mode) {
-               switch (rtd->i2s_instance) {
-               case I2S_HS_INSTANCE:
-                       master_reg = ACP_I2STDM2_MSTRCLKGEN;
-                       break;
-               case I2S_SP_INSTANCE:
-               default:
-                       master_reg = ACP_I2STDM0_MSTRCLKGEN;
-                       break;
-               }
-               mclkgen.bits.i2stdm_master_mode = 0x1;
-               if (adata->tdm_mode)
-                       mclkgen.bits.i2stdm_format_mode = 0x01;
-               else
-                       mclkgen.bits.i2stdm_format_mode = 0x0;
                switch (params_format(params)) {
                case SNDRV_PCM_FORMAT_S16_LE:
                        switch (params_rate(params)) {
@@ -238,9 +223,8 @@ static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
                default:
                        return -EINVAL;
                }
-               mclkgen.bits.i2stdm_bclk_div_val = bclk_div_val;
-               mclkgen.bits.i2stdm_lrclk_div_val = lrclk_div_val;
-               acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);
+               rtd->lrclk_div = lrclk_div_val;
+               rtd->bclk_div = bclk_div_val;
        }
        return 0;
 }
@@ -249,9 +233,11 @@ static int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
                             int cmd, struct snd_soc_dai *dai)
 {
        struct i2s_stream_instance *rtd;
+       struct i2s_dev_data *adata;
        u32 ret, val, period_bytes, reg_val, ier_val, water_val;
        u32 buf_size, buf_reg;
 
+       adata = snd_soc_dai_get_drvdata(dai);
        rtd = substream->runtime->private_data;
        period_bytes = frames_to_bytes(substream->runtime,
                                       substream->runtime->period_size);
@@ -300,6 +286,8 @@ static int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
                }
                acp_writel(period_bytes, rtd->acp5x_base + water_val);
                acp_writel(buf_size, rtd->acp5x_base + buf_reg);
+               if (adata->master_mode)
+                       acp5x_set_i2s_clk(adata, rtd);
                val = acp_readl(rtd->acp5x_base + reg_val);
                val = val | BIT(0);
                acp_writel(val, rtd->acp5x_base + reg_val);
index fe5e1fa..b85d3ee 100644 (file)
@@ -105,6 +105,8 @@ struct i2s_stream_instance {
        dma_addr_t dma_addr;
        u64 bytescount;
        void __iomem *acp5x_base;
+       u32 lrclk_div;
+       u32 bclk_div;
 };
 
 union acp_dma_count {
@@ -191,3 +193,30 @@ static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
        }
        return byte_count.bytescount;
 }
+
+static inline void acp5x_set_i2s_clk(struct i2s_dev_data *adata,
+                                    struct i2s_stream_instance *rtd)
+{
+       union acp_i2stdm_mstrclkgen mclkgen;
+       u32 master_reg;
+
+       switch (rtd->i2s_instance) {
+       case I2S_HS_INSTANCE:
+               master_reg = ACP_I2STDM2_MSTRCLKGEN;
+               break;
+       case I2S_SP_INSTANCE:
+       default:
+               master_reg = ACP_I2STDM0_MSTRCLKGEN;
+               break;
+       }
+
+       mclkgen.bits.i2stdm_master_mode = 0x1;
+       if (adata->tdm_mode)
+               mclkgen.bits.i2stdm_format_mode = 0x01;
+       else
+               mclkgen.bits.i2stdm_format_mode = 0x00;
+
+       mclkgen.bits.i2stdm_bclk_div_val = rtd->bclk_div;
+       mclkgen.bits.i2stdm_lrclk_div_val = rtd->lrclk_div;
+       acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);
+}