I2S-MCC found on SAMA7G5 includes 2 FIFOs (capture and playback). When
FIFOs are enabled, bits I2SMCC_ISRA.TXLRDYx and I2SMCC_ISRA.TXRRDYx must
not be used. Bits I2SMCC_ISRB.TXFFRDY and I2SMCC_ISRB.RXFFRDY must be used
instead.

Signed-off-by: Codrin Ciubotariu <codrin.ciubota...@microchip.com>
---
 sound/soc/atmel/mchp-i2s-mcc.c | 76 +++++++++++++++++++++++++---------
 1 file changed, 56 insertions(+), 20 deletions(-)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 3d13efb11444..f951fa0f39fd 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -176,7 +176,7 @@
  */
 #define MCHP_I2SMCC_MRB_CRAMODE_REGULAR                (1 << 0)
 
-#define MCHP_I2SMCC_MRB_FIFOEN                 BIT(1)
+#define MCHP_I2SMCC_MRB_FIFOEN                 BIT(4)
 
 #define MCHP_I2SMCC_MRB_DMACHUNK_MASK          GENMASK(9, 8)
 #define MCHP_I2SMCC_MRB_DMACHUNK(no_words) \
@@ -230,6 +230,7 @@ static const struct regmap_config 
mchp_i2s_mcc_regmap_config = {
 
 struct mchp_i2s_mcc_soc_data {
        unsigned int    data_pin_pair_num;
+       bool            has_fifo;
 };
 
 struct mchp_i2s_mcc_dev {
@@ -257,7 +258,7 @@ struct mchp_i2s_mcc_dev {
 static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void *dev_id)
 {
        struct mchp_i2s_mcc_dev *dev = dev_id;
-       u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0;
+       u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0, idrb = 0;
        irqreturn_t ret = IRQ_NONE;
 
        regmap_read(dev->regmap, MCHP_I2SMCC_IMRA, &imra);
@@ -275,24 +276,36 @@ static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void 
*dev_id)
         * Tx/Rx ready interrupts are enabled when stopping only, to assure
         * availability and to disable clocks if necessary
         */
-       idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
-                           MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
-       if (idra)
+       if (dev->soc->has_fifo) {
+               idrb |= pendingb & (MCHP_I2SMCC_INT_TXFFRDY |
+                                   MCHP_I2SMCC_INT_RXFFRDY);
+       } else {
+               idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
+                                   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+       }
+       if (idra || idrb)
                ret = IRQ_HANDLED;
 
-       if ((imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
-           (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
-           (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) {
+       if ((!dev->soc->has_fifo &&
+            (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
+            (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
+            (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) ||
+           (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_TXFFRDY)) {
                dev->tx_rdy = 1;
                wake_up_interruptible(&dev->wq_txrdy);
        }
-       if ((imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
-           (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
-           (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) {
+       if ((!dev->soc->has_fifo &&
+            (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
+            (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
+            (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) ||
+           (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_RXFFRDY)) {
                dev->rx_rdy = 1;
                wake_up_interruptible(&dev->wq_rxrdy);
        }
-       regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
+       if (dev->soc->has_fifo)
+               regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, idrb);
+       else
+               regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
 
        return ret;
 }
@@ -664,6 +677,10 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
                }
        }
 
+       /* enable FIFO if available */
+       if (dev->soc->has_fifo)
+               mrb |= MCHP_I2SMCC_MRB_FIFOEN;
+
        /*
         * If we are already running, the wanted setup must be
         * the same with the one that's currently ongoing
@@ -726,8 +743,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream 
*substream,
                if (err == 0) {
                        dev_warn_once(dev->dev,
                                      "Timeout waiting for Tx ready\n");
-                       regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
-                                    MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+                       if (dev->soc->has_fifo)
+                               regmap_write(dev->regmap, MCHP_I2SMCC_IDRB,
+                                            MCHP_I2SMCC_INT_TXFFRDY);
+                       else
+                               regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+                                            
MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+
                        dev->tx_rdy = 1;
                }
        } else {
@@ -737,8 +759,12 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream 
*substream,
                if (err == 0) {
                        dev_warn_once(dev->dev,
                                      "Timeout waiting for Rx ready\n");
-                       regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
-                                    MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+                       if (dev->soc->has_fifo)
+                               regmap_write(dev->regmap, MCHP_I2SMCC_IDRB,
+                                            MCHP_I2SMCC_INT_RXFFRDY);
+                       else
+                               regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+                                            
MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
                        dev->rx_rdy = 1;
                }
        }
@@ -765,7 +791,7 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream 
*substream, int cmd,
        struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai);
        bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        u32 cr = 0;
-       u32 iera = 0;
+       u32 iera = 0, ierb = 0;
        u32 sr;
        int err;
 
@@ -789,7 +815,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream 
*substream, int cmd,
                         * Enable Tx Ready interrupts on all channels
                         * to assure all data is sent
                         */
-                       iera = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels);
+                       if (dev->soc->has_fifo)
+                               ierb = MCHP_I2SMCC_INT_TXFFRDY;
+                       else
+                               iera = 
MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels);
                } else if (!is_playback && (sr & MCHP_I2SMCC_SR_RXEN)) {
                        cr = MCHP_I2SMCC_CR_RXDIS;
                        dev->rx_rdy = 0;
@@ -797,7 +826,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream 
*substream, int cmd,
                         * Enable Rx Ready interrupts on all channels
                         * to assure all data is received
                         */
-                       iera = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels);
+                       if (dev->soc->has_fifo)
+                               ierb = MCHP_I2SMCC_INT_RXFFRDY;
+                       else
+                               iera = 
MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels);
                }
                break;
        default:
@@ -815,7 +847,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream 
*substream, int cmd,
                }
        }
 
-       regmap_write(dev->regmap, MCHP_I2SMCC_IERA, iera);
+       if (dev->soc->has_fifo)
+               regmap_write(dev->regmap, MCHP_I2SMCC_IERB, ierb);
+       else
+               regmap_write(dev->regmap, MCHP_I2SMCC_IERA, iera);
        regmap_write(dev->regmap, MCHP_I2SMCC_CR, cr);
 
        return 0;
@@ -903,6 +938,7 @@ static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 = {
 
 static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 = {
        .data_pin_pair_num = 4,
+       .has_fifo = true,
 };
 
 static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
-- 
2.27.0

Reply via email to