ASoC: amd: add acp3x i2s ops
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Mon, 12 Nov 2018 05:34:58 +0000 (11:04 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 13 Nov 2018 19:44:08 +0000 (11:44 -0800)
ACP3x has a i2s controller block for playback and capture.
This patch adds ACP3x i2s DAI operations.

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Tested-by: Ravulapati Vishnu vardhan Rao <Vishnuvardhanrao.Ravulapati@amd.com>
Signed-off-by: Vijendar Mukunda <vijendar.mukunda@amd.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/raven/acp3x-pcm-dma.c

index 06c1985..ed2c163 100644 (file)
@@ -423,10 +423,93 @@ static struct snd_pcm_ops acp3x_dma_ops = {
        .mmap = acp3x_dma_mmap,
 };
 
+static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       u32 val = 0;
+       struct i2s_stream_instance *rtd = substream->runtime->private_data;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_U8:
+       case SNDRV_PCM_FORMAT_S8:
+               rtd->xfer_resolution = 0x0;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               rtd->xfer_resolution = 0x02;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               rtd->xfer_resolution = 0x04;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               rtd->xfer_resolution = 0x05;
+               break;
+       default:
+               return -EINVAL;
+       }
+       val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+       val = val | (rtd->xfer_resolution  << 3);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+       else
+               rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+
+       return 0;
+}
+
+static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
+                                int cmd, struct snd_soc_dai *dai)
+{
+       int ret = 0;
+       struct i2s_stream_instance *rtd = substream->runtime->private_data;
+       u32 val, period_bytes;
+
+       period_bytes = frames_to_bytes(substream->runtime,
+                                      substream->runtime->period_size);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       rv_writel(period_bytes, rtd->acp3x_base +
+                                 mmACP_BT_TX_INTR_WATERMARK_SIZE);
+                       val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+                       val = val | BIT(0);
+                       rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+               } else {
+                       rv_writel(period_bytes, rtd->acp3x_base +
+                                 mmACP_BT_RX_INTR_WATERMARK_SIZE);
+                       val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+                       val = val | BIT(0);
+                       rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+               }
+               rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
+                       val = val & ~BIT(0);
+                       rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
+               } else {
+                       val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
+                       val = val & ~BIT(0);
+                       rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
+               }
+               rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
 struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
-       .hw_params = NULL,
-       .trigger   = NULL,
-       .set_fmt = NULL,
+       .hw_params = acp3x_dai_i2s_hwparams,
+       .trigger   = acp3x_dai_i2s_trigger,
 };
 
 static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {