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

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: fsl: fsl_qmc_audio: Identify the QMC channel involved in completion routines

The current QMC audio driver uses only one QMC channel per DAI. The
context used by QMC channel transfer (read and write) completion
routines does not contains any QMC channel and the only one available
per DAI is used to schedule the next transfer.
This works pretty well with only one QMC channel per DAI.

The future support for non-inlerleave mode will use several QMC channel
per DAI. In that case, QMC channel transfer completion routines need to
identify the QMC channel related to the completion.

In order to fill this lack, even if identifying the current QMC channel
among several QMC channels is not needed for the current code, add one
indirection level and introduce the qmc_dai_chan data structrure.
This structure contains the QMC channel involved in the completion and
refererences to the runtime context (capture and playback) used by the
DAI.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
Link: https://patch.msgid.link/20240701113038.55144-5-herve.codina@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Herve Codina and committed by
Mark Brown
5e51a1f9 42212b2c

+47 -25
+47 -25
sound/soc/fsl/fsl_qmc_audio.c
··· 17 17 #include <sound/pcm_params.h> 18 18 #include <sound/soc.h> 19 19 20 + struct qmc_dai_chan { 21 + struct qmc_dai_prtd *prtd_tx; 22 + struct qmc_dai_prtd *prtd_rx; 23 + struct qmc_chan *qmc_chan; 24 + }; 25 + 20 26 struct qmc_dai { 21 27 char *name; 22 28 int id; 23 29 struct device *dev; 24 - struct qmc_chan *qmc_chan; 25 30 unsigned int nb_tx_ts; 26 31 unsigned int nb_rx_ts; 32 + struct qmc_dai_chan chan; 27 33 }; 28 34 29 35 struct qmc_audio { ··· 92 86 93 87 static void qmc_audio_pcm_write_complete(void *context) 94 88 { 95 - struct qmc_dai_prtd *prtd = context; 89 + struct qmc_dai_chan *chan = context; 90 + struct qmc_dai_prtd *prtd; 96 91 int ret; 92 + 93 + prtd = chan->prtd_tx; 97 94 98 95 prtd->buffer_ended += prtd->period_size; 99 96 if (prtd->buffer_ended >= prtd->buffer_size) ··· 106 97 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 107 98 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 108 99 109 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 100 + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, 110 101 prtd->ch_dma_addr_current, prtd->ch_dma_size, 111 - qmc_audio_pcm_write_complete, prtd); 102 + qmc_audio_pcm_write_complete, 103 + &prtd->qmc_dai->chan); 112 104 if (ret) { 113 105 dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", 114 106 ret); ··· 120 110 121 111 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) 122 112 { 123 - struct qmc_dai_prtd *prtd = context; 113 + struct qmc_dai_chan *chan = context; 114 + struct qmc_dai_prtd *prtd; 124 115 int ret; 116 + 117 + prtd = chan->prtd_rx; 125 118 126 119 if (length != prtd->ch_dma_size) { 127 120 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", ··· 139 126 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 140 127 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 141 128 142 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 129 + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, 143 130 prtd->ch_dma_addr_current, prtd->ch_dma_size, 144 - qmc_audio_pcm_read_complete, prtd); 131 + qmc_audio_pcm_read_complete, 132 + &prtd->qmc_dai->chan); 145 133 if (ret) { 146 134 dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", 147 135 ret); ··· 165 151 switch (cmd) { 166 152 case SNDRV_PCM_TRIGGER_START: 167 153 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 154 + prtd->qmc_dai->chan.prtd_tx = prtd; 155 + 168 156 /* Submit first chunk ... */ 169 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 157 + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, 170 158 prtd->ch_dma_addr_current, prtd->ch_dma_size, 171 - qmc_audio_pcm_write_complete, prtd); 159 + qmc_audio_pcm_write_complete, 160 + &prtd->qmc_dai->chan); 172 161 if (ret) { 173 162 dev_err(component->dev, "write_submit failed %d\n", 174 163 ret); ··· 184 167 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 185 168 186 169 /* ... and send it */ 187 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 170 + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, 188 171 prtd->ch_dma_addr_current, prtd->ch_dma_size, 189 - qmc_audio_pcm_write_complete, prtd); 172 + qmc_audio_pcm_write_complete, 173 + &prtd->qmc_dai->chan); 190 174 if (ret) { 191 175 dev_err(component->dev, "write_submit failed %d\n", 192 176 ret); 193 177 return ret; 194 178 } 195 179 } else { 180 + prtd->qmc_dai->chan.prtd_rx = prtd; 181 + 196 182 /* Submit first chunk ... */ 197 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 183 + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, 198 184 prtd->ch_dma_addr_current, prtd->ch_dma_size, 199 - qmc_audio_pcm_read_complete, prtd); 185 + qmc_audio_pcm_read_complete, 186 + &prtd->qmc_dai->chan); 200 187 if (ret) { 201 188 dev_err(component->dev, "read_submit failed %d\n", 202 189 ret); ··· 213 192 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 214 193 215 194 /* ... and send it */ 216 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 195 + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, 217 196 prtd->ch_dma_addr_current, prtd->ch_dma_size, 218 - qmc_audio_pcm_read_complete, prtd); 197 + qmc_audio_pcm_read_complete, 198 + &prtd->qmc_dai->chan); 219 199 if (ret) { 220 200 dev_err(component->dev, "write_submit failed %d\n", 221 201 ret); ··· 511 489 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 512 490 chan_param.mode = QMC_TRANSPARENT; 513 491 chan_param.transp.max_rx_buf_size = params_period_bytes(params); 514 - ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); 492 + ret = qmc_chan_set_param(qmc_dai->chan.qmc_chan, &chan_param); 515 493 if (ret) { 516 494 dev_err(dai->dev, "set param failed %d\n", 517 495 ret); ··· 542 520 case SNDRV_PCM_TRIGGER_START: 543 521 case SNDRV_PCM_TRIGGER_RESUME: 544 522 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 545 - ret = qmc_chan_start(qmc_dai->qmc_chan, direction); 523 + ret = qmc_chan_start(qmc_dai->chan.qmc_chan, direction); 546 524 if (ret) 547 525 return ret; 548 526 break; 549 527 550 528 case SNDRV_PCM_TRIGGER_STOP: 551 - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 529 + ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); 552 530 if (ret) 553 531 return ret; 554 - ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); 532 + ret = qmc_chan_reset(qmc_dai->chan.qmc_chan, direction); 555 533 if (ret) 556 534 return ret; 557 535 break; 558 536 559 537 case SNDRV_PCM_TRIGGER_SUSPEND: 560 538 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 561 - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 539 + ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction); 562 540 if (ret) 563 541 return ret; 564 542 break; ··· 635 613 if (!qmc_dai->name) 636 614 return -ENOMEM; 637 615 638 - qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, 639 - "fsl,qmc-chan"); 640 - if (IS_ERR(qmc_dai->qmc_chan)) { 641 - ret = PTR_ERR(qmc_dai->qmc_chan); 616 + qmc_dai->chan.qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, 617 + "fsl,qmc-chan"); 618 + if (IS_ERR(qmc_dai->chan.qmc_chan)) { 619 + ret = PTR_ERR(qmc_dai->chan.qmc_chan); 642 620 return dev_err_probe(qmc_audio->dev, ret, 643 621 "dai %d get QMC channel failed\n", qmc_dai->id); 644 622 } ··· 646 624 qmc_soc_dai_driver->id = qmc_dai->id; 647 625 qmc_soc_dai_driver->name = qmc_dai->name; 648 626 649 - ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); 627 + ret = qmc_chan_get_info(qmc_dai->chan.qmc_chan, &info); 650 628 if (ret) { 651 629 dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", 652 630 qmc_dai->id, ret);