aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/fsl/fsl_qmc_audio.c72
1 files changed, 47 insertions, 25 deletions
diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
index e8281e548746..b07770257bad 100644
--- a/sound/soc/fsl/fsl_qmc_audio.c
+++ b/sound/soc/fsl/fsl_qmc_audio.c
@@ -17,13 +17,19 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
+struct qmc_dai_chan {
+ struct qmc_dai_prtd *prtd_tx;
+ struct qmc_dai_prtd *prtd_rx;
+ struct qmc_chan *qmc_chan;
+};
+
struct qmc_dai {
char *name;
int id;
struct device *dev;
- struct qmc_chan *qmc_chan;
unsigned int nb_tx_ts;
unsigned int nb_rx_ts;
+ struct qmc_dai_chan chan;
};
struct qmc_audio {
@@ -86,9 +92,12 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
static void qmc_audio_pcm_write_complete(void *context)
{
- struct qmc_dai_prtd *prtd = context;
+ struct qmc_dai_chan *chan = context;
+ struct qmc_dai_prtd *prtd;
int ret;
+ prtd = chan->prtd_tx;
+
prtd->buffer_ended += prtd->period_size;
if (prtd->buffer_ended >= prtd->buffer_size)
prtd->buffer_ended = 0;
@@ -97,9 +106,10 @@ static void qmc_audio_pcm_write_complete(void *context)
if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
- ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_write_complete, prtd);
+ qmc_audio_pcm_write_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n",
ret);
@@ -110,9 +120,12 @@ static void qmc_audio_pcm_write_complete(void *context)
static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
{
- struct qmc_dai_prtd *prtd = context;
+ struct qmc_dai_chan *chan = context;
+ struct qmc_dai_prtd *prtd;
int ret;
+ prtd = chan->prtd_rx;
+
if (length != prtd->ch_dma_size) {
dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n",
length, prtd->ch_dma_size);
@@ -126,9 +139,10 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i
if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
- ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_read_complete, prtd);
+ qmc_audio_pcm_read_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n",
ret);
@@ -151,10 +165,13 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ prtd->qmc_dai->chan.prtd_tx = prtd;
+
/* Submit first chunk ... */
- ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_write_complete, prtd);
+ qmc_audio_pcm_write_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(component->dev, "write_submit failed %d\n",
ret);
@@ -167,19 +184,23 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
/* ... and send it */
- ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_write_complete, prtd);
+ qmc_audio_pcm_write_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(component->dev, "write_submit failed %d\n",
ret);
return ret;
}
} else {
+ prtd->qmc_dai->chan.prtd_rx = prtd;
+
/* Submit first chunk ... */
- ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_read_complete, prtd);
+ qmc_audio_pcm_read_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(component->dev, "read_submit failed %d\n",
ret);
@@ -192,9 +213,10 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
/* ... and send it */
- ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
+ ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan,
prtd->ch_dma_addr_current, prtd->ch_dma_size,
- qmc_audio_pcm_read_complete, prtd);
+ qmc_audio_pcm_read_complete,
+ &prtd->qmc_dai->chan);
if (ret) {
dev_err(component->dev, "write_submit failed %d\n",
ret);
@@ -489,7 +511,7 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
chan_param.mode = QMC_TRANSPARENT;
chan_param.transp.max_rx_buf_size = params_period_bytes(params);
- ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param);
+ ret = qmc_chan_set_param(qmc_dai->chan.qmc_chan, &chan_param);
if (ret) {
dev_err(dai->dev, "set param failed %d\n",
ret);
@@ -520,23 +542,23 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ret = qmc_chan_start(qmc_dai->qmc_chan, direction);
+ ret = qmc_chan_start(qmc_dai->chan.qmc_chan, direction);
if (ret)
return ret;
break;
case SNDRV_PCM_TRIGGER_STOP:
- ret = qmc_chan_stop(qmc_dai->qmc_chan, direction);
+ ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction);
if (ret)
return ret;
- ret = qmc_chan_reset(qmc_dai->qmc_chan, direction);
+ ret = qmc_chan_reset(qmc_dai->chan.qmc_chan, direction);
if (ret)
return ret;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ret = qmc_chan_stop(qmc_dai->qmc_chan, direction);
+ ret = qmc_chan_stop(qmc_dai->chan.qmc_chan, direction);
if (ret)
return ret;
break;
@@ -613,10 +635,10 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
if (!qmc_dai->name)
return -ENOMEM;
- qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np,
- "fsl,qmc-chan");
- if (IS_ERR(qmc_dai->qmc_chan)) {
- ret = PTR_ERR(qmc_dai->qmc_chan);
+ qmc_dai->chan.qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np,
+ "fsl,qmc-chan");
+ if (IS_ERR(qmc_dai->chan.qmc_chan)) {
+ ret = PTR_ERR(qmc_dai->chan.qmc_chan);
return dev_err_probe(qmc_audio->dev, ret,
"dai %d get QMC channel failed\n", qmc_dai->id);
}
@@ -624,7 +646,7 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
qmc_soc_dai_driver->id = qmc_dai->id;
qmc_soc_dai_driver->name = qmc_dai->name;
- ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info);
+ ret = qmc_chan_get_info(qmc_dai->chan.qmc_chan, &info);
if (ret) {
dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n",
qmc_dai->id, ret);