0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/platform_device.h>
0016 #include <linux/module.h>
0017 #include <linux/err.h>
0018 #include <linux/io.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021 #include <sound/soc-dai.h>
0022 #include <linux/dma-mapping.h>
0023
0024 #include "amd.h"
0025
0026 #define DRV_NAME "acp_i2s_playcap"
0027
0028 static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
0029 struct snd_soc_dai *dai)
0030 {
0031 struct device *dev = dai->component->dev;
0032 struct acp_dev_data *adata;
0033 struct acp_resource *rsrc;
0034 u32 val;
0035 u32 xfer_resolution;
0036 u32 reg_val;
0037 u32 lrclk_div_val, bclk_div_val;
0038
0039 adata = snd_soc_dai_get_drvdata(dai);
0040 rsrc = adata->rsrc;
0041
0042
0043 switch (params_format(params)) {
0044 case SNDRV_PCM_FORMAT_U8:
0045 case SNDRV_PCM_FORMAT_S8:
0046 xfer_resolution = 0x0;
0047 break;
0048 case SNDRV_PCM_FORMAT_S16_LE:
0049 xfer_resolution = 0x02;
0050 break;
0051 case SNDRV_PCM_FORMAT_S24_LE:
0052 xfer_resolution = 0x04;
0053 break;
0054 case SNDRV_PCM_FORMAT_S32_LE:
0055 xfer_resolution = 0x05;
0056 break;
0057 default:
0058 return -EINVAL;
0059 }
0060
0061 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0062 switch (dai->driver->id) {
0063 case I2S_BT_INSTANCE:
0064 reg_val = ACP_BTTDM_ITER;
0065 break;
0066 case I2S_SP_INSTANCE:
0067 reg_val = ACP_I2STDM_ITER;
0068 break;
0069 case I2S_HS_INSTANCE:
0070 reg_val = ACP_HSTDM_ITER;
0071 break;
0072 default:
0073 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0074 return -EINVAL;
0075 }
0076 } else {
0077 switch (dai->driver->id) {
0078 case I2S_BT_INSTANCE:
0079 reg_val = ACP_BTTDM_IRER;
0080 break;
0081 case I2S_SP_INSTANCE:
0082 reg_val = ACP_I2STDM_IRER;
0083 break;
0084 case I2S_HS_INSTANCE:
0085 reg_val = ACP_HSTDM_IRER;
0086 break;
0087 default:
0088 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0089 return -EINVAL;
0090 }
0091 }
0092
0093 val = readl(adata->acp_base + reg_val);
0094 val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
0095 val = val | (xfer_resolution << 3);
0096 writel(val, adata->acp_base + reg_val);
0097
0098 if (rsrc->soc_mclk) {
0099 switch (params_format(params)) {
0100 case SNDRV_PCM_FORMAT_S16_LE:
0101 switch (params_rate(params)) {
0102 case 8000:
0103 bclk_div_val = 768;
0104 break;
0105 case 16000:
0106 bclk_div_val = 384;
0107 break;
0108 case 24000:
0109 bclk_div_val = 256;
0110 break;
0111 case 32000:
0112 bclk_div_val = 192;
0113 break;
0114 case 44100:
0115 case 48000:
0116 bclk_div_val = 128;
0117 break;
0118 case 88200:
0119 case 96000:
0120 bclk_div_val = 64;
0121 break;
0122 case 192000:
0123 bclk_div_val = 32;
0124 break;
0125 default:
0126 return -EINVAL;
0127 }
0128 lrclk_div_val = 32;
0129 break;
0130 case SNDRV_PCM_FORMAT_S32_LE:
0131 switch (params_rate(params)) {
0132 case 8000:
0133 bclk_div_val = 384;
0134 break;
0135 case 16000:
0136 bclk_div_val = 192;
0137 break;
0138 case 24000:
0139 bclk_div_val = 128;
0140 break;
0141 case 32000:
0142 bclk_div_val = 96;
0143 break;
0144 case 44100:
0145 case 48000:
0146 bclk_div_val = 64;
0147 break;
0148 case 88200:
0149 case 96000:
0150 bclk_div_val = 32;
0151 break;
0152 case 192000:
0153 bclk_div_val = 16;
0154 break;
0155 default:
0156 return -EINVAL;
0157 }
0158 lrclk_div_val = 64;
0159 break;
0160 default:
0161 return -EINVAL;
0162 }
0163 adata->lrclk_div = lrclk_div_val;
0164 adata->bclk_div = bclk_div_val;
0165 }
0166 return 0;
0167 }
0168
0169 static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
0170 {
0171 struct acp_stream *stream = substream->runtime->private_data;
0172 struct device *dev = dai->component->dev;
0173 struct acp_dev_data *adata = dev_get_drvdata(dev);
0174 struct acp_resource *rsrc = adata->rsrc;
0175 u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
0176
0177 period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
0178 buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
0179
0180 switch (cmd) {
0181 case SNDRV_PCM_TRIGGER_START:
0182 case SNDRV_PCM_TRIGGER_RESUME:
0183 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0184 stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
0185 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0186 switch (dai->driver->id) {
0187 case I2S_BT_INSTANCE:
0188 water_val = ACP_BT_TX_INTR_WATERMARK_SIZE;
0189 reg_val = ACP_BTTDM_ITER;
0190 ier_val = ACP_BTTDM_IER;
0191 buf_reg = ACP_BT_TX_RINGBUFSIZE;
0192 break;
0193 case I2S_SP_INSTANCE:
0194 water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE;
0195 reg_val = ACP_I2STDM_ITER;
0196 ier_val = ACP_I2STDM_IER;
0197 buf_reg = ACP_I2S_TX_RINGBUFSIZE;
0198 break;
0199 case I2S_HS_INSTANCE:
0200 water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
0201 reg_val = ACP_HSTDM_ITER;
0202 ier_val = ACP_HSTDM_IER;
0203 buf_reg = ACP_HS_TX_RINGBUFSIZE;
0204 break;
0205 default:
0206 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0207 return -EINVAL;
0208 }
0209 } else {
0210 switch (dai->driver->id) {
0211 case I2S_BT_INSTANCE:
0212 water_val = ACP_BT_RX_INTR_WATERMARK_SIZE;
0213 reg_val = ACP_BTTDM_IRER;
0214 ier_val = ACP_BTTDM_IER;
0215 buf_reg = ACP_BT_RX_RINGBUFSIZE;
0216 break;
0217 case I2S_SP_INSTANCE:
0218 water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE;
0219 reg_val = ACP_I2STDM_IRER;
0220 ier_val = ACP_I2STDM_IER;
0221 buf_reg = ACP_I2S_RX_RINGBUFSIZE;
0222 break;
0223 case I2S_HS_INSTANCE:
0224 water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
0225 reg_val = ACP_HSTDM_IRER;
0226 ier_val = ACP_HSTDM_IER;
0227 buf_reg = ACP_HS_RX_RINGBUFSIZE;
0228 break;
0229 default:
0230 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0231 return -EINVAL;
0232 }
0233 }
0234 writel(period_bytes, adata->acp_base + water_val);
0235 writel(buf_size, adata->acp_base + buf_reg);
0236 val = readl(adata->acp_base + reg_val);
0237 val = val | BIT(0);
0238 writel(val, adata->acp_base + reg_val);
0239 writel(1, adata->acp_base + ier_val);
0240 if (rsrc->soc_mclk)
0241 acp_set_i2s_clk(adata, dai->driver->id);
0242 return 0;
0243 case SNDRV_PCM_TRIGGER_STOP:
0244 case SNDRV_PCM_TRIGGER_SUSPEND:
0245 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0246 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0247 switch (dai->driver->id) {
0248 case I2S_BT_INSTANCE:
0249 reg_val = ACP_BTTDM_ITER;
0250 break;
0251 case I2S_SP_INSTANCE:
0252 reg_val = ACP_I2STDM_ITER;
0253 break;
0254 case I2S_HS_INSTANCE:
0255 reg_val = ACP_HSTDM_ITER;
0256 break;
0257 default:
0258 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0259 return -EINVAL;
0260 }
0261
0262 } else {
0263 switch (dai->driver->id) {
0264 case I2S_BT_INSTANCE:
0265 reg_val = ACP_BTTDM_IRER;
0266 break;
0267 case I2S_SP_INSTANCE:
0268 reg_val = ACP_I2STDM_IRER;
0269 break;
0270 case I2S_HS_INSTANCE:
0271 reg_val = ACP_HSTDM_IRER;
0272 break;
0273 default:
0274 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0275 return -EINVAL;
0276 }
0277 }
0278 val = readl(adata->acp_base + reg_val);
0279 val = val & ~BIT(0);
0280 writel(val, adata->acp_base + reg_val);
0281
0282 if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
0283 !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
0284 writel(0, adata->acp_base + ACP_BTTDM_IER);
0285 if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
0286 !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
0287 writel(0, adata->acp_base + ACP_I2STDM_IER);
0288 if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
0289 !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
0290 writel(0, adata->acp_base + ACP_HSTDM_IER);
0291 return 0;
0292 default:
0293 return -EINVAL;
0294 }
0295
0296 return 0;
0297 }
0298
0299 static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0300 {
0301 struct device *dev = dai->component->dev;
0302 struct acp_dev_data *adata = dev_get_drvdata(dev);
0303 struct acp_resource *rsrc = adata->rsrc;
0304 struct acp_stream *stream = substream->runtime->private_data;
0305 u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
0306 u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
0307 unsigned int dir = substream->stream;
0308
0309 switch (dai->driver->id) {
0310 case I2S_SP_INSTANCE:
0311 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0312 reg_dma_size = ACP_I2S_TX_DMA_SIZE;
0313 acp_fifo_addr = rsrc->sram_pte_offset +
0314 SP_PB_FIFO_ADDR_OFFSET;
0315 reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
0316 reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
0317
0318 phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
0319 writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
0320 } else {
0321 reg_dma_size = ACP_I2S_RX_DMA_SIZE;
0322 acp_fifo_addr = rsrc->sram_pte_offset +
0323 SP_CAPT_FIFO_ADDR_OFFSET;
0324 reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
0325 reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
0326 phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
0327 writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
0328 }
0329 break;
0330 case I2S_BT_INSTANCE:
0331 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0332 reg_dma_size = ACP_BT_TX_DMA_SIZE;
0333 acp_fifo_addr = rsrc->sram_pte_offset +
0334 BT_PB_FIFO_ADDR_OFFSET;
0335 reg_fifo_addr = ACP_BT_TX_FIFOADDR;
0336 reg_fifo_size = ACP_BT_TX_FIFOSIZE;
0337
0338 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
0339 writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
0340 } else {
0341 reg_dma_size = ACP_BT_RX_DMA_SIZE;
0342 acp_fifo_addr = rsrc->sram_pte_offset +
0343 BT_CAPT_FIFO_ADDR_OFFSET;
0344 reg_fifo_addr = ACP_BT_RX_FIFOADDR;
0345 reg_fifo_size = ACP_BT_RX_FIFOSIZE;
0346
0347 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
0348 writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
0349 }
0350 break;
0351 case I2S_HS_INSTANCE:
0352 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0353 reg_dma_size = ACP_HS_TX_DMA_SIZE;
0354 acp_fifo_addr = rsrc->sram_pte_offset +
0355 HS_PB_FIFO_ADDR_OFFSET;
0356 reg_fifo_addr = ACP_HS_TX_FIFOADDR;
0357 reg_fifo_size = ACP_HS_TX_FIFOSIZE;
0358
0359 phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
0360 writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
0361 } else {
0362 reg_dma_size = ACP_HS_RX_DMA_SIZE;
0363 acp_fifo_addr = rsrc->sram_pte_offset +
0364 HS_CAPT_FIFO_ADDR_OFFSET;
0365 reg_fifo_addr = ACP_HS_RX_FIFOADDR;
0366 reg_fifo_size = ACP_HS_RX_FIFOSIZE;
0367
0368 phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
0369 writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
0370 }
0371 break;
0372 default:
0373 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0374 return -EINVAL;
0375 }
0376
0377 writel(DMA_SIZE, adata->acp_base + reg_dma_size);
0378 writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
0379 writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
0380
0381 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
0382 ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
0383 BIT(BT_RX_THRESHOLD(rsrc->offset)) |
0384 BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
0385 BIT(BT_TX_THRESHOLD(rsrc->offset)) |
0386 BIT(HS_RX_THRESHOLD(rsrc->offset)) |
0387 BIT(HS_TX_THRESHOLD(rsrc->offset));
0388
0389 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
0390
0391 return 0;
0392 }
0393
0394 static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0395 {
0396 struct acp_stream *stream = substream->runtime->private_data;
0397 struct device *dev = dai->component->dev;
0398 struct acp_dev_data *adata = dev_get_drvdata(dev);
0399 struct acp_resource *rsrc = adata->rsrc;
0400 unsigned int dir = substream->stream;
0401 unsigned int irq_bit = 0;
0402
0403 switch (dai->driver->id) {
0404 case I2S_SP_INSTANCE:
0405 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0406 irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
0407 stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
0408 stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
0409 } else {
0410 irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
0411 stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
0412 stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
0413 }
0414 break;
0415 case I2S_BT_INSTANCE:
0416 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0417 irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
0418 stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
0419 stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
0420 } else {
0421 irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
0422 stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
0423 stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
0424 }
0425 break;
0426 case I2S_HS_INSTANCE:
0427 if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
0428 irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
0429 stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
0430 stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
0431 } else {
0432 irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
0433 stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
0434 stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
0435 }
0436 break;
0437 default:
0438 dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
0439 return -EINVAL;
0440 }
0441
0442
0443 stream->id = dai->driver->id + dir;
0444 stream->dai_id = dai->driver->id;
0445 stream->irq_bit = irq_bit;
0446
0447 return 0;
0448 }
0449
0450 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
0451 .startup = acp_i2s_startup,
0452 .hw_params = acp_i2s_hwparams,
0453 .prepare = acp_i2s_prepare,
0454 .trigger = acp_i2s_trigger,
0455 };
0456 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
0457
0458 int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
0459 {
0460 struct device *dev = dai->component->dev;
0461 struct acp_dev_data *adata = dev_get_drvdata(dev);
0462 struct acp_resource *rsrc = adata->rsrc;
0463 unsigned int val;
0464
0465 if (!adata->acp_base) {
0466 dev_err(dev, "I2S base is NULL\n");
0467 return -EINVAL;
0468 }
0469
0470 val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
0471 if (val != rsrc->i2s_mode) {
0472 dev_err(dev, "I2S Mode not supported val %x\n", val);
0473 return -EINVAL;
0474 }
0475
0476 return 0;
0477 }
0478 EXPORT_SYMBOL_NS_GPL(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON);
0479
0480 MODULE_LICENSE("Dual BSD/GPL");
0481 MODULE_ALIAS(DRV_NAME);