123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- From 36bb4f0ab8e7ef69cc11d4d888aa898223b0e901 Mon Sep 17 00:00:00 2001
- From: Codrin Ciubotariu <[email protected]>
- 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 <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- Signed-off-by: Mark Brown <[email protected]>
- ---
- 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[] = {
|