@@ -166,7 +166,7 @@
struct qmc_xfer_desc {
union {
void (*tx_complete)(void *context);
- void (*rx_complete)(void *context, size_t length);
+ void (*rx_complete)(void *context, size_t length, unsigned int flags);
};
void *context;
};
@@ -421,7 +421,8 @@ static void qmc_chan_write_done(struct qmc_chan *chan)
}
int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
- void (*complete)(void *context, size_t length), void *context)
+ void (*complete)(void *context, size_t length, unsigned int flags),
+ void *context)
{
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
@@ -454,6 +455,10 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
xfer_desc->rx_complete = complete;
xfer_desc->context = context;
+ /* Clear previous status flags */
+ ctrl &= ~(QMC_BD_RX_L | QMC_BD_RX_F | QMC_BD_RX_LG | QMC_BD_RX_NO |
+ QMC_BD_RX_AB | QMC_BD_RX_CR);
+
/* Activate the descriptor */
ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB);
wmb(); /* Be sure to flush data before descriptor activation */
@@ -485,7 +490,7 @@ EXPORT_SYMBOL(qmc_chan_read_submit);
static void qmc_chan_read_done(struct qmc_chan *chan)
{
- void (*complete)(void *context, size_t size);
+ void (*complete)(void *context, size_t size, unsigned int flags);
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
cbd_t __iomem *bd;
@@ -527,7 +532,23 @@ static void qmc_chan_read_done(struct qmc_chan *chan)
if (complete) {
spin_unlock_irqrestore(&chan->rx_lock, flags);
- complete(context, datalen);
+
+ /*
+ * Avoid conversion between internal hardware flags and
+ * the software API flags.
+ * -> Be sure that the software API flags are consistent
+ * with the hardware flags
+ */
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_LAST != QMC_BD_RX_L);
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_FIRST != QMC_BD_RX_F);
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_OVF != QMC_BD_RX_LG);
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_UNA != QMC_BD_RX_NO);
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_ABORT != QMC_BD_RX_AB);
+ BUILD_BUG_ON(QMC_RX_FLAG_HDLC_CRC != QMC_BD_RX_CR);
+
+ complete(context, datalen,
+ ctrl & (QMC_BD_RX_L | QMC_BD_RX_F | QMC_BD_RX_LG |
+ QMC_BD_RX_NO | QMC_BD_RX_AB | QMC_BD_RX_CR));
spin_lock_irqsave(&chan->rx_lock, flags);
}
@@ -9,6 +9,7 @@
#ifndef __SOC_FSL_QMC_H__
#define __SOC_FSL_QMC_H__
+#include <linux/bits.h>
#include <linux/types.h>
struct device_node;
@@ -56,8 +57,20 @@ int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param
int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
void (*complete)(void *context), void *context);
+/* Flags available (ORed) for read complete() flags parameter in HDLC mode.
+ * No flags are available in transparent mode and the read complete() flags
+ * parameter has no meaning in transparent mode.
+ */
+#define QMC_RX_FLAG_HDLC_LAST BIT(11) /* Last in frame */
+#define QMC_RX_FLAG_HDLC_FIRST BIT(10) /* First in frame */
+#define QMC_RX_FLAG_HDLC_OVF BIT(5) /* Data overflow */
+#define QMC_RX_FLAG_HDLC_UNA BIT(4) /* Unaligned (ie. bits received not multiple of 8) */
+#define QMC_RX_FLAG_HDLC_ABORT BIT(3) /* Received an abort sequence (seven consecutive ones) */
+#define QMC_RX_FLAG_HDLC_CRC BIT(2) /* CRC error */
+
int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
- void (*complete)(void *context, size_t length),
+ void (*complete)(void *context, size_t length,
+ unsigned int flags),
void *context);
#define QMC_CHAN_READ (1<<0)
@@ -99,7 +99,7 @@ static void qmc_audio_pcm_write_complete(void *context)
snd_pcm_period_elapsed(prtd->substream);
}
-static void qmc_audio_pcm_read_complete(void *context, size_t length)
+static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
{
struct qmc_dai_prtd *prtd = context;
int ret;