1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (C) 2014-2015 Broadcom Corporation 3 #include <linux/debugfs.h> 4 #include <linux/dma-mapping.h> 5 #include <linux/init.h> 6 #include <linux/io.h> 7 #include <linux/module.h> 8 #include <linux/slab.h> 9 #include <linux/timer.h> 10 #include <sound/core.h> 11 #include <sound/pcm.h> 12 #include <sound/pcm_params.h> 13 #include <sound/soc.h> 14 #include <sound/soc-dai.h> 15 16 #include "cygnus-ssp.h" 17 18 /* Register offset needed for ASoC PCM module */ 19 20 #define INTH_R5F_STATUS_OFFSET 0x040 21 #define INTH_R5F_CLEAR_OFFSET 0x048 22 #define INTH_R5F_MASK_SET_OFFSET 0x050 23 #define INTH_R5F_MASK_CLEAR_OFFSET 0x054 24 25 #define BF_REARM_FREE_MARK_OFFSET 0x344 26 #define BF_REARM_FULL_MARK_OFFSET 0x348 27 28 /* Ring Buffer Ctrl Regs --- Start */ 29 /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_RDADDR_REG_BASE */ 30 #define SRC_RBUF_0_RDADDR_OFFSET 0x500 31 #define SRC_RBUF_1_RDADDR_OFFSET 0x518 32 #define SRC_RBUF_2_RDADDR_OFFSET 0x530 33 #define SRC_RBUF_3_RDADDR_OFFSET 0x548 34 #define SRC_RBUF_4_RDADDR_OFFSET 0x560 35 #define SRC_RBUF_5_RDADDR_OFFSET 0x578 36 #define SRC_RBUF_6_RDADDR_OFFSET 0x590 37 38 /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_WRADDR_REG_BASE */ 39 #define SRC_RBUF_0_WRADDR_OFFSET 0x504 40 #define SRC_RBUF_1_WRADDR_OFFSET 0x51c 41 #define SRC_RBUF_2_WRADDR_OFFSET 0x534 42 #define SRC_RBUF_3_WRADDR_OFFSET 0x54c 43 #define SRC_RBUF_4_WRADDR_OFFSET 0x564 44 #define SRC_RBUF_5_WRADDR_OFFSET 0x57c 45 #define SRC_RBUF_6_WRADDR_OFFSET 0x594 46 47 /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_BASEADDR_REG_BASE */ 48 #define SRC_RBUF_0_BASEADDR_OFFSET 0x508 49 #define SRC_RBUF_1_BASEADDR_OFFSET 0x520 50 #define SRC_RBUF_2_BASEADDR_OFFSET 0x538 51 #define SRC_RBUF_3_BASEADDR_OFFSET 0x550 52 #define SRC_RBUF_4_BASEADDR_OFFSET 0x568 53 #define SRC_RBUF_5_BASEADDR_OFFSET 0x580 54 #define SRC_RBUF_6_BASEADDR_OFFSET 0x598 55 56 /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_ENDADDR_REG_BASE */ 57 #define SRC_RBUF_0_ENDADDR_OFFSET 0x50c 58 #define SRC_RBUF_1_ENDADDR_OFFSET 0x524 59 #define SRC_RBUF_2_ENDADDR_OFFSET 0x53c 60 #define SRC_RBUF_3_ENDADDR_OFFSET 0x554 61 #define SRC_RBUF_4_ENDADDR_OFFSET 0x56c 62 #define SRC_RBUF_5_ENDADDR_OFFSET 0x584 63 #define SRC_RBUF_6_ENDADDR_OFFSET 0x59c 64 65 /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_FREE_MARK_REG_BASE */ 66 #define SRC_RBUF_0_FREE_MARK_OFFSET 0x510 67 #define SRC_RBUF_1_FREE_MARK_OFFSET 0x528 68 #define SRC_RBUF_2_FREE_MARK_OFFSET 0x540 69 #define SRC_RBUF_3_FREE_MARK_OFFSET 0x558 70 #define SRC_RBUF_4_FREE_MARK_OFFSET 0x570 71 #define SRC_RBUF_5_FREE_MARK_OFFSET 0x588 72 #define SRC_RBUF_6_FREE_MARK_OFFSET 0x5a0 73 74 /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_RDADDR_REG_BASE */ 75 #define DST_RBUF_0_RDADDR_OFFSET 0x5c0 76 #define DST_RBUF_1_RDADDR_OFFSET 0x5d8 77 #define DST_RBUF_2_RDADDR_OFFSET 0x5f0 78 #define DST_RBUF_3_RDADDR_OFFSET 0x608 79 #define DST_RBUF_4_RDADDR_OFFSET 0x620 80 #define DST_RBUF_5_RDADDR_OFFSET 0x638 81 82 /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_WRADDR_REG_BASE */ 83 #define DST_RBUF_0_WRADDR_OFFSET 0x5c4 84 #define DST_RBUF_1_WRADDR_OFFSET 0x5dc 85 #define DST_RBUF_2_WRADDR_OFFSET 0x5f4 86 #define DST_RBUF_3_WRADDR_OFFSET 0x60c 87 #define DST_RBUF_4_WRADDR_OFFSET 0x624 88 #define DST_RBUF_5_WRADDR_OFFSET 0x63c 89 90 /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_BASEADDR_REG_BASE */ 91 #define DST_RBUF_0_BASEADDR_OFFSET 0x5c8 92 #define DST_RBUF_1_BASEADDR_OFFSET 0x5e0 93 #define DST_RBUF_2_BASEADDR_OFFSET 0x5f8 94 #define DST_RBUF_3_BASEADDR_OFFSET 0x610 95 #define DST_RBUF_4_BASEADDR_OFFSET 0x628 96 #define DST_RBUF_5_BASEADDR_OFFSET 0x640 97 98 /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_ENDADDR_REG_BASE */ 99 #define DST_RBUF_0_ENDADDR_OFFSET 0x5cc 100 #define DST_RBUF_1_ENDADDR_OFFSET 0x5e4 101 #define DST_RBUF_2_ENDADDR_OFFSET 0x5fc 102 #define DST_RBUF_3_ENDADDR_OFFSET 0x614 103 #define DST_RBUF_4_ENDADDR_OFFSET 0x62c 104 #define DST_RBUF_5_ENDADDR_OFFSET 0x644 105 106 /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_FULL_MARK_REG_BASE */ 107 #define DST_RBUF_0_FULL_MARK_OFFSET 0x5d0 108 #define DST_RBUF_1_FULL_MARK_OFFSET 0x5e8 109 #define DST_RBUF_2_FULL_MARK_OFFSET 0x600 110 #define DST_RBUF_3_FULL_MARK_OFFSET 0x618 111 #define DST_RBUF_4_FULL_MARK_OFFSET 0x630 112 #define DST_RBUF_5_FULL_MARK_OFFSET 0x648 113 /* Ring Buffer Ctrl Regs --- End */ 114 115 /* Error Status Regs --- Start */ 116 /* AUD_FMM_BF_ESR_ESRX_STATUS_REG_BASE */ 117 #define ESR0_STATUS_OFFSET 0x900 118 #define ESR1_STATUS_OFFSET 0x918 119 #define ESR2_STATUS_OFFSET 0x930 120 #define ESR3_STATUS_OFFSET 0x948 121 #define ESR4_STATUS_OFFSET 0x960 122 123 /* AUD_FMM_BF_ESR_ESRX_STATUS_CLEAR_REG_BASE */ 124 #define ESR0_STATUS_CLR_OFFSET 0x908 125 #define ESR1_STATUS_CLR_OFFSET 0x920 126 #define ESR2_STATUS_CLR_OFFSET 0x938 127 #define ESR3_STATUS_CLR_OFFSET 0x950 128 #define ESR4_STATUS_CLR_OFFSET 0x968 129 130 /* AUD_FMM_BF_ESR_ESRX_MASK_REG_BASE */ 131 #define ESR0_MASK_STATUS_OFFSET 0x90c 132 #define ESR1_MASK_STATUS_OFFSET 0x924 133 #define ESR2_MASK_STATUS_OFFSET 0x93c 134 #define ESR3_MASK_STATUS_OFFSET 0x954 135 #define ESR4_MASK_STATUS_OFFSET 0x96c 136 137 /* AUD_FMM_BF_ESR_ESRX_MASK_SET_REG_BASE */ 138 #define ESR0_MASK_SET_OFFSET 0x910 139 #define ESR1_MASK_SET_OFFSET 0x928 140 #define ESR2_MASK_SET_OFFSET 0x940 141 #define ESR3_MASK_SET_OFFSET 0x958 142 #define ESR4_MASK_SET_OFFSET 0x970 143 144 /* AUD_FMM_BF_ESR_ESRX_MASK_CLEAR_REG_BASE */ 145 #define ESR0_MASK_CLR_OFFSET 0x914 146 #define ESR1_MASK_CLR_OFFSET 0x92c 147 #define ESR2_MASK_CLR_OFFSET 0x944 148 #define ESR3_MASK_CLR_OFFSET 0x95c 149 #define ESR4_MASK_CLR_OFFSET 0x974 150 /* Error Status Regs --- End */ 151 152 #define R5F_ESR0_SHIFT 0 /* esr0 = fifo underflow */ 153 #define R5F_ESR1_SHIFT 1 /* esr1 = ringbuf underflow */ 154 #define R5F_ESR2_SHIFT 2 /* esr2 = ringbuf overflow */ 155 #define R5F_ESR3_SHIFT 3 /* esr3 = freemark */ 156 #define R5F_ESR4_SHIFT 4 /* esr4 = fullmark */ 157 158 159 /* Mask for R5F register. Set all relevant interrupt for playback handler */ 160 #define ANY_PLAYBACK_IRQ (BIT(R5F_ESR0_SHIFT) | \ 161 BIT(R5F_ESR1_SHIFT) | \ 162 BIT(R5F_ESR3_SHIFT)) 163 164 /* Mask for R5F register. Set all relevant interrupt for capture handler */ 165 #define ANY_CAPTURE_IRQ (BIT(R5F_ESR2_SHIFT) | BIT(R5F_ESR4_SHIFT)) 166 167 /* 168 * PERIOD_BYTES_MIN is the number of bytes to at which the interrupt will tick. 169 * This number should be a multiple of 256. Minimum value is 256 170 */ 171 #define PERIOD_BYTES_MIN 0x100 172 173 static const struct snd_pcm_hardware cygnus_pcm_hw = { 174 .info = SNDRV_PCM_INFO_MMAP | 175 SNDRV_PCM_INFO_MMAP_VALID | 176 SNDRV_PCM_INFO_INTERLEAVED, 177 .formats = SNDRV_PCM_FMTBIT_S16_LE | 178 SNDRV_PCM_FMTBIT_S32_LE, 179 180 /* A period is basically an interrupt */ 181 .period_bytes_min = PERIOD_BYTES_MIN, 182 .period_bytes_max = 0x10000, 183 184 /* period_min/max gives range of approx interrupts per buffer */ 185 .periods_min = 2, 186 .periods_max = 8, 187 188 /* 189 * maximum buffer size in bytes = period_bytes_max * periods_max 190 * We allocate this amount of data for each enabled channel 191 */ 192 .buffer_bytes_max = 4 * 0x8000, 193 }; 194 195 static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32); 196 197 static struct cygnus_aio_port *cygnus_dai_get_dma_data( 198 struct snd_pcm_substream *substream) 199 { 200 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 201 202 return snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(soc_runtime, 0), substream); 203 } 204 205 static void ringbuf_set_initial(void __iomem *audio_io, 206 struct ringbuf_regs *p_rbuf, 207 bool is_playback, 208 u32 start, 209 u32 periodsize, 210 u32 bufsize) 211 { 212 u32 initial_rd; 213 u32 initial_wr; 214 u32 end; 215 u32 fmark_val; /* free or full mark */ 216 217 p_rbuf->period_bytes = periodsize; 218 p_rbuf->buf_size = bufsize; 219 220 if (is_playback) { 221 /* Set the pointers to indicate full (flip uppermost bit) */ 222 initial_rd = start; 223 initial_wr = initial_rd ^ BIT(31); 224 } else { 225 /* Set the pointers to indicate empty */ 226 initial_wr = start; 227 initial_rd = initial_wr; 228 } 229 230 end = start + bufsize - 1; 231 232 /* 233 * The interrupt will fire when free/full mark is *exceeded* 234 * The fmark value must be multiple of PERIOD_BYTES_MIN so set fmark 235 * to be PERIOD_BYTES_MIN less than the period size. 236 */ 237 fmark_val = periodsize - PERIOD_BYTES_MIN; 238 239 writel(start, audio_io + p_rbuf->baseaddr); 240 writel(end, audio_io + p_rbuf->endaddr); 241 writel(fmark_val, audio_io + p_rbuf->fmark); 242 writel(initial_rd, audio_io + p_rbuf->rdaddr); 243 writel(initial_wr, audio_io + p_rbuf->wraddr); 244 } 245 246 static int configure_ringbuf_regs(struct snd_pcm_substream *substream) 247 { 248 struct cygnus_aio_port *aio; 249 struct ringbuf_regs *p_rbuf; 250 int status = 0; 251 252 aio = cygnus_dai_get_dma_data(substream); 253 254 /* Map the ssp portnum to a set of ring buffers. */ 255 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 256 p_rbuf = &aio->play_rb_regs; 257 258 switch (aio->portnum) { 259 case 0: 260 *p_rbuf = RINGBUF_REG_PLAYBACK(0); 261 break; 262 case 1: 263 *p_rbuf = RINGBUF_REG_PLAYBACK(2); 264 break; 265 case 2: 266 *p_rbuf = RINGBUF_REG_PLAYBACK(4); 267 break; 268 case 3: /* SPDIF */ 269 *p_rbuf = RINGBUF_REG_PLAYBACK(6); 270 break; 271 default: 272 status = -EINVAL; 273 } 274 } else { 275 p_rbuf = &aio->capture_rb_regs; 276 277 switch (aio->portnum) { 278 case 0: 279 *p_rbuf = RINGBUF_REG_CAPTURE(0); 280 break; 281 case 1: 282 *p_rbuf = RINGBUF_REG_CAPTURE(2); 283 break; 284 case 2: 285 *p_rbuf = RINGBUF_REG_CAPTURE(4); 286 break; 287 default: 288 status = -EINVAL; 289 } 290 } 291 292 return status; 293 } 294 295 static struct ringbuf_regs *get_ringbuf(struct snd_pcm_substream *substream) 296 { 297 struct cygnus_aio_port *aio; 298 struct ringbuf_regs *p_rbuf = NULL; 299 300 aio = cygnus_dai_get_dma_data(substream); 301 302 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 303 p_rbuf = &aio->play_rb_regs; 304 else 305 p_rbuf = &aio->capture_rb_regs; 306 307 return p_rbuf; 308 } 309 310 static void enable_intr(struct snd_pcm_substream *substream) 311 { 312 struct cygnus_aio_port *aio; 313 u32 clear_mask; 314 315 aio = cygnus_dai_get_dma_data(substream); 316 317 /* The port number maps to the bit position to be cleared */ 318 clear_mask = BIT(aio->portnum); 319 320 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 321 /* Clear interrupt status before enabling them */ 322 writel(clear_mask, aio->cygaud->audio + ESR0_STATUS_CLR_OFFSET); 323 writel(clear_mask, aio->cygaud->audio + ESR1_STATUS_CLR_OFFSET); 324 writel(clear_mask, aio->cygaud->audio + ESR3_STATUS_CLR_OFFSET); 325 /* Unmask the interrupts of the given port*/ 326 writel(clear_mask, aio->cygaud->audio + ESR0_MASK_CLR_OFFSET); 327 writel(clear_mask, aio->cygaud->audio + ESR1_MASK_CLR_OFFSET); 328 writel(clear_mask, aio->cygaud->audio + ESR3_MASK_CLR_OFFSET); 329 330 writel(ANY_PLAYBACK_IRQ, 331 aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET); 332 } else { 333 writel(clear_mask, aio->cygaud->audio + ESR2_STATUS_CLR_OFFSET); 334 writel(clear_mask, aio->cygaud->audio + ESR4_STATUS_CLR_OFFSET); 335 writel(clear_mask, aio->cygaud->audio + ESR2_MASK_CLR_OFFSET); 336 writel(clear_mask, aio->cygaud->audio + ESR4_MASK_CLR_OFFSET); 337 338 writel(ANY_CAPTURE_IRQ, 339 aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET); 340 } 341 342 } 343 344 static void disable_intr(struct snd_pcm_substream *substream) 345 { 346 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 347 struct cygnus_aio_port *aio; 348 u32 set_mask; 349 350 aio = cygnus_dai_get_dma_data(substream); 351 352 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s on port %d\n", __func__, aio->portnum); 353 354 /* The port number maps to the bit position to be set */ 355 set_mask = BIT(aio->portnum); 356 357 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 358 /* Mask the interrupts of the given port*/ 359 writel(set_mask, aio->cygaud->audio + ESR0_MASK_SET_OFFSET); 360 writel(set_mask, aio->cygaud->audio + ESR1_MASK_SET_OFFSET); 361 writel(set_mask, aio->cygaud->audio + ESR3_MASK_SET_OFFSET); 362 } else { 363 writel(set_mask, aio->cygaud->audio + ESR2_MASK_SET_OFFSET); 364 writel(set_mask, aio->cygaud->audio + ESR4_MASK_SET_OFFSET); 365 } 366 367 } 368 369 static int cygnus_pcm_trigger(struct snd_soc_component *component, 370 struct snd_pcm_substream *substream, int cmd) 371 { 372 int ret = 0; 373 374 switch (cmd) { 375 case SNDRV_PCM_TRIGGER_START: 376 case SNDRV_PCM_TRIGGER_RESUME: 377 enable_intr(substream); 378 break; 379 380 case SNDRV_PCM_TRIGGER_STOP: 381 case SNDRV_PCM_TRIGGER_SUSPEND: 382 disable_intr(substream); 383 break; 384 default: 385 ret = -EINVAL; 386 } 387 388 return ret; 389 } 390 391 static void cygnus_pcm_period_elapsed(struct snd_pcm_substream *substream) 392 { 393 struct cygnus_aio_port *aio; 394 struct ringbuf_regs *p_rbuf = NULL; 395 u32 regval; 396 397 aio = cygnus_dai_get_dma_data(substream); 398 399 p_rbuf = get_ringbuf(substream); 400 401 /* 402 * If free/full mark interrupt occurs, provide timestamp 403 * to ALSA and update appropriate idx by period_bytes 404 */ 405 snd_pcm_period_elapsed(substream); 406 407 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 408 /* Set the ring buffer to full */ 409 regval = readl(aio->cygaud->audio + p_rbuf->rdaddr); 410 regval = regval ^ BIT(31); 411 writel(regval, aio->cygaud->audio + p_rbuf->wraddr); 412 } else { 413 /* Set the ring buffer to empty */ 414 regval = readl(aio->cygaud->audio + p_rbuf->wraddr); 415 writel(regval, aio->cygaud->audio + p_rbuf->rdaddr); 416 } 417 } 418 419 /* 420 * ESR0/1/3 status Description 421 * 0x1 I2S0_out port caused interrupt 422 * 0x2 I2S1_out port caused interrupt 423 * 0x4 I2S2_out port caused interrupt 424 * 0x8 SPDIF_out port caused interrupt 425 */ 426 static void handle_playback_irq(struct cygnus_audio *cygaud) 427 { 428 void __iomem *audio_io; 429 u32 port; 430 u32 esr_status0, esr_status1, esr_status3; 431 432 audio_io = cygaud->audio; 433 434 /* 435 * ESR status gets updates with/without interrupts enabled. 436 * So, check the ESR mask, which provides interrupt enable/ 437 * disable status and use it to determine which ESR status 438 * should be serviced. 439 */ 440 esr_status0 = readl(audio_io + ESR0_STATUS_OFFSET); 441 esr_status0 &= ~readl(audio_io + ESR0_MASK_STATUS_OFFSET); 442 esr_status1 = readl(audio_io + ESR1_STATUS_OFFSET); 443 esr_status1 &= ~readl(audio_io + ESR1_MASK_STATUS_OFFSET); 444 esr_status3 = readl(audio_io + ESR3_STATUS_OFFSET); 445 esr_status3 &= ~readl(audio_io + ESR3_MASK_STATUS_OFFSET); 446 447 for (port = 0; port < CYGNUS_MAX_PLAYBACK_PORTS; port++) { 448 u32 esrmask = BIT(port); 449 450 /* 451 * Ringbuffer or FIFO underflow 452 * If we get this interrupt then, it is also true that we have 453 * not yet responded to the freemark interrupt. 454 * Log a debug message. The freemark handler below will 455 * handle getting everything going again. 456 */ 457 if ((esrmask & esr_status1) || (esrmask & esr_status0)) { 458 dev_dbg(cygaud->dev, 459 "Underrun: esr0=0x%x, esr1=0x%x esr3=0x%x\n", 460 esr_status0, esr_status1, esr_status3); 461 } 462 463 /* 464 * Freemark is hit. This is the normal interrupt. 465 * In typical operation the read and write regs will be equal 466 */ 467 if (esrmask & esr_status3) { 468 struct snd_pcm_substream *playstr; 469 470 playstr = cygaud->portinfo[port].play_stream; 471 cygnus_pcm_period_elapsed(playstr); 472 } 473 } 474 475 /* Clear ESR interrupt */ 476 writel(esr_status0, audio_io + ESR0_STATUS_CLR_OFFSET); 477 writel(esr_status1, audio_io + ESR1_STATUS_CLR_OFFSET); 478 writel(esr_status3, audio_io + ESR3_STATUS_CLR_OFFSET); 479 /* Rearm freemark logic by writing 1 to the correct bit */ 480 writel(esr_status3, audio_io + BF_REARM_FREE_MARK_OFFSET); 481 } 482 483 /* 484 * ESR2/4 status Description 485 * 0x1 I2S0_in port caused interrupt 486 * 0x2 I2S1_in port caused interrupt 487 * 0x4 I2S2_in port caused interrupt 488 */ 489 static void handle_capture_irq(struct cygnus_audio *cygaud) 490 { 491 void __iomem *audio_io; 492 u32 port; 493 u32 esr_status2, esr_status4; 494 495 audio_io = cygaud->audio; 496 497 /* 498 * ESR status gets updates with/without interrupts enabled. 499 * So, check the ESR mask, which provides interrupt enable/ 500 * disable status and use it to determine which ESR status 501 * should be serviced. 502 */ 503 esr_status2 = readl(audio_io + ESR2_STATUS_OFFSET); 504 esr_status2 &= ~readl(audio_io + ESR2_MASK_STATUS_OFFSET); 505 esr_status4 = readl(audio_io + ESR4_STATUS_OFFSET); 506 esr_status4 &= ~readl(audio_io + ESR4_MASK_STATUS_OFFSET); 507 508 for (port = 0; port < CYGNUS_MAX_CAPTURE_PORTS; port++) { 509 u32 esrmask = BIT(port); 510 511 /* 512 * Ringbuffer or FIFO overflow 513 * If we get this interrupt then, it is also true that we have 514 * not yet responded to the fullmark interrupt. 515 * Log a debug message. The fullmark handler below will 516 * handle getting everything going again. 517 */ 518 if (esrmask & esr_status2) 519 dev_dbg(cygaud->dev, 520 "Overflow: esr2=0x%x\n", esr_status2); 521 522 if (esrmask & esr_status4) { 523 struct snd_pcm_substream *capstr; 524 525 capstr = cygaud->portinfo[port].capture_stream; 526 cygnus_pcm_period_elapsed(capstr); 527 } 528 } 529 530 writel(esr_status2, audio_io + ESR2_STATUS_CLR_OFFSET); 531 writel(esr_status4, audio_io + ESR4_STATUS_CLR_OFFSET); 532 /* Rearm fullmark logic by writing 1 to the correct bit */ 533 writel(esr_status4, audio_io + BF_REARM_FULL_MARK_OFFSET); 534 } 535 536 static irqreturn_t cygnus_dma_irq(int irq, void *data) 537 { 538 u32 r5_status; 539 struct cygnus_audio *cygaud = data; 540 541 /* 542 * R5 status bits Description 543 * 0 ESR0 (playback FIFO interrupt) 544 * 1 ESR1 (playback rbuf interrupt) 545 * 2 ESR2 (capture rbuf interrupt) 546 * 3 ESR3 (Freemark play. interrupt) 547 * 4 ESR4 (Fullmark capt. interrupt) 548 */ 549 r5_status = readl(cygaud->audio + INTH_R5F_STATUS_OFFSET); 550 551 if (!(r5_status & (ANY_PLAYBACK_IRQ | ANY_CAPTURE_IRQ))) 552 return IRQ_NONE; 553 554 /* If playback interrupt happened */ 555 if (ANY_PLAYBACK_IRQ & r5_status) { 556 handle_playback_irq(cygaud); 557 writel(ANY_PLAYBACK_IRQ & r5_status, 558 cygaud->audio + INTH_R5F_CLEAR_OFFSET); 559 } 560 561 /* If capture interrupt happened */ 562 if (ANY_CAPTURE_IRQ & r5_status) { 563 handle_capture_irq(cygaud); 564 writel(ANY_CAPTURE_IRQ & r5_status, 565 cygaud->audio + INTH_R5F_CLEAR_OFFSET); 566 } 567 568 return IRQ_HANDLED; 569 } 570 571 static int cygnus_pcm_open(struct snd_soc_component *component, 572 struct snd_pcm_substream *substream) 573 { 574 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 575 struct snd_pcm_runtime *runtime = substream->runtime; 576 struct cygnus_aio_port *aio; 577 int ret; 578 579 aio = cygnus_dai_get_dma_data(substream); 580 if (!aio) 581 return -ENODEV; 582 583 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); 584 585 snd_soc_set_runtime_hwparams(substream, &cygnus_pcm_hw); 586 587 ret = snd_pcm_hw_constraint_step(runtime, 0, 588 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, PERIOD_BYTES_MIN); 589 if (ret < 0) 590 return ret; 591 592 ret = snd_pcm_hw_constraint_step(runtime, 0, 593 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, PERIOD_BYTES_MIN); 594 if (ret < 0) 595 return ret; 596 /* 597 * Keep track of which substream belongs to which port. 598 * This info is needed by snd_pcm_period_elapsed() in irq_handler 599 */ 600 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 601 aio->play_stream = substream; 602 else 603 aio->capture_stream = substream; 604 605 return 0; 606 } 607 608 static int cygnus_pcm_close(struct snd_soc_component *component, 609 struct snd_pcm_substream *substream) 610 { 611 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 612 struct cygnus_aio_port *aio; 613 614 aio = cygnus_dai_get_dma_data(substream); 615 616 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); 617 618 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 619 aio->play_stream = NULL; 620 else 621 aio->capture_stream = NULL; 622 623 if (!aio->play_stream && !aio->capture_stream) 624 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "freed port %d\n", aio->portnum); 625 626 return 0; 627 } 628 629 static int cygnus_pcm_prepare(struct snd_soc_component *component, 630 struct snd_pcm_substream *substream) 631 { 632 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 633 struct snd_pcm_runtime *runtime = substream->runtime; 634 struct cygnus_aio_port *aio; 635 unsigned long bufsize, periodsize; 636 bool is_play; 637 u32 start; 638 struct ringbuf_regs *p_rbuf = NULL; 639 640 aio = cygnus_dai_get_dma_data(substream); 641 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); 642 643 bufsize = snd_pcm_lib_buffer_bytes(substream); 644 periodsize = snd_pcm_lib_period_bytes(substream); 645 646 dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s (buf_size %lu) (period_size %lu)\n", 647 __func__, bufsize, periodsize); 648 649 configure_ringbuf_regs(substream); 650 651 p_rbuf = get_ringbuf(substream); 652 653 start = runtime->dma_addr; 654 655 is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 1 : 0; 656 657 ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, 658 periodsize, bufsize); 659 660 return 0; 661 } 662 663 static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component, 664 struct snd_pcm_substream *substream) 665 { 666 struct cygnus_aio_port *aio; 667 unsigned int res = 0, cur = 0, base = 0; 668 struct ringbuf_regs *p_rbuf = NULL; 669 670 aio = cygnus_dai_get_dma_data(substream); 671 672 /* 673 * Get the offset of the current read (for playack) or write 674 * index (for capture). Report this value back to the asoc framework. 675 */ 676 p_rbuf = get_ringbuf(substream); 677 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 678 cur = readl(aio->cygaud->audio + p_rbuf->rdaddr); 679 else 680 cur = readl(aio->cygaud->audio + p_rbuf->wraddr); 681 682 base = readl(aio->cygaud->audio + p_rbuf->baseaddr); 683 684 /* 685 * Mask off the MSB of the rdaddr,wraddr and baseaddr 686 * since MSB is not part of the address 687 */ 688 res = (cur & 0x7fffffff) - (base & 0x7fffffff); 689 690 return bytes_to_frames(substream->runtime, res); 691 } 692 693 static int cygnus_dma_new(struct snd_soc_component *component, 694 struct snd_soc_pcm_runtime *rtd) 695 { 696 size_t size = cygnus_pcm_hw.buffer_bytes_max; 697 struct snd_card *card = rtd->card->snd_card; 698 699 if (!card->dev->dma_mask) 700 card->dev->dma_mask = &cygnus_dma_dmamask; 701 if (!card->dev->coherent_dma_mask) 702 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 703 704 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, 705 card->dev, size, size); 706 707 return 0; 708 } 709 710 static struct snd_soc_component_driver cygnus_soc_platform = { 711 .open = cygnus_pcm_open, 712 .close = cygnus_pcm_close, 713 .prepare = cygnus_pcm_prepare, 714 .trigger = cygnus_pcm_trigger, 715 .pointer = cygnus_pcm_pointer, 716 .pcm_construct = cygnus_dma_new, 717 }; 718 719 int cygnus_soc_platform_register(struct device *dev, 720 struct cygnus_audio *cygaud) 721 { 722 int rc; 723 724 dev_dbg(dev, "%s Enter\n", __func__); 725 726 rc = devm_request_irq(dev, cygaud->irq_num, cygnus_dma_irq, 727 IRQF_SHARED, "cygnus-audio", cygaud); 728 if (rc) { 729 dev_err(dev, "%s request_irq error %d\n", __func__, rc); 730 return rc; 731 } 732 733 rc = devm_snd_soc_register_component(dev, &cygnus_soc_platform, 734 NULL, 0); 735 if (rc) { 736 dev_err(dev, "%s failed\n", __func__); 737 return rc; 738 } 739 740 return 0; 741 } 742 743 int cygnus_soc_platform_unregister(struct device *dev) 744 { 745 return 0; 746 } 747 748 MODULE_LICENSE("GPL v2"); 749 MODULE_AUTHOR("Broadcom"); 750 MODULE_DESCRIPTION("Cygnus ASoC PCM module"); 751