^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // AMD ALSA SoC PCM Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //Copyright 2016 Advanced Micro Devices, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/soc-dai.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "acp3x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define DRV_NAME "acp3x_i2s_playcap"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct i2s_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) adata = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) adata->tdm_mode = TDM_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case SND_SOC_DAIFMT_DSP_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) adata->tdm_mode = TDM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 tx_mask, u32 rx_mask, int slots, int slot_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct i2s_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 frm_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u16 slot_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) adata = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* These values are as per Hardware Spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) switch (slot_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case SLOT_WIDTH_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) slot_len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case SLOT_WIDTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) slot_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) case SLOT_WIDTH_24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) slot_len = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case SLOT_WIDTH_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) slot_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) adata->tdm_fmt = frm_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct i2s_stream_instance *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct snd_soc_pcm_runtime *prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct snd_soc_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct acp3x_platform_info *pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct i2s_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 reg_val, frmt_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) prtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rtd = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) card = prtd->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) adata = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pinfo = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (pinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) rtd->i2s_instance = pinfo->play_i2s_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) rtd->i2s_instance = pinfo->cap_i2s_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* These values are as per Hardware Spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case SNDRV_PCM_FORMAT_U8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case SNDRV_PCM_FORMAT_S8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) rtd->xfer_resolution = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) rtd->xfer_resolution = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case SNDRV_PCM_FORMAT_S24_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) rtd->xfer_resolution = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) rtd->xfer_resolution = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) reg_val = mmACP_BTTDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) frmt_reg = mmACP_BTTDM_TXFRMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) reg_val = mmACP_I2STDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) frmt_reg = mmACP_I2STDM_TXFRMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) reg_val = mmACP_BTTDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) frmt_reg = mmACP_BTTDM_RXFRMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) reg_val = mmACP_I2STDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) frmt_reg = mmACP_I2STDM_RXFRMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (adata->tdm_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) val = rv_readl(rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) rv_writel(val | 0x2, rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) rv_writel(adata->tdm_fmt, rtd->acp3x_base + frmt_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) val = rv_readl(rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) val = val | (rtd->xfer_resolution << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) rv_writel(val, rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int cmd, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct i2s_stream_instance *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u32 ret, val, period_bytes, reg_val, ier_val, water_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u32 buf_size, buf_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rtd = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) period_bytes = frames_to_bytes(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) substream->runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) buf_size = frames_to_bytes(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) substream->runtime->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) rtd->bytescount = acp_get_byte_count(rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) water_val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mmACP_BT_TX_INTR_WATERMARK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) reg_val = mmACP_BTTDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ier_val = mmACP_BTTDM_IER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) buf_reg = mmACP_BT_TX_RINGBUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) water_val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mmACP_I2S_TX_INTR_WATERMARK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) reg_val = mmACP_I2STDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ier_val = mmACP_I2STDM_IER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) buf_reg = mmACP_I2S_TX_RINGBUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) water_val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) mmACP_BT_RX_INTR_WATERMARK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) reg_val = mmACP_BTTDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ier_val = mmACP_BTTDM_IER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) buf_reg = mmACP_BT_RX_RINGBUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) water_val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) mmACP_I2S_RX_INTR_WATERMARK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) reg_val = mmACP_I2STDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ier_val = mmACP_I2STDM_IER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) buf_reg = mmACP_I2S_RX_RINGBUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) rv_writel(period_bytes, rtd->acp3x_base + water_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) rv_writel(buf_size, rtd->acp3x_base + buf_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) val = rv_readl(rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) val = val | BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) rv_writel(val, rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) rv_writel(1, rtd->acp3x_base + ier_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) reg_val = mmACP_BTTDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) reg_val = mmACP_I2STDM_ITER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) switch (rtd->i2s_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case I2S_BT_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) reg_val = mmACP_BTTDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case I2S_SP_INSTANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) reg_val = mmACP_I2STDM_IRER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) val = rv_readl(rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) val = val & ~BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) rv_writel(val, rtd->acp3x_base + reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!(rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER) & BIT(0)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) !(rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER) & BIT(0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!(rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER) & BIT(0)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) !(rv_readl(rtd->acp3x_base + mmACP_I2STDM_IRER) & BIT(0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) rv_writel(0, rtd->acp3x_base + mmACP_I2STDM_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct snd_soc_dai_ops acp3x_i2s_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .hw_params = acp3x_i2s_hwparams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .trigger = acp3x_i2s_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .set_fmt = acp3x_i2s_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .set_tdm_slot = acp3x_i2s_set_tdm_slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const struct snd_soc_component_driver acp3x_dai_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct snd_soc_dai_driver acp3x_i2s_dai = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .rates = SNDRV_PCM_RATE_8000_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .channels_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .rate_max = 96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .rates = SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .ops = &acp3x_i2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int acp3x_dai_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct i2s_dev_data *adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!adata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!adata->acp3x_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) adata->i2s_irq = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev_set_drvdata(&pdev->dev, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = devm_snd_soc_register_component(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) &acp3x_dai_component, &acp3x_i2s_dai, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int acp3x_dai_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* As we use devm_ memory alloc there is nothing TBD here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static struct platform_driver acp3x_dai_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .probe = acp3x_dai_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .remove = acp3x_dai_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .name = "acp3x_i2s_playcap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) module_platform_driver(acp3x_dai_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) MODULE_ALIAS("platform:"DRV_NAME);