diff options
Diffstat (limited to 'target/linux/at91/patches-5.15/153-ASoC-mchp-i2s-mcc-Add-FIFOs-support.patch')
-rw-r--r-- | target/linux/at91/patches-5.15/153-ASoC-mchp-i2s-mcc-Add-FIFOs-support.patch | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/target/linux/at91/patches-5.15/153-ASoC-mchp-i2s-mcc-Add-FIFOs-support.patch b/target/linux/at91/patches-5.15/153-ASoC-mchp-i2s-mcc-Add-FIFOs-support.patch new file mode 100644 index 0000000000..24e0e4de4c --- /dev/null +++ b/target/linux/at91/patches-5.15/153-ASoC-mchp-i2s-mcc-Add-FIFOs-support.patch @@ -0,0 +1,187 @@ +From 36bb4f0ab8e7ef69cc11d4d888aa898223b0e901 Mon Sep 17 00:00:00 2001 +From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> +Date: Mon, 1 Mar 2021 19:09:04 +0200 +Subject: [PATCH 153/247] ASoC: mchp-i2s-mcc: Add FIFOs support + +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.ciubotariu@microchip.com> +Link: https://lore.kernel.org/r/20210301170905.835091-7-codrin.ciubotariu@microchip.com +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/atmel/mchp-i2s-mcc.c | 76 +++++++++++++++++++++++++--------- + 1 file changed, 56 insertions(+), 20 deletions(-) + +--- 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_i + + 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_interrup + * 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 + } + } + ++ /* 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 s + 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 s + 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 s + 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 s + * 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 s + * 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 s + } + } + +- 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 + + 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[] = { |