*/
#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) \
struct mchp_i2s_mcc_soc_data {
unsigned int data_pin_pair_num;
+ bool has_fifo;
};
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);
* 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;
}
}
}
+ /* 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
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 {
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;
}
}
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;
* 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;
* 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:
}
}
- 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;
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[] = {