Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: sh: rz-ssi: Add full duplex support

Add full duplex support, to support simultaneous
playback/record on the same ssi channel.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://patch.msgid.link/20240715092322.119879-1-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Biju Das and committed by
Mark Brown
4f8cd05a b3f35bae

+198 -91
+198 -91
sound/soc/sh/rz-ssi.c
··· 52 52 #define SSIFCR_RIE BIT(2) 53 53 #define SSIFCR_TFRST BIT(1) 54 54 #define SSIFCR_RFRST BIT(0) 55 + #define SSIFCR_FIFO_RST (SSIFCR_TFRST | SSIFCR_RFRST) 55 56 56 57 #define SSIFSR_TDC_MASK 0x3f 57 58 #define SSIFSR_TDC_SHIFT 24 ··· 131 130 bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */ 132 131 bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */ 133 132 bool dma_rt; 133 + 134 + /* Full duplex communication support */ 135 + struct { 136 + unsigned int rate; 137 + unsigned int channels; 138 + unsigned int sample_width; 139 + unsigned int sample_bits; 140 + } hw_params_cache; 134 141 }; 135 142 136 143 static void rz_ssi_dma_complete(void *data); ··· 215 206 spin_unlock_irqrestore(&ssi->lock, flags); 216 207 217 208 return ret; 209 + } 210 + 211 + static inline bool rz_ssi_is_stream_running(struct rz_ssi_stream *strm) 212 + { 213 + return strm->substream && strm->running; 218 214 } 219 215 220 216 static void rz_ssi_stream_init(struct rz_ssi_stream *strm, ··· 317 303 return 0; 318 304 } 319 305 320 - static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) 321 - { 322 - bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); 323 - u32 ssicr, ssifcr; 324 - 325 - ssicr = rz_ssi_reg_readl(ssi, SSICR); 326 - ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF; 327 - 328 - /* FIFO interrupt thresholds */ 329 - if (rz_ssi_is_dma_enabled(ssi)) 330 - rz_ssi_reg_writel(ssi, SSISCR, 0); 331 - else 332 - rz_ssi_reg_writel(ssi, SSISCR, 333 - SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | 334 - SSISCR_RDFS(0)); 335 - 336 - /* enable IRQ */ 337 - if (is_play) { 338 - ssicr |= SSICR_TUIEN | SSICR_TOIEN; 339 - ssifcr |= SSIFCR_TIE | SSIFCR_RFRST; 340 - } else { 341 - ssicr |= SSICR_RUIEN | SSICR_ROIEN; 342 - ssifcr |= SSIFCR_RIE | SSIFCR_TFRST; 343 - } 344 - 345 - rz_ssi_reg_writel(ssi, SSICR, ssicr); 346 - rz_ssi_reg_writel(ssi, SSIFCR, ssifcr); 347 - 348 - /* Clear all error flags */ 349 - rz_ssi_reg_mask_setl(ssi, SSISR, 350 - (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | 351 - SSISR_RUIRQ), 0); 352 - 353 - strm->running = 1; 354 - ssicr |= is_play ? SSICR_TEN : SSICR_REN; 355 - rz_ssi_reg_writel(ssi, SSICR, ssicr); 356 - 357 - return 0; 358 - } 359 - 360 - static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) 306 + static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) 361 307 { 362 308 int timeout; 363 - 364 - strm->running = 0; 365 - 366 - /* Disable TX/RX */ 367 - rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); 368 - 369 - /* Cancel all remaining DMA transactions */ 370 - if (rz_ssi_is_dma_enabled(ssi)) 371 - dmaengine_terminate_async(strm->dma_ch); 372 309 373 310 /* Disable irqs */ 374 311 rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | ··· 345 380 /* Hold FIFOs in reset */ 346 381 rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, 347 382 SSIFCR_TFRST | SSIFCR_RFRST); 383 + } 384 + 385 + static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) 386 + { 387 + bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); 388 + bool is_full_duplex; 389 + u32 ssicr, ssifcr; 390 + 391 + is_full_duplex = rz_ssi_is_stream_running(&ssi->playback) || 392 + rz_ssi_is_stream_running(&ssi->capture); 393 + ssicr = rz_ssi_reg_readl(ssi, SSICR); 394 + ssifcr = rz_ssi_reg_readl(ssi, SSIFCR); 395 + if (!is_full_duplex) { 396 + ssifcr &= ~0xF; 397 + } else { 398 + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); 399 + rz_ssi_set_idle(ssi); 400 + ssifcr &= ~SSIFCR_FIFO_RST; 401 + } 402 + 403 + /* FIFO interrupt thresholds */ 404 + if (rz_ssi_is_dma_enabled(ssi)) 405 + rz_ssi_reg_writel(ssi, SSISCR, 0); 406 + else 407 + rz_ssi_reg_writel(ssi, SSISCR, 408 + SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | 409 + SSISCR_RDFS(0)); 410 + 411 + /* enable IRQ */ 412 + if (is_play) { 413 + ssicr |= SSICR_TUIEN | SSICR_TOIEN; 414 + ssifcr |= SSIFCR_TIE; 415 + if (!is_full_duplex) 416 + ssifcr |= SSIFCR_RFRST; 417 + } else { 418 + ssicr |= SSICR_RUIEN | SSICR_ROIEN; 419 + ssifcr |= SSIFCR_RIE; 420 + if (!is_full_duplex) 421 + ssifcr |= SSIFCR_TFRST; 422 + } 423 + 424 + rz_ssi_reg_writel(ssi, SSICR, ssicr); 425 + rz_ssi_reg_writel(ssi, SSIFCR, ssifcr); 426 + 427 + /* Clear all error flags */ 428 + rz_ssi_reg_mask_setl(ssi, SSISR, 429 + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | 430 + SSISR_RUIRQ), 0); 431 + 432 + strm->running = 1; 433 + if (is_full_duplex) 434 + ssicr |= SSICR_TEN | SSICR_REN; 435 + else 436 + ssicr |= is_play ? SSICR_TEN : SSICR_REN; 437 + 438 + rz_ssi_reg_writel(ssi, SSICR, ssicr); 439 + 440 + return 0; 441 + } 442 + 443 + static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) 444 + { 445 + strm->running = 0; 446 + 447 + if (rz_ssi_is_stream_running(&ssi->playback) || 448 + rz_ssi_is_stream_running(&ssi->capture)) 449 + return 0; 450 + 451 + /* Disable TX/RX */ 452 + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); 453 + 454 + /* Cancel all remaining DMA transactions */ 455 + if (rz_ssi_is_dma_enabled(ssi)) 456 + dmaengine_terminate_async(strm->dma_ch); 457 + 458 + rz_ssi_set_idle(ssi); 348 459 349 460 return 0; 350 461 } ··· 553 512 554 513 static irqreturn_t rz_ssi_interrupt(int irq, void *data) 555 514 { 556 - struct rz_ssi_stream *strm = NULL; 515 + struct rz_ssi_stream *strm_playback = NULL; 516 + struct rz_ssi_stream *strm_capture = NULL; 557 517 struct rz_ssi_priv *ssi = data; 558 518 u32 ssisr = rz_ssi_reg_readl(ssi, SSISR); 559 519 560 520 if (ssi->playback.substream) 561 - strm = &ssi->playback; 562 - else if (ssi->capture.substream) 563 - strm = &ssi->capture; 564 - else 521 + strm_playback = &ssi->playback; 522 + if (ssi->capture.substream) 523 + strm_capture = &ssi->capture; 524 + 525 + if (!strm_playback && !strm_capture) 565 526 return IRQ_HANDLED; /* Left over TX/RX interrupt */ 566 527 567 528 if (irq == ssi->irq_int) { /* error or idle */ 568 - if (ssisr & SSISR_TUIRQ) 569 - strm->uerr_num++; 570 - if (ssisr & SSISR_TOIRQ) 571 - strm->oerr_num++; 572 - if (ssisr & SSISR_RUIRQ) 573 - strm->uerr_num++; 574 - if (ssisr & SSISR_ROIRQ) 575 - strm->oerr_num++; 529 + bool is_stopped = false; 530 + int i, count; 576 531 577 - if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ | 578 - SSISR_ROIRQ)) { 579 - /* Error handling */ 580 - /* You must reset (stop/restart) after each interrupt */ 581 - rz_ssi_stop(ssi, strm); 532 + if (rz_ssi_is_dma_enabled(ssi)) 533 + count = 4; 534 + else 535 + count = 1; 582 536 583 - /* Clear all flags */ 584 - rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | 585 - SSISR_TUIRQ | SSISR_ROIRQ | 586 - SSISR_RUIRQ, 0); 537 + if (ssisr & (SSISR_RUIRQ | SSISR_ROIRQ | SSISR_TUIRQ | SSISR_TOIRQ)) 538 + is_stopped = true; 587 539 588 - /* Add/remove more data */ 589 - strm->transfer(ssi, strm); 540 + if (ssi->capture.substream && is_stopped) { 541 + if (ssisr & SSISR_RUIRQ) 542 + strm_capture->uerr_num++; 543 + if (ssisr & SSISR_ROIRQ) 544 + strm_capture->oerr_num++; 590 545 591 - /* Resume */ 592 - rz_ssi_start(ssi, strm); 546 + rz_ssi_stop(ssi, strm_capture); 593 547 } 548 + 549 + if (ssi->playback.substream && is_stopped) { 550 + if (ssisr & SSISR_TUIRQ) 551 + strm_playback->uerr_num++; 552 + if (ssisr & SSISR_TOIRQ) 553 + strm_playback->oerr_num++; 554 + 555 + rz_ssi_stop(ssi, strm_playback); 556 + } 557 + 558 + /* Clear all flags */ 559 + rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | SSISR_TUIRQ | 560 + SSISR_ROIRQ | SSISR_RUIRQ, 0); 561 + 562 + /* Add/remove more data */ 563 + if (ssi->capture.substream && is_stopped) { 564 + for (i = 0; i < count; i++) 565 + strm_capture->transfer(ssi, strm_capture); 566 + } 567 + 568 + if (ssi->playback.substream && is_stopped) { 569 + for (i = 0; i < count; i++) 570 + strm_playback->transfer(ssi, strm_playback); 571 + } 572 + 573 + /* Resume */ 574 + if (ssi->playback.substream && is_stopped) 575 + rz_ssi_start(ssi, &ssi->playback); 576 + if (ssi->capture.substream && is_stopped) 577 + rz_ssi_start(ssi, &ssi->capture); 594 578 } 595 579 596 - if (!strm->running) 580 + if (!rz_ssi_is_stream_running(&ssi->playback) && 581 + !rz_ssi_is_stream_running(&ssi->capture)) 597 582 return IRQ_HANDLED; 598 583 599 584 /* tx data empty */ 600 - if (irq == ssi->irq_tx) 601 - strm->transfer(ssi, &ssi->playback); 585 + if (irq == ssi->irq_tx && rz_ssi_is_stream_running(&ssi->playback)) 586 + strm_playback->transfer(ssi, &ssi->playback); 602 587 603 588 /* rx data full */ 604 - if (irq == ssi->irq_rx) { 605 - strm->transfer(ssi, &ssi->capture); 589 + if (irq == ssi->irq_rx && rz_ssi_is_stream_running(&ssi->capture)) { 590 + strm_capture->transfer(ssi, &ssi->capture); 606 591 rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); 607 592 } 608 593 609 594 if (irq == ssi->irq_rt) { 610 - struct snd_pcm_substream *substream = strm->substream; 611 - 612 - if (rz_ssi_stream_is_play(ssi, substream)) { 613 - strm->transfer(ssi, &ssi->playback); 595 + if (ssi->playback.substream) { 596 + strm_playback->transfer(ssi, &ssi->playback); 614 597 } else { 615 - strm->transfer(ssi, &ssi->capture); 598 + strm_capture->transfer(ssi, &ssi->capture); 616 599 rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); 617 600 } 618 601 } ··· 796 731 switch (cmd) { 797 732 case SNDRV_PCM_TRIGGER_START: 798 733 /* Soft Reset */ 799 - rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); 800 - rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); 801 - udelay(5); 734 + if (!rz_ssi_is_stream_running(&ssi->playback) && 735 + !rz_ssi_is_stream_running(&ssi->capture)) { 736 + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); 737 + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); 738 + udelay(5); 739 + } 802 740 803 741 rz_ssi_stream_init(strm, substream); 804 742 ··· 892 824 return 0; 893 825 } 894 826 827 + static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate, 828 + unsigned int channels, 829 + unsigned int sample_width, 830 + unsigned int sample_bits) 831 + { 832 + if (ssi->hw_params_cache.rate != rate || 833 + ssi->hw_params_cache.channels != channels || 834 + ssi->hw_params_cache.sample_width != sample_width || 835 + ssi->hw_params_cache.sample_bits != sample_bits) 836 + return false; 837 + 838 + return true; 839 + } 840 + 841 + static void rz_ssi_cache_hw_params(struct rz_ssi_priv *ssi, unsigned int rate, 842 + unsigned int channels, 843 + unsigned int sample_width, 844 + unsigned int sample_bits) 845 + { 846 + ssi->hw_params_cache.rate = rate; 847 + ssi->hw_params_cache.channels = channels; 848 + ssi->hw_params_cache.sample_width = sample_width; 849 + ssi->hw_params_cache.sample_bits = sample_bits; 850 + } 851 + 895 852 static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, 896 853 struct snd_pcm_hw_params *params, 897 854 struct snd_soc_dai *dai) 898 855 { 899 856 struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); 857 + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); 900 858 unsigned int sample_bits = hw_param_interval(params, 901 859 SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; 902 860 unsigned int channels = params_channels(params); 861 + unsigned int rate = params_rate(params); 903 862 904 863 if (sample_bits != 16) { 905 864 dev_err(ssi->dev, "Unsupported sample width: %d\n", ··· 940 845 return -EINVAL; 941 846 } 942 847 943 - return rz_ssi_clk_setup(ssi, params_rate(params), 944 - params_channels(params)); 848 + if (rz_ssi_is_stream_running(&ssi->playback) || 849 + rz_ssi_is_stream_running(&ssi->capture)) { 850 + if (rz_ssi_is_valid_hw_params(ssi, rate, channels, 851 + strm->sample_width, sample_bits)) 852 + return 0; 853 + 854 + dev_err(ssi->dev, "Full duplex needs same HW params\n"); 855 + return -EINVAL; 856 + } 857 + 858 + rz_ssi_cache_hw_params(ssi, rate, channels, strm->sample_width, 859 + sample_bits); 860 + 861 + return rz_ssi_clk_setup(ssi, rate, channels); 945 862 } 946 863 947 864 static const struct snd_soc_dai_ops rz_ssi_dai_ops = {