188 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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[] = {
 | 
