#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 {
 
 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;
        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);
 
 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);
        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);
        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);
                                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);
                                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);
        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);
        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;
        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);
        }
        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);