ASoC: fsl_esai: Wrap some operations to be functions
authorShengjiu Wang <shengjiu.wang@nxp.com>
Thu, 11 Jul 2019 10:49:45 +0000 (18:49 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 22 Jul 2019 12:10:39 +0000 (13:10 +0100)
Extract the operation to be functions, to improve the
readability.

In this patch, fsl_esai_hw_init, fsl_esai_register_restore,
fsl_esai_trigger_start and fsl_esai_trigger_stop are
extracted.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/804d7e75ae7e06a913479912b578b3538ca7cd3f.1562842206.git.shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/fsl/fsl_esai.c

index 10d2210..ab460d6 100644 (file)
@@ -35,6 +35,7 @@
  * @fifo_depth: depth of tx/rx FIFO
  * @slot_width: width of each DAI slot
  * @slots: number of slots
+ * @channels: channel num for tx or rx
  * @hck_rate: clock rate of desired HCKx clock
  * @sck_rate: clock rate of desired SCKx clock
  * @hck_dir: the direction of HCKx pads
@@ -57,6 +58,7 @@ struct fsl_esai {
        u32 slots;
        u32 tx_mask;
        u32 rx_mask;
+       u32 channels[2];
        u32 hck_rate[2];
        u32 sck_rate[2];
        bool hck_dir[2];
@@ -543,64 +545,132 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int fsl_esai_hw_init(struct fsl_esai *esai_priv)
+{
+       struct platform_device *pdev = esai_priv->pdev;
+       int ret;
+
+       /* Reset ESAI unit */
+       ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
+                                ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
+                                ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * We need to enable ESAI so as to access some of its registers.
+        * Otherwise, we would fail to dump regmap from user space.
+        */
+       ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
+                                ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
+                                ESAI_ECR_ESAIEN);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
+               return ret;
+       }
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
+                          ESAI_PRRC_PDC_MASK, 0);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
+                          ESAI_PCRC_PC_MASK, 0);
+
+       return 0;
+}
+
+static int fsl_esai_register_restore(struct fsl_esai *esai_priv)
+{
+       int ret;
+
+       /* FIFO reset for safety */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR,
+                          ESAI_xFCR_xFR, ESAI_xFCR_xFR);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR,
+                          ESAI_xFCR_xFR, ESAI_xFCR_xFR);
+
+       regcache_mark_dirty(esai_priv->regmap);
+       ret = regcache_sync(esai_priv->regmap);
+       if (ret)
+               return ret;
+
+       /* FIFO reset done */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
+
+       return 0;
+}
+
+static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx)
+{
+       u8 i, channels = esai_priv->channels[tx];
+       u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
+       u32 mask;
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                          ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
+
+       /* Write initial words reqiured by ESAI as normal procedure */
+       for (i = 0; tx && i < channels; i++)
+               regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
+
+       /*
+        * When set the TE/RE in the end of enablement flow, there
+        * will be channel swap issue for multi data line case.
+        * In order to workaround this issue, we switch the bit
+        * enablement sequence to below sequence
+        * 1) clear the xSMB & xSMA: which is done in probe and
+        *                           stop state.
+        * 2) set TE/RE
+        * 3) set xSMB
+        * 4) set xSMA:  xSMA is the last one in this flow, which
+        *               will trigger esai to start.
+        */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+                          tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
+                          tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
+       mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+                          ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
+}
+
+static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx)
+{
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+                          tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+                          ESAI_xSMA_xS_MASK, 0);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+                          ESAI_xSMB_xS_MASK, 0);
+
+       /* Disable and reset FIFO */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                          ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                          ESAI_xFCR_xFR, 0);
+}
+
 static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
                            struct snd_soc_dai *dai)
 {
        struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-       u8 i, channels = substream->runtime->channels;
-       u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
-       u32 mask;
+
+       esai_priv->channels[tx] = substream->runtime->channels;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
-                                  ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
-
-               /* Write initial words reqiured by ESAI as normal procedure */
-               for (i = 0; tx && i < channels; i++)
-                       regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
-
-               /*
-                * When set the TE/RE in the end of enablement flow, there
-                * will be channel swap issue for multi data line case.
-                * In order to workaround this issue, we switch the bit
-                * enablement sequence to below sequence
-                * 1) clear the xSMB & xSMA: which is done in probe and
-                *                           stop state.
-                * 2) set TE/RE
-                * 3) set xSMB
-                * 4) set xSMA:  xSMA is the last one in this flow, which
-                *               will trigger esai to start.
-                */
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
-                                  tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
-                                  tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
-               mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
-
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
-                                  ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
-                                  ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
-
+               fsl_esai_trigger_start(esai_priv, tx);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
-                                  tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
-                                  ESAI_xSMA_xS_MASK, 0);
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
-                                  ESAI_xSMB_xS_MASK, 0);
-
-               /* Disable and reset FIFO */
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
-                                  ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
-                                  ESAI_xFCR_xFR, 0);
+               fsl_esai_trigger_stop(esai_priv, tx);
                break;
        default:
                return -EINVAL;
@@ -866,22 +936,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
 
        dev_set_drvdata(&pdev->dev, esai_priv);
 
-       /* Reset ESAI unit */
-       ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
-               return ret;
-       }
-
-       /*
-        * We need to enable ESAI so as to access some of its registers.
-        * Otherwise, we would fail to dump regmap from user space.
-        */
-       ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
+       ret = fsl_esai_hw_init(esai_priv);
+       if (ret)
                return ret;
-       }
 
        esai_priv->tx_mask = 0xFFFFFFFF;
        esai_priv->rx_mask = 0xFFFFFFFF;
@@ -955,20 +1012,10 @@ static int fsl_esai_runtime_resume(struct device *dev)
 
        regcache_cache_only(esai->regmap, false);
 
-       /* FIFO reset for safety */
-       regmap_update_bits(esai->regmap, REG_ESAI_TFCR,
-                          ESAI_xFCR_xFR, ESAI_xFCR_xFR);
-       regmap_update_bits(esai->regmap, REG_ESAI_RFCR,
-                          ESAI_xFCR_xFR, ESAI_xFCR_xFR);
-
-       ret = regcache_sync(esai->regmap);
+       ret = fsl_esai_register_restore(esai);
        if (ret)
                goto err_regcache_sync;
 
-       /* FIFO reset done */
-       regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
-       regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
-
        return 0;
 
 err_regcache_sync:
@@ -991,7 +1038,6 @@ static int fsl_esai_runtime_suspend(struct device *dev)
        struct fsl_esai *esai = dev_get_drvdata(dev);
 
        regcache_cache_only(esai->regmap, true);
-       regcache_mark_dirty(esai->regmap);
 
        if (!IS_ERR(esai->fsysclk))
                clk_disable_unprepare(esai->fsysclk);