1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2021 Advanced Micro Devices, Inc. 7 // 8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> 9 // 10 11 /* 12 * Generic Hardware interface for ACP Audio I2S controller 13 */ 14 15 #include <linux/platform_device.h> 16 #include <linux/module.h> 17 #include <linux/err.h> 18 #include <linux/io.h> 19 #include <sound/pcm_params.h> 20 #include <sound/soc.h> 21 #include <sound/soc-dai.h> 22 #include <linux/dma-mapping.h> 23 24 #include "amd.h" 25 26 #define DRV_NAME "acp_i2s_playcap" 27 28 static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 29 unsigned int fmt) 30 { 31 struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai); 32 int mode; 33 34 mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 35 switch (mode) { 36 case SND_SOC_DAIFMT_I2S: 37 adata->tdm_mode = TDM_DISABLE; 38 break; 39 case SND_SOC_DAIFMT_DSP_A: 40 adata->tdm_mode = TDM_ENABLE; 41 break; 42 default: 43 return -EINVAL; 44 } 45 return 0; 46 } 47 48 static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask, 49 int slots, int slot_width) 50 { 51 struct device *dev = dai->component->dev; 52 struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai); 53 struct acp_stream *stream; 54 int slot_len, no_of_slots; 55 56 switch (slot_width) { 57 case SLOT_WIDTH_8: 58 slot_len = 8; 59 break; 60 case SLOT_WIDTH_16: 61 slot_len = 16; 62 break; 63 case SLOT_WIDTH_24: 64 slot_len = 24; 65 break; 66 case SLOT_WIDTH_32: 67 slot_len = 0; 68 break; 69 default: 70 dev_err(dev, "Unsupported bitdepth %d\n", slot_width); 71 return -EINVAL; 72 } 73 74 switch (slots) { 75 case 1 ... 7: 76 no_of_slots = slots; 77 break; 78 case 8: 79 no_of_slots = 0; 80 break; 81 default: 82 dev_err(dev, "Unsupported slots %d\n", slots); 83 return -EINVAL; 84 } 85 86 slots = no_of_slots; 87 88 spin_lock_irq(&adata->acp_lock); 89 list_for_each_entry(stream, &adata->stream_list, list) { 90 if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 91 adata->tdm_tx_fmt[stream->dai_id - 1] = 92 FRM_LEN | (slots << 15) | (slot_len << 18); 93 else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) 94 adata->tdm_rx_fmt[stream->dai_id - 1] = 95 FRM_LEN | (slots << 15) | (slot_len << 18); 96 } 97 spin_unlock_irq(&adata->acp_lock); 98 return 0; 99 } 100 101 static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, 102 struct snd_soc_dai *dai) 103 { 104 struct device *dev = dai->component->dev; 105 struct acp_dev_data *adata; 106 struct acp_resource *rsrc; 107 u32 val; 108 u32 xfer_resolution; 109 u32 reg_val, fmt_reg, tdm_fmt; 110 u32 lrclk_div_val, bclk_div_val; 111 112 adata = snd_soc_dai_get_drvdata(dai); 113 rsrc = adata->rsrc; 114 115 /* These values are as per Hardware Spec */ 116 switch (params_format(params)) { 117 case SNDRV_PCM_FORMAT_U8: 118 case SNDRV_PCM_FORMAT_S8: 119 xfer_resolution = 0x0; 120 break; 121 case SNDRV_PCM_FORMAT_S16_LE: 122 xfer_resolution = 0x02; 123 break; 124 case SNDRV_PCM_FORMAT_S24_LE: 125 xfer_resolution = 0x04; 126 break; 127 case SNDRV_PCM_FORMAT_S32_LE: 128 xfer_resolution = 0x05; 129 break; 130 default: 131 return -EINVAL; 132 } 133 134 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 135 switch (dai->driver->id) { 136 case I2S_BT_INSTANCE: 137 reg_val = ACP_BTTDM_ITER; 138 fmt_reg = ACP_BTTDM_TXFRMT; 139 break; 140 case I2S_SP_INSTANCE: 141 reg_val = ACP_I2STDM_ITER; 142 fmt_reg = ACP_I2STDM_TXFRMT; 143 break; 144 case I2S_HS_INSTANCE: 145 reg_val = ACP_HSTDM_ITER; 146 fmt_reg = ACP_HSTDM_TXFRMT; 147 break; 148 default: 149 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 150 return -EINVAL; 151 } 152 adata->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution; 153 } else { 154 switch (dai->driver->id) { 155 case I2S_BT_INSTANCE: 156 reg_val = ACP_BTTDM_IRER; 157 fmt_reg = ACP_BTTDM_RXFRMT; 158 break; 159 case I2S_SP_INSTANCE: 160 reg_val = ACP_I2STDM_IRER; 161 fmt_reg = ACP_I2STDM_RXFRMT; 162 break; 163 case I2S_HS_INSTANCE: 164 reg_val = ACP_HSTDM_IRER; 165 fmt_reg = ACP_HSTDM_RXFRMT; 166 break; 167 default: 168 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 169 return -EINVAL; 170 } 171 adata->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution; 172 } 173 174 val = readl(adata->acp_base + reg_val); 175 val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK; 176 val = val | (xfer_resolution << 3); 177 writel(val, adata->acp_base + reg_val); 178 179 if (adata->tdm_mode) { 180 val = readl(adata->acp_base + reg_val); 181 writel(val | BIT(1), adata->acp_base + reg_val); 182 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 183 tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1]; 184 else 185 tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1]; 186 writel(tdm_fmt, adata->acp_base + fmt_reg); 187 } 188 189 if (rsrc->soc_mclk) { 190 switch (params_format(params)) { 191 case SNDRV_PCM_FORMAT_S16_LE: 192 switch (params_rate(params)) { 193 case 8000: 194 bclk_div_val = 768; 195 break; 196 case 16000: 197 bclk_div_val = 384; 198 break; 199 case 24000: 200 bclk_div_val = 256; 201 break; 202 case 32000: 203 bclk_div_val = 192; 204 break; 205 case 44100: 206 case 48000: 207 bclk_div_val = 128; 208 break; 209 case 88200: 210 case 96000: 211 bclk_div_val = 64; 212 break; 213 case 192000: 214 bclk_div_val = 32; 215 break; 216 default: 217 return -EINVAL; 218 } 219 lrclk_div_val = 32; 220 break; 221 case SNDRV_PCM_FORMAT_S32_LE: 222 switch (params_rate(params)) { 223 case 8000: 224 bclk_div_val = 384; 225 break; 226 case 16000: 227 bclk_div_val = 192; 228 break; 229 case 24000: 230 bclk_div_val = 128; 231 break; 232 case 32000: 233 bclk_div_val = 96; 234 break; 235 case 44100: 236 case 48000: 237 bclk_div_val = 64; 238 break; 239 case 88200: 240 case 96000: 241 bclk_div_val = 32; 242 break; 243 case 192000: 244 bclk_div_val = 16; 245 break; 246 default: 247 return -EINVAL; 248 } 249 lrclk_div_val = 64; 250 break; 251 default: 252 return -EINVAL; 253 } 254 adata->lrclk_div = lrclk_div_val; 255 adata->bclk_div = bclk_div_val; 256 } 257 return 0; 258 } 259 260 static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) 261 { 262 struct acp_stream *stream = substream->runtime->private_data; 263 struct device *dev = dai->component->dev; 264 struct acp_dev_data *adata = dev_get_drvdata(dev); 265 struct acp_resource *rsrc = adata->rsrc; 266 u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg; 267 268 period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); 269 buf_size = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); 270 271 switch (cmd) { 272 case SNDRV_PCM_TRIGGER_START: 273 case SNDRV_PCM_TRIGGER_RESUME: 274 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 275 stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream); 276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 277 switch (dai->driver->id) { 278 case I2S_BT_INSTANCE: 279 water_val = ACP_BT_TX_INTR_WATERMARK_SIZE; 280 reg_val = ACP_BTTDM_ITER; 281 ier_val = ACP_BTTDM_IER; 282 buf_reg = ACP_BT_TX_RINGBUFSIZE; 283 break; 284 case I2S_SP_INSTANCE: 285 water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE; 286 reg_val = ACP_I2STDM_ITER; 287 ier_val = ACP_I2STDM_IER; 288 buf_reg = ACP_I2S_TX_RINGBUFSIZE; 289 break; 290 case I2S_HS_INSTANCE: 291 water_val = ACP_HS_TX_INTR_WATERMARK_SIZE; 292 reg_val = ACP_HSTDM_ITER; 293 ier_val = ACP_HSTDM_IER; 294 buf_reg = ACP_HS_TX_RINGBUFSIZE; 295 break; 296 default: 297 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 298 return -EINVAL; 299 } 300 } else { 301 switch (dai->driver->id) { 302 case I2S_BT_INSTANCE: 303 water_val = ACP_BT_RX_INTR_WATERMARK_SIZE; 304 reg_val = ACP_BTTDM_IRER; 305 ier_val = ACP_BTTDM_IER; 306 buf_reg = ACP_BT_RX_RINGBUFSIZE; 307 break; 308 case I2S_SP_INSTANCE: 309 water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE; 310 reg_val = ACP_I2STDM_IRER; 311 ier_val = ACP_I2STDM_IER; 312 buf_reg = ACP_I2S_RX_RINGBUFSIZE; 313 break; 314 case I2S_HS_INSTANCE: 315 water_val = ACP_HS_RX_INTR_WATERMARK_SIZE; 316 reg_val = ACP_HSTDM_IRER; 317 ier_val = ACP_HSTDM_IER; 318 buf_reg = ACP_HS_RX_RINGBUFSIZE; 319 break; 320 default: 321 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 322 return -EINVAL; 323 } 324 } 325 writel(period_bytes, adata->acp_base + water_val); 326 writel(buf_size, adata->acp_base + buf_reg); 327 val = readl(adata->acp_base + reg_val); 328 val = val | BIT(0); 329 writel(val, adata->acp_base + reg_val); 330 writel(1, adata->acp_base + ier_val); 331 if (rsrc->soc_mclk) 332 acp_set_i2s_clk(adata, dai->driver->id); 333 return 0; 334 case SNDRV_PCM_TRIGGER_STOP: 335 case SNDRV_PCM_TRIGGER_SUSPEND: 336 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 337 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 338 switch (dai->driver->id) { 339 case I2S_BT_INSTANCE: 340 reg_val = ACP_BTTDM_ITER; 341 break; 342 case I2S_SP_INSTANCE: 343 reg_val = ACP_I2STDM_ITER; 344 break; 345 case I2S_HS_INSTANCE: 346 reg_val = ACP_HSTDM_ITER; 347 break; 348 default: 349 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 350 return -EINVAL; 351 } 352 353 } else { 354 switch (dai->driver->id) { 355 case I2S_BT_INSTANCE: 356 reg_val = ACP_BTTDM_IRER; 357 break; 358 case I2S_SP_INSTANCE: 359 reg_val = ACP_I2STDM_IRER; 360 break; 361 case I2S_HS_INSTANCE: 362 reg_val = ACP_HSTDM_IRER; 363 break; 364 default: 365 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 366 return -EINVAL; 367 } 368 } 369 val = readl(adata->acp_base + reg_val); 370 val = val & ~BIT(0); 371 writel(val, adata->acp_base + reg_val); 372 373 if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) && 374 !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0))) 375 writel(0, adata->acp_base + ACP_BTTDM_IER); 376 if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) && 377 !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0))) 378 writel(0, adata->acp_base + ACP_I2STDM_IER); 379 if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) && 380 !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0))) 381 writel(0, adata->acp_base + ACP_HSTDM_IER); 382 return 0; 383 default: 384 return -EINVAL; 385 } 386 387 return 0; 388 } 389 390 static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 391 { 392 struct device *dev = dai->component->dev; 393 struct acp_dev_data *adata = dev_get_drvdata(dev); 394 struct acp_resource *rsrc = adata->rsrc; 395 struct acp_stream *stream = substream->runtime->private_data; 396 u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0; 397 u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl; 398 unsigned int dir = substream->stream; 399 400 switch (dai->driver->id) { 401 case I2S_SP_INSTANCE: 402 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 403 reg_dma_size = ACP_I2S_TX_DMA_SIZE; 404 acp_fifo_addr = rsrc->sram_pte_offset + 405 SP_PB_FIFO_ADDR_OFFSET; 406 reg_fifo_addr = ACP_I2S_TX_FIFOADDR; 407 reg_fifo_size = ACP_I2S_TX_FIFOSIZE; 408 409 phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; 410 writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); 411 } else { 412 reg_dma_size = ACP_I2S_RX_DMA_SIZE; 413 acp_fifo_addr = rsrc->sram_pte_offset + 414 SP_CAPT_FIFO_ADDR_OFFSET; 415 reg_fifo_addr = ACP_I2S_RX_FIFOADDR; 416 reg_fifo_size = ACP_I2S_RX_FIFOSIZE; 417 phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; 418 writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); 419 } 420 break; 421 case I2S_BT_INSTANCE: 422 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 423 reg_dma_size = ACP_BT_TX_DMA_SIZE; 424 acp_fifo_addr = rsrc->sram_pte_offset + 425 BT_PB_FIFO_ADDR_OFFSET; 426 reg_fifo_addr = ACP_BT_TX_FIFOADDR; 427 reg_fifo_size = ACP_BT_TX_FIFOSIZE; 428 429 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; 430 writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); 431 } else { 432 reg_dma_size = ACP_BT_RX_DMA_SIZE; 433 acp_fifo_addr = rsrc->sram_pte_offset + 434 BT_CAPT_FIFO_ADDR_OFFSET; 435 reg_fifo_addr = ACP_BT_RX_FIFOADDR; 436 reg_fifo_size = ACP_BT_RX_FIFOSIZE; 437 438 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; 439 writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); 440 } 441 break; 442 case I2S_HS_INSTANCE: 443 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 444 reg_dma_size = ACP_HS_TX_DMA_SIZE; 445 acp_fifo_addr = rsrc->sram_pte_offset + 446 HS_PB_FIFO_ADDR_OFFSET; 447 reg_fifo_addr = ACP_HS_TX_FIFOADDR; 448 reg_fifo_size = ACP_HS_TX_FIFOSIZE; 449 450 phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; 451 writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR); 452 } else { 453 reg_dma_size = ACP_HS_RX_DMA_SIZE; 454 acp_fifo_addr = rsrc->sram_pte_offset + 455 HS_CAPT_FIFO_ADDR_OFFSET; 456 reg_fifo_addr = ACP_HS_RX_FIFOADDR; 457 reg_fifo_size = ACP_HS_RX_FIFOSIZE; 458 459 phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; 460 writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR); 461 } 462 break; 463 default: 464 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 465 return -EINVAL; 466 } 467 468 writel(DMA_SIZE, adata->acp_base + reg_dma_size); 469 writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); 470 writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); 471 472 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); 473 ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | 474 BIT(BT_RX_THRESHOLD(rsrc->offset)) | 475 BIT(I2S_TX_THRESHOLD(rsrc->offset)) | 476 BIT(BT_TX_THRESHOLD(rsrc->offset)) | 477 BIT(HS_RX_THRESHOLD(rsrc->offset)) | 478 BIT(HS_TX_THRESHOLD(rsrc->offset)); 479 480 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); 481 482 return 0; 483 } 484 485 static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 486 { 487 struct acp_stream *stream = substream->runtime->private_data; 488 struct device *dev = dai->component->dev; 489 struct acp_dev_data *adata = dev_get_drvdata(dev); 490 struct acp_resource *rsrc = adata->rsrc; 491 unsigned int dir = substream->stream; 492 unsigned int irq_bit = 0; 493 494 switch (dai->driver->id) { 495 case I2S_SP_INSTANCE: 496 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 497 irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset)); 498 stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET; 499 stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET; 500 } else { 501 irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset)); 502 stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET; 503 stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET; 504 } 505 break; 506 case I2S_BT_INSTANCE: 507 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 508 irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset)); 509 stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET; 510 stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET; 511 } else { 512 irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset)); 513 stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET; 514 stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET; 515 } 516 break; 517 case I2S_HS_INSTANCE: 518 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 519 irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset)); 520 stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET; 521 stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET; 522 } else { 523 irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset)); 524 stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET; 525 stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET; 526 } 527 break; 528 default: 529 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 530 return -EINVAL; 531 } 532 533 /* Save runtime dai configuration in stream */ 534 stream->id = dai->driver->id + dir; 535 stream->dai_id = dai->driver->id; 536 stream->irq_bit = irq_bit; 537 stream->dir = substream->stream; 538 539 return 0; 540 } 541 542 static int acp_i2s_probe(struct snd_soc_dai *dai) 543 { 544 struct device *dev = dai->component->dev; 545 struct acp_dev_data *adata = dev_get_drvdata(dev); 546 547 if (!adata->acp_base) { 548 dev_err(dev, "I2S base is NULL\n"); 549 return -EINVAL; 550 } 551 552 return 0; 553 } 554 555 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { 556 .probe = acp_i2s_probe, 557 .startup = acp_i2s_startup, 558 .hw_params = acp_i2s_hwparams, 559 .prepare = acp_i2s_prepare, 560 .trigger = acp_i2s_trigger, 561 .set_fmt = acp_i2s_set_fmt, 562 .set_tdm_slot = acp_i2s_set_tdm_slot, 563 }; 564 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON); 565 566 MODULE_LICENSE("Dual BSD/GPL"); 567 MODULE_ALIAS(DRV_NAME); 568