[09/10] ASoC: fsl_sai: Add support for SAI new version
diff mbox series

Message ID 20190722124833.28757-10-daniel.baluta@nxp.com
State Not Applicable
Headers show
Series
  • Add support for new SAI IP version
Related show

Checks

Context Check Description
snowpatch_ozlabs/checkpatch warning total: 0 errors, 1 warnings, 32 checks, 589 lines checked
snowpatch_ozlabs/apply_patch success Successfully applied on branch next (f3365d1a959d5c6527efe3d38276acc9b58e3f3f)

Commit Message

Daniel Baluta July 22, 2019, 12:48 p.m. UTC
New IP version introduces Version ID and Parameter registers
and optionally added Timestamp feature.

VERID and PARAM registers are placed at the top of registers
address space and some registers are shifted according to
the following table:

Tx/Rx data registers and Tx/Rx FIFO registers keep their
addresses, all other registers are shifted by 8.

SAI Memory map is described in chapter 13.10.4.1.1 I2S Memory map
of the Reference Manual [1].

In order to make as less changes as possible we attach an offset
to each register offset to each changed register definition. The
offset is read from each board private data.

[1]https://cache.nxp.com/secured/assets/documents/en/reference-manual/IMX8MDQLQRM.pdf?__gda__=1563728701_38bea7f0f726472cc675cb141b91bec7&fileExt=.pdf

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
 sound/soc/fsl/fsl_sai.c | 240 +++++++++++++++++++++++-----------------
 sound/soc/fsl/fsl_sai.h |  41 +++----
 2 files changed, 162 insertions(+), 119 deletions(-)

Comments

Nicolin Chen July 24, 2019, 11:32 p.m. UTC | #1
On Mon, Jul 22, 2019 at 03:48:32PM +0300, Daniel Baluta wrote:
> New IP version introduces Version ID and Parameter registers
> and optionally added Timestamp feature.
> 
> VERID and PARAM registers are placed at the top of registers
> address space and some registers are shifted according to
> the following table:
> 
> Tx/Rx data registers and Tx/Rx FIFO registers keep their
> addresses, all other registers are shifted by 8.

Feels like Lucas's approach is neater. I saw that Register TMR
at 0x60 is exceptional during your previous discussion. So can
we apply an offset-cancellation for it exceptionally? I haven't
checked all the registers so this would look okay to me as well
if there are more than just Register TMR.

Thanks
Nicolin

> SAI Memory map is described in chapter 13.10.4.1.1 I2S Memory map
> of the Reference Manual [1].
> 
> In order to make as less changes as possible we attach an offset
> to each register offset to each changed register definition. The
> offset is read from each board private data.
> 
> [1]https://cache.nxp.com/secured/assets/documents/en/reference-manual/IMX8MDQLQRM.pdf?__gda__=1563728701_38bea7f0f726472cc675cb141b91bec7&fileExt=.pdf
> 
> Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
> ---
>  sound/soc/fsl/fsl_sai.c | 240 +++++++++++++++++++++++-----------------
>  sound/soc/fsl/fsl_sai.h |  41 +++----
>  2 files changed, 162 insertions(+), 119 deletions(-)
> 
> diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
> index 140014901fce..f2441b84877e 100644
> --- a/sound/soc/fsl/fsl_sai.c
> +++ b/sound/soc/fsl/fsl_sai.c
> @@ -40,6 +40,7 @@ static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = {
>  static irqreturn_t fsl_sai_isr(int irq, void *devid)
>  {
>  	struct fsl_sai *sai = (struct fsl_sai *)devid;
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	struct device *dev = &sai->pdev->dev;
>  	u32 flags, xcsr, mask;
>  	bool irq_none = true;
> @@ -52,7 +53,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
>  	mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
>  
>  	/* Tx IRQ */
> -	regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
> +	regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
>  	flags = xcsr & mask;
>  
>  	if (flags)
> @@ -82,11 +83,11 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
>  	xcsr &= ~FSL_SAI_CSR_xF_MASK;
>  
>  	if (flags)
> -		regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
> +		regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
>  
>  irq_rx:
>  	/* Rx IRQ */
> -	regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
> +	regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
>  	flags = xcsr & mask;
>  
>  	if (flags)
> @@ -116,7 +117,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
>  	xcsr &= ~FSL_SAI_CSR_xF_MASK;
>  
>  	if (flags)
> -		regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
> +		regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
>  
>  out:
>  	if (irq_none)
> @@ -140,6 +141,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
>  		int clk_id, unsigned int freq, int fsl_dir)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
>  	u32 val_cr2 = 0;
>  
> @@ -160,7 +162,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
>  		return -EINVAL;
>  	}
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
>  			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
>  
>  	return 0;
> @@ -193,6 +195,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
>  				unsigned int fmt, int fsl_dir)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
>  	u32 val_cr2 = 0, val_cr4 = 0;
>  
> @@ -287,9 +290,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
>  		return -EINVAL;
>  	}
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
>  			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
>  			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
>  
> @@ -316,6 +319,7 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
>  static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	unsigned long clk_rate;
>  	u32 savediv = 0, ratio, savesub = freq;
>  	u32 id;
> @@ -378,17 +382,17 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
>  	 */
>  	if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
>  	    (!tx && !sai->synchronous[RX])) {
> -		regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
> +		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
>  				   FSL_SAI_CR2_MSEL_MASK,
>  				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
> -		regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
> +		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
>  				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
>  	} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
>  		   (tx && !sai->synchronous[TX])) {
> -		regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
> +		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
>  				   FSL_SAI_CR2_MSEL_MASK,
>  				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
> -		regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
> +		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
>  				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
>  	}
>  
> @@ -403,6 +407,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
>  		struct snd_soc_dai *cpu_dai)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>  	unsigned int channels = params_channels(params);
>  	u32 word_width = params_width(params);
> @@ -455,19 +460,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
>  
>  	if (!sai->is_slave_mode) {
>  		if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
> -			regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
> +			regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs),
>  				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
>  				val_cr4);
> -			regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
> +			regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs),
>  				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
>  				FSL_SAI_CR5_FBT_MASK, val_cr5);
>  			regmap_write(sai->regmap, FSL_SAI_TMR,
>  				~0UL - ((1 << channels) - 1));
>  		} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
> -			regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
> +			regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs),
>  				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
>  				val_cr4);
> -			regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
> +			regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs),
>  				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
>  				FSL_SAI_CR5_FBT_MASK, val_cr5);
>  			regmap_write(sai->regmap, FSL_SAI_RMR,
> @@ -475,26 +480,26 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
>  		}
>  	}
>  
> -	switch (sai->soc_data->fcomb_mode[tx]) {
> +	switch (sai->fcomb_mode[tx]) {
>  	case FSL_SAI_FCOMB_NONE:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  				   FSL_SAI_CR4_FCOMB_SOFT |
>  				   FSL_SAI_CR4_FCOMB_SHIFT, 0);
>  		break;
>  	case FSL_SAI_FCOMB_SHIFT:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  				   FSL_SAI_CR4_FCOMB_SOFT |
>  				   FSL_SAI_CR4_FCOMB_SHIFT,
>  				   FSL_SAI_CR4_FCOMB_SHIFT);
>  		break;
>  	case FSL_SAI_FCOMB_SOFT:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  				   FSL_SAI_CR4_FCOMB_SOFT |
>  				   FSL_SAI_CR4_FCOMB_SHIFT,
>  				   FSL_SAI_CR4_FCOMB_SOFT);
>  		break;
>  	case FSL_SAI_FCOMB_BOTH:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  				   FSL_SAI_CR4_FCOMB_SOFT |
>  				   FSL_SAI_CR4_FCOMB_SHIFT,
>  				   FSL_SAI_CR4_FCOMB_SOFT |
> @@ -504,10 +509,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
>  		break;
>  	}
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
>  			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
>  			   val_cr4);
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
>  			   FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
>  			   FSL_SAI_CR5_FBT_MASK, val_cr5);
>  	regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
> @@ -535,6 +540,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
>  		struct snd_soc_dai *cpu_dai)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
> +
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>  	u32 xcsr, count = 100;
>  
> @@ -543,9 +550,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
>  	 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
>  	 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
>  	 */
> -	regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
> -		           sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
> -	regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
> +	regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
> +			   sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
> +	regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
>  			   sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
>  
>  	/*
> @@ -556,43 +563,44 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
>  	case SNDRV_PCM_TRIGGER_START:
>  	case SNDRV_PCM_TRIGGER_RESUME:
>  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
>  				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
>  
> -		regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
> +		regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
>  				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
> -		regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
> +		regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
>  				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
>  
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
>  				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
>  		break;
>  	case SNDRV_PCM_TRIGGER_STOP:
>  	case SNDRV_PCM_TRIGGER_SUSPEND:
>  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
>  				   FSL_SAI_CSR_FRDE, 0);
> -		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
> +		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
>  				   FSL_SAI_CSR_xIE_MASK, 0);
>  
>  		/* Check if the opposite FRDE is also disabled */
> -		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr);
> +		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
>  		if (!(xcsr & FSL_SAI_CSR_FRDE)) {
>  			/* Disable both directions and reset their FIFOs */
> -			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
> +			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
>  					   FSL_SAI_CSR_TERE, 0);
> -			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
> +			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
>  					   FSL_SAI_CSR_TERE, 0);
>  
>  			/* TERE will remain set till the end of current frame */
>  			do {
>  				udelay(10);
> -				regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr);
> +				regmap_read(sai->regmap,
> +					    FSL_SAI_xCSR(tx, ofs), &xcsr);
>  			} while (--count && xcsr & FSL_SAI_CSR_TERE);
>  
> -			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
> +			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
>  					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
> -			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
> +			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
>  					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
>  
>  			/*
> @@ -604,13 +612,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
>  			 */
>  			if (!sai->is_slave_mode) {
>  				/* Software Reset for both Tx and Rx */
> -				regmap_write(sai->regmap,
> -					     FSL_SAI_TCSR, FSL_SAI_CSR_SR);
> -				regmap_write(sai->regmap,
> -					     FSL_SAI_RCSR, FSL_SAI_CSR_SR);
> +				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs),
> +					     FSL_SAI_CSR_SR);
> +				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs),
> +					     FSL_SAI_CSR_SR);
>  				/* Clear SR bit to finish the reset */
> -				regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
> -				regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
> +				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
> +				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
>  			}
>  		}
>  		break;
> @@ -625,12 +633,13 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
>  		struct snd_soc_dai *cpu_dai)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>  	int ret;
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
>  			   FSL_SAI_CR3_TRCE_MASK,
> -			   FSL_SAI_CR3_TRCE(sai->soc_data->dl_mask[tx]);
> +			   FSL_SAI_CR3_TRCE(sai->dl_mask[tx]));
>  
>  	ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
>  			SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);
> @@ -642,9 +651,10 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
>  		struct snd_soc_dai *cpu_dai)
>  {
>  	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
> +	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
>  			   FSL_SAI_CR3_TRCE_MASK, 0);
>  }
>  
> @@ -662,18 +672,20 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
>  static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
>  {
>  	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  
>  	/* Software Reset for both Tx and Rx */
> -	regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
> -	regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
> +	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
> +	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
>  	/* Clear SR bit to finish the reset */
> -	regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
> -	regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
> +	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
> +	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
>  
> -	regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
> +	regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
> +			   FSL_SAI_CR1_RFW_MASK,
>  			   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
> -	regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
> -			   FSL_SAI_MAXBURST_RX - 1);
> +	regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
> +			   FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1);
>  
>  	snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
>  				&sai->dma_params_rx);
> @@ -710,12 +722,12 @@ static const struct snd_soc_component_driver fsl_component = {
>  	.name           = "fsl-sai",
>  };
>  
> -static struct reg_default fsl_sai_reg_defaults[] = {
> -	{FSL_SAI_TCR1, 0},
> -	{FSL_SAI_TCR2, 0},
> -	{FSL_SAI_TCR3, 0},
> -	{FSL_SAI_TCR4, 0},
> -	{FSL_SAI_TCR5, 0},
> +static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
> +	{FSL_SAI_TCR1(0), 0},
> +	{FSL_SAI_TCR2(0), 0},
> +	{FSL_SAI_TCR3(0), 0},
> +	{FSL_SAI_TCR4(0), 0},
> +	{FSL_SAI_TCR5(0), 0},
>  	{FSL_SAI_TDR0, 0},
>  	{FSL_SAI_TDR1, 0},
>  	{FSL_SAI_TDR2, 0},
> @@ -724,24 +736,50 @@ static struct reg_default fsl_sai_reg_defaults[] = {
>  	{FSL_SAI_TDR5, 0},
>  	{FSL_SAI_TDR6, 0},
>  	{FSL_SAI_TDR7, 0},
> -	{FSL_SAI_TMR,  0},
> -	{FSL_SAI_RCR1, 0},
> -	{FSL_SAI_RCR2, 0},
> -	{FSL_SAI_RCR3, 0},
> -	{FSL_SAI_RCR4, 0},
> -	{FSL_SAI_RCR5, 0},
> -	{FSL_SAI_RMR,  0},
> +	{FSL_SAI_TMR, 0},
> +	{FSL_SAI_RCR1(0), 0},
> +	{FSL_SAI_RCR2(0), 0},
> +	{FSL_SAI_RCR3(0), 0},
> +	{FSL_SAI_RCR4(0), 0},
> +	{FSL_SAI_RCR5(0), 0},
> +	{FSL_SAI_RMR, 0},
> +};
> +
> +static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
> +	{FSL_SAI_TCR1(8), 0},
> +	{FSL_SAI_TCR2(8), 0},
> +	{FSL_SAI_TCR3(8), 0},
> +	{FSL_SAI_TCR4(8), 0},
> +	{FSL_SAI_TCR5(8), 0},
> +	{FSL_SAI_TDR0, 0},
> +	{FSL_SAI_TDR1, 0},
> +	{FSL_SAI_TDR2, 0},
> +	{FSL_SAI_TDR3, 0},
> +	{FSL_SAI_TDR4, 0},
> +	{FSL_SAI_TDR5, 0},
> +	{FSL_SAI_TDR6, 0},
> +	{FSL_SAI_TDR7, 0},
> +	{FSL_SAI_TMR, 0},
> +	{FSL_SAI_RCR1(8), 0},
> +	{FSL_SAI_RCR2(8), 0},
> +	{FSL_SAI_RCR3(8), 0},
> +	{FSL_SAI_RCR4(8), 0},
> +	{FSL_SAI_RCR5(8), 0},
> +	{FSL_SAI_RMR, 0},
>  };
>  
>  static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
>  {
> +	struct fsl_sai *sai = dev_get_drvdata(dev);
> +	unsigned int ofs = sai->soc_data->reg_offset;
> +
> +	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
> +		return true;
> +
> +	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
> +		return true;
> +
>  	switch (reg) {
> -	case FSL_SAI_TCSR:
> -	case FSL_SAI_TCR1:
> -	case FSL_SAI_TCR2:
> -	case FSL_SAI_TCR3:
> -	case FSL_SAI_TCR4:
> -	case FSL_SAI_TCR5:
>  	case FSL_SAI_TFR0:
>  	case FSL_SAI_TFR1:
>  	case FSL_SAI_TFR2:
> @@ -751,12 +789,6 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
>  	case FSL_SAI_TFR6:
>  	case FSL_SAI_TFR7:
>  	case FSL_SAI_TMR:
> -	case FSL_SAI_RCSR:
> -	case FSL_SAI_RCR1:
> -	case FSL_SAI_RCR2:
> -	case FSL_SAI_RCR3:
> -	case FSL_SAI_RCR4:
> -	case FSL_SAI_RCR5:
>  	case FSL_SAI_RDR0:
>  	case FSL_SAI_RDR1:
>  	case FSL_SAI_RDR2:
> @@ -782,9 +814,13 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
>  
>  static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
>  {
> +	struct fsl_sai *sai = dev_get_drvdata(dev);
> +	unsigned int ofs = sai->soc_data->reg_offset;
> +
> +	if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
> +		return true;
> +
>  	switch (reg) {
> -	case FSL_SAI_TCSR:
> -	case FSL_SAI_RCSR:
>  	case FSL_SAI_TFR0:
>  	case FSL_SAI_TFR1:
>  	case FSL_SAI_TFR2:
> @@ -817,13 +853,16 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
>  
>  static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
>  {
> +	struct fsl_sai *sai = dev_get_drvdata(dev);
> +	unsigned int ofs = sai->soc_data->reg_offset;
> +
> +	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
> +		return true;
> +
> +	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
> +		return true;
> +
>  	switch (reg) {
> -	case FSL_SAI_TCSR:
> -	case FSL_SAI_TCR1:
> -	case FSL_SAI_TCR2:
> -	case FSL_SAI_TCR3:
> -	case FSL_SAI_TCR4:
> -	case FSL_SAI_TCR5:
>  	case FSL_SAI_TDR0:
>  	case FSL_SAI_TDR1:
>  	case FSL_SAI_TDR2:
> @@ -833,12 +872,6 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
>  	case FSL_SAI_TDR6:
>  	case FSL_SAI_TDR7:
>  	case FSL_SAI_TMR:
> -	case FSL_SAI_RCSR:
> -	case FSL_SAI_RCR1:
> -	case FSL_SAI_RCR2:
> -	case FSL_SAI_RCR3:
> -	case FSL_SAI_RCR4:
> -	case FSL_SAI_RCR5:
>  	case FSL_SAI_RMR:
>  		return true;
>  	default:
> @@ -846,14 +879,14 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
>  	}
>  }
>  
> -static const struct regmap_config fsl_sai_regmap_config = {
> +static struct regmap_config fsl_sai_regmap_config = {
>  	.reg_bits = 32,
>  	.reg_stride = 4,
>  	.val_bits = 32,
>  
>  	.max_register = FSL_SAI_RMR,
> -	.reg_defaults = fsl_sai_reg_defaults,
> -	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
> +	.reg_defaults = fsl_sai_reg_defaults_ofs0,
> +	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
>  	.readable_reg = fsl_sai_readable_reg,
>  	.volatile_reg = fsl_sai_volatile_reg,
>  	.writeable_reg = fsl_sai_writeable_reg,
> @@ -885,6 +918,12 @@ static int fsl_sai_probe(struct platform_device *pdev)
>  	if (IS_ERR(base))
>  		return PTR_ERR(base);
>  
> +	if (sai->soc_data->reg_offset == 8) {
> +		fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
> +		fsl_sai_regmap_config.num_reg_defaults =
> +			ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
> +	}
> +
>  	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
>  			"bus", base, &fsl_sai_regmap_config);
>  
> @@ -1017,11 +1056,13 @@ static int fsl_sai_remove(struct platform_device *pdev)
>  static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
>  	.use_imx_pcm = false,
>  	.fifo_depth = 32,
> +	.reg_offset = 0,
>  };
>  
>  static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
>  	.use_imx_pcm = true,
>  	.fifo_depth = 32,
> +	.reg_offset = 0,
>  };
>  
>  static const struct of_device_id fsl_sai_ids[] = {
> @@ -1054,6 +1095,7 @@ static int fsl_sai_runtime_suspend(struct device *dev)
>  static int fsl_sai_runtime_resume(struct device *dev)
>  {
>  	struct fsl_sai *sai = dev_get_drvdata(dev);
> +	unsigned int ofs = sai->soc_data->reg_offset;
>  	int ret;
>  
>  	ret = clk_prepare_enable(sai->bus_clk);
> @@ -1075,11 +1117,11 @@ static int fsl_sai_runtime_resume(struct device *dev)
>  	}
>  
>  	regcache_cache_only(sai->regmap, false);
> -	regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
> -	regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
> +	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
> +	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
>  	usleep_range(1000, 2000);
> -	regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
> -	regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
> +	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
> +	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
>  
>  	ret = regcache_sync(sai->regmap);
>  	if (ret)
> diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
> index abf140951187..d20f16cc2a80 100644
> --- a/sound/soc/fsl/fsl_sai.h
> +++ b/sound/soc/fsl/fsl_sai.h
> @@ -14,12 +14,12 @@
>  			 SNDRV_PCM_FMTBIT_S32_LE)
>  
>  /* SAI Register Map Register */
> -#define FSL_SAI_TCSR	0x00 /* SAI Transmit Control */
> -#define FSL_SAI_TCR1	0x04 /* SAI Transmit Configuration 1 */
> -#define FSL_SAI_TCR2	0x08 /* SAI Transmit Configuration 2 */
> -#define FSL_SAI_TCR3	0x0c /* SAI Transmit Configuration 3 */
> -#define FSL_SAI_TCR4	0x10 /* SAI Transmit Configuration 4 */
> -#define FSL_SAI_TCR5	0x14 /* SAI Transmit Configuration 5 */
> +#define FSL_SAI_TCSR(ofs)	(0x00 + ofs) /* SAI Transmit Control */
> +#define FSL_SAI_TCR1(ofs)	(0x04 + ofs) /* SAI Transmit Configuration 1 */
> +#define FSL_SAI_TCR2(ofs)	(0x08 + ofs) /* SAI Transmit Configuration 2 */
> +#define FSL_SAI_TCR3(ofs)	(0x0c + ofs) /* SAI Transmit Configuration 3 */
> +#define FSL_SAI_TCR4(ofs)	(0x10 + ofs) /* SAI Transmit Configuration 4 */
> +#define FSL_SAI_TCR5(ofs)	(0x14 + ofs) /* SAI Transmit Configuration 5 */
>  #define FSL_SAI_TDR0	0x20 /* SAI Transmit Data 0 */
>  #define FSL_SAI_TDR1	0x24 /* SAI Transmit Data 1 */
>  #define FSL_SAI_TDR2	0x28 /* SAI Transmit Data 2 */
> @@ -37,12 +37,12 @@
>  #define FSL_SAI_TFR6	0x58 /* SAI Transmit FIFO 6 */
>  #define FSL_SAI_TFR7	0x5C /* SAI Transmit FIFO 7 */
>  #define FSL_SAI_TMR	0x60 /* SAI Transmit Mask */
> -#define FSL_SAI_RCSR	0x80 /* SAI Receive Control */
> -#define FSL_SAI_RCR1	0x84 /* SAI Receive Configuration 1 */
> -#define FSL_SAI_RCR2	0x88 /* SAI Receive Configuration 2 */
> -#define FSL_SAI_RCR3	0x8c /* SAI Receive Configuration 3 */
> -#define FSL_SAI_RCR4	0x90 /* SAI Receive Configuration 4 */
> -#define FSL_SAI_RCR5	0x94 /* SAI Receive Configuration 5 */
> +#define FSL_SAI_RCSR(ofs)	(0x80 + ofs) /* SAI Receive Control */
> +#define FSL_SAI_RCR1(ofs)	(0x84 + ofs)/* SAI Receive Configuration 1 */
> +#define FSL_SAI_RCR2(ofs)	(0x88 + ofs) /* SAI Receive Configuration 2 */
> +#define FSL_SAI_RCR3(ofs)	(0x8c + ofs) /* SAI Receive Configuration 3 */
> +#define FSL_SAI_RCR4(ofs)	(0x90 + ofs) /* SAI Receive Configuration 4 */
> +#define FSL_SAI_RCR5(ofs)	(0x94 + ofs) /* SAI Receive Configuration 5 */
>  #define FSL_SAI_RDR0	0xa0 /* SAI Receive Data 0 */
>  #define FSL_SAI_RDR1	0xa4 /* SAI Receive Data 1 */
>  #define FSL_SAI_RDR2	0xa8 /* SAI Receive Data 2 */
> @@ -61,14 +61,14 @@
>  #define FSL_SAI_RFR7	0xdc /* SAI Receive FIFO 7 */
>  #define FSL_SAI_RMR	0xe0 /* SAI Receive Mask */
>  
> -#define FSL_SAI_xCSR(tx)	(tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
> -#define FSL_SAI_xCR1(tx)	(tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
> -#define FSL_SAI_xCR2(tx)	(tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
> -#define FSL_SAI_xCR3(tx)	(tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
> -#define FSL_SAI_xCR4(tx)	(tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
> -#define FSL_SAI_xCR5(tx)	(tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
> -#define FSL_SAI_xDR(tx)		(tx ? FSL_SAI_TDR : FSL_SAI_RDR)
> -#define FSL_SAI_xFR(tx)		(tx ? FSL_SAI_TFR : FSL_SAI_RFR)
> +#define FSL_SAI_xCSR(tx, ofs)	(tx ? FSL_SAI_TCSR(ofs) : FSL_SAI_RCSR(ofs))
> +#define FSL_SAI_xCR1(tx, ofs)	(tx ? FSL_SAI_TCR1(ofs) : FSL_SAI_RCR1(ofs))
> +#define FSL_SAI_xCR2(tx, ofs)	(tx ? FSL_SAI_TCR2(ofs) : FSL_SAI_RCR2(ofs))
> +#define FSL_SAI_xCR3(tx, ofs)	(tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs))
> +#define FSL_SAI_xCR4(tx, ofs)	(tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs))
> +#define FSL_SAI_xCR5(tx, ofs)	(tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs))
> +#define FSL_SAI_xDR(tx, ofs)	(tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs))
> +#define FSL_SAI_xFR(tx, ofs)	(tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs))
>  #define FSL_SAI_xMR(tx)		(tx ? FSL_SAI_TMR : FSL_SAI_RMR)
>  
>  /* SAI Transmit/Receive Control Register */
> @@ -166,6 +166,7 @@
>  struct fsl_sai_soc_data {
>  	bool use_imx_pcm;
>  	unsigned int fifo_depth;
> +	unsigned int reg_offset;
>  };
>  
>  struct fsl_sai {
> -- 
> 2.17.1
>
Daniel Baluta July 25, 2019, 6:06 a.m. UTC | #2
On Thu, Jul 25, 2019 at 2:32 AM Nicolin Chen <nicoleotsuka@gmail.com> wrote:
>
> On Mon, Jul 22, 2019 at 03:48:32PM +0300, Daniel Baluta wrote:
> > New IP version introduces Version ID and Parameter registers
> > and optionally added Timestamp feature.
> >
> > VERID and PARAM registers are placed at the top of registers
> > address space and some registers are shifted according to
> > the following table:
> >
> > Tx/Rx data registers and Tx/Rx FIFO registers keep their
> > addresses, all other registers are shifted by 8.
>
> Feels like Lucas's approach is neater. I saw that Register TMR
> at 0x60 is exceptional during your previous discussion. So can
> we apply an offset-cancellation for it exceptionally? I haven't
> checked all the registers so this would look okay to me as well
> if there are more than just Register TMR.

It is not just TMR exceptional. There are like half of the registers.
Thus: half of the registers need to be shifted and half of them
need to stay the same as in previous version of SAI.

I'm not seeing yet a neater approach. Lucas idea would somehow
work if regmap will allow some sort of translation function applied
over registers before being accessed.

Maybe Mark has some clues here?

thanks,
daniel.

Patch
diff mbox series

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 140014901fce..f2441b84877e 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -40,6 +40,7 @@  static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = {
 static irqreturn_t fsl_sai_isr(int irq, void *devid)
 {
 	struct fsl_sai *sai = (struct fsl_sai *)devid;
+	unsigned int ofs = sai->soc_data->reg_offset;
 	struct device *dev = &sai->pdev->dev;
 	u32 flags, xcsr, mask;
 	bool irq_none = true;
@@ -52,7 +53,7 @@  static irqreturn_t fsl_sai_isr(int irq, void *devid)
 	mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
 
 	/* Tx IRQ */
-	regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
+	regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
 	flags = xcsr & mask;
 
 	if (flags)
@@ -82,11 +83,11 @@  static irqreturn_t fsl_sai_isr(int irq, void *devid)
 	xcsr &= ~FSL_SAI_CSR_xF_MASK;
 
 	if (flags)
-		regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
+		regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
 
 irq_rx:
 	/* Rx IRQ */
-	regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
+	regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
 	flags = xcsr & mask;
 
 	if (flags)
@@ -116,7 +117,7 @@  static irqreturn_t fsl_sai_isr(int irq, void *devid)
 	xcsr &= ~FSL_SAI_CSR_xF_MASK;
 
 	if (flags)
-		regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
+		regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
 
 out:
 	if (irq_none)
@@ -140,6 +141,7 @@  static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		int clk_id, unsigned int freq, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
 	u32 val_cr2 = 0;
 
@@ -160,7 +162,7 @@  static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		return -EINVAL;
 	}
 
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
 			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
 
 	return 0;
@@ -193,6 +195,7 @@  static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 				unsigned int fmt, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
 	u32 val_cr2 = 0, val_cr4 = 0;
 
@@ -287,9 +290,9 @@  static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		return -EINVAL;
 	}
 
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
 			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
 			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
 
@@ -316,6 +319,7 @@  static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	unsigned long clk_rate;
 	u32 savediv = 0, ratio, savesub = freq;
 	u32 id;
@@ -378,17 +382,17 @@  static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
 	 */
 	if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
 	    (!tx && !sai->synchronous[RX])) {
-		regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
+		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
 				   FSL_SAI_CR2_MSEL_MASK,
 				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
-		regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
+		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
 				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
 	} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
 		   (tx && !sai->synchronous[TX])) {
-		regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
+		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
 				   FSL_SAI_CR2_MSEL_MASK,
 				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
-		regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
+		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
 				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
 	}
 
@@ -403,6 +407,7 @@  static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	unsigned int channels = params_channels(params);
 	u32 word_width = params_width(params);
@@ -455,19 +460,19 @@  static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 
 	if (!sai->is_slave_mode) {
 		if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
-			regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
+			regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs),
 				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
 				val_cr4);
-			regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
+			regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs),
 				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
 				FSL_SAI_CR5_FBT_MASK, val_cr5);
 			regmap_write(sai->regmap, FSL_SAI_TMR,
 				~0UL - ((1 << channels) - 1));
 		} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
-			regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
+			regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs),
 				FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
 				val_cr4);
-			regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
+			regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs),
 				FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
 				FSL_SAI_CR5_FBT_MASK, val_cr5);
 			regmap_write(sai->regmap, FSL_SAI_RMR,
@@ -475,26 +480,26 @@  static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 		}
 	}
 
-	switch (sai->soc_data->fcomb_mode[tx]) {
+	switch (sai->fcomb_mode[tx]) {
 	case FSL_SAI_FCOMB_NONE:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 				   FSL_SAI_CR4_FCOMB_SOFT |
 				   FSL_SAI_CR4_FCOMB_SHIFT, 0);
 		break;
 	case FSL_SAI_FCOMB_SHIFT:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 				   FSL_SAI_CR4_FCOMB_SOFT |
 				   FSL_SAI_CR4_FCOMB_SHIFT,
 				   FSL_SAI_CR4_FCOMB_SHIFT);
 		break;
 	case FSL_SAI_FCOMB_SOFT:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 				   FSL_SAI_CR4_FCOMB_SOFT |
 				   FSL_SAI_CR4_FCOMB_SHIFT,
 				   FSL_SAI_CR4_FCOMB_SOFT);
 		break;
 	case FSL_SAI_FCOMB_BOTH:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 				   FSL_SAI_CR4_FCOMB_SOFT |
 				   FSL_SAI_CR4_FCOMB_SHIFT,
 				   FSL_SAI_CR4_FCOMB_SOFT |
@@ -504,10 +509,10 @@  static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
 			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
 			   val_cr4);
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
 			   FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
 			   FSL_SAI_CR5_FBT_MASK, val_cr5);
 	regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
@@ -535,6 +540,8 @@  static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
+
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	u32 xcsr, count = 100;
 
@@ -543,9 +550,9 @@  static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
 	 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
 	 */
-	regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
-		           sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
-	regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
+	regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
+			   sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
+	regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
 			   sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
 
 	/*
@@ -556,43 +563,44 @@  static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
 				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
 
-		regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+		regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
 				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
-		regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+		regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
 				   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
 
-		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
 				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
 				   FSL_SAI_CSR_FRDE, 0);
-		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
 				   FSL_SAI_CSR_xIE_MASK, 0);
 
 		/* Check if the opposite FRDE is also disabled */
-		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr);
+		regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
 		if (!(xcsr & FSL_SAI_CSR_FRDE)) {
 			/* Disable both directions and reset their FIFOs */
-			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
 					   FSL_SAI_CSR_TERE, 0);
-			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
 					   FSL_SAI_CSR_TERE, 0);
 
 			/* TERE will remain set till the end of current frame */
 			do {
 				udelay(10);
-				regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr);
+				regmap_read(sai->regmap,
+					    FSL_SAI_xCSR(tx, ofs), &xcsr);
 			} while (--count && xcsr & FSL_SAI_CSR_TERE);
 
-			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+			regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
 					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
-			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+			regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
 					   FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
 
 			/*
@@ -604,13 +612,13 @@  static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 			 */
 			if (!sai->is_slave_mode) {
 				/* Software Reset for both Tx and Rx */
-				regmap_write(sai->regmap,
-					     FSL_SAI_TCSR, FSL_SAI_CSR_SR);
-				regmap_write(sai->regmap,
-					     FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs),
+					     FSL_SAI_CSR_SR);
+				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs),
+					     FSL_SAI_CSR_SR);
 				/* Clear SR bit to finish the reset */
-				regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
-				regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+				regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+				regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
 			}
 		}
 		break;
@@ -625,12 +633,13 @@  static int fsl_sai_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	int ret;
 
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
 			   FSL_SAI_CR3_TRCE_MASK,
-			   FSL_SAI_CR3_TRCE(sai->soc_data->dl_mask[tx]);
+			   FSL_SAI_CR3_TRCE(sai->dl_mask[tx]));
 
 	ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
 			SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);
@@ -642,9 +651,10 @@  static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
-	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
 			   FSL_SAI_CR3_TRCE_MASK, 0);
 }
 
@@ -662,18 +672,20 @@  static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
+	unsigned int ofs = sai->soc_data->reg_offset;
 
 	/* Software Reset for both Tx and Rx */
-	regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
-	regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
+	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
 	/* Clear SR bit to finish the reset */
-	regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
-	regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
 
-	regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
+	regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
+			   FSL_SAI_CR1_RFW_MASK,
 			   sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
-	regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
-			   FSL_SAI_MAXBURST_RX - 1);
+	regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
+			   FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1);
 
 	snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
 				&sai->dma_params_rx);
@@ -710,12 +722,12 @@  static const struct snd_soc_component_driver fsl_component = {
 	.name           = "fsl-sai",
 };
 
-static struct reg_default fsl_sai_reg_defaults[] = {
-	{FSL_SAI_TCR1, 0},
-	{FSL_SAI_TCR2, 0},
-	{FSL_SAI_TCR3, 0},
-	{FSL_SAI_TCR4, 0},
-	{FSL_SAI_TCR5, 0},
+static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
+	{FSL_SAI_TCR1(0), 0},
+	{FSL_SAI_TCR2(0), 0},
+	{FSL_SAI_TCR3(0), 0},
+	{FSL_SAI_TCR4(0), 0},
+	{FSL_SAI_TCR5(0), 0},
 	{FSL_SAI_TDR0, 0},
 	{FSL_SAI_TDR1, 0},
 	{FSL_SAI_TDR2, 0},
@@ -724,24 +736,50 @@  static struct reg_default fsl_sai_reg_defaults[] = {
 	{FSL_SAI_TDR5, 0},
 	{FSL_SAI_TDR6, 0},
 	{FSL_SAI_TDR7, 0},
-	{FSL_SAI_TMR,  0},
-	{FSL_SAI_RCR1, 0},
-	{FSL_SAI_RCR2, 0},
-	{FSL_SAI_RCR3, 0},
-	{FSL_SAI_RCR4, 0},
-	{FSL_SAI_RCR5, 0},
-	{FSL_SAI_RMR,  0},
+	{FSL_SAI_TMR, 0},
+	{FSL_SAI_RCR1(0), 0},
+	{FSL_SAI_RCR2(0), 0},
+	{FSL_SAI_RCR3(0), 0},
+	{FSL_SAI_RCR4(0), 0},
+	{FSL_SAI_RCR5(0), 0},
+	{FSL_SAI_RMR, 0},
+};
+
+static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
+	{FSL_SAI_TCR1(8), 0},
+	{FSL_SAI_TCR2(8), 0},
+	{FSL_SAI_TCR3(8), 0},
+	{FSL_SAI_TCR4(8), 0},
+	{FSL_SAI_TCR5(8), 0},
+	{FSL_SAI_TDR0, 0},
+	{FSL_SAI_TDR1, 0},
+	{FSL_SAI_TDR2, 0},
+	{FSL_SAI_TDR3, 0},
+	{FSL_SAI_TDR4, 0},
+	{FSL_SAI_TDR5, 0},
+	{FSL_SAI_TDR6, 0},
+	{FSL_SAI_TDR7, 0},
+	{FSL_SAI_TMR, 0},
+	{FSL_SAI_RCR1(8), 0},
+	{FSL_SAI_RCR2(8), 0},
+	{FSL_SAI_RCR3(8), 0},
+	{FSL_SAI_RCR4(8), 0},
+	{FSL_SAI_RCR5(8), 0},
+	{FSL_SAI_RMR, 0},
 };
 
 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
 {
+	struct fsl_sai *sai = dev_get_drvdata(dev);
+	unsigned int ofs = sai->soc_data->reg_offset;
+
+	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
+		return true;
+
+	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
+		return true;
+
 	switch (reg) {
-	case FSL_SAI_TCSR:
-	case FSL_SAI_TCR1:
-	case FSL_SAI_TCR2:
-	case FSL_SAI_TCR3:
-	case FSL_SAI_TCR4:
-	case FSL_SAI_TCR5:
 	case FSL_SAI_TFR0:
 	case FSL_SAI_TFR1:
 	case FSL_SAI_TFR2:
@@ -751,12 +789,6 @@  static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
 	case FSL_SAI_TFR6:
 	case FSL_SAI_TFR7:
 	case FSL_SAI_TMR:
-	case FSL_SAI_RCSR:
-	case FSL_SAI_RCR1:
-	case FSL_SAI_RCR2:
-	case FSL_SAI_RCR3:
-	case FSL_SAI_RCR4:
-	case FSL_SAI_RCR5:
 	case FSL_SAI_RDR0:
 	case FSL_SAI_RDR1:
 	case FSL_SAI_RDR2:
@@ -782,9 +814,13 @@  static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
 
 static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
 {
+	struct fsl_sai *sai = dev_get_drvdata(dev);
+	unsigned int ofs = sai->soc_data->reg_offset;
+
+	if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
+		return true;
+
 	switch (reg) {
-	case FSL_SAI_TCSR:
-	case FSL_SAI_RCSR:
 	case FSL_SAI_TFR0:
 	case FSL_SAI_TFR1:
 	case FSL_SAI_TFR2:
@@ -817,13 +853,16 @@  static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
 
 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
 {
+	struct fsl_sai *sai = dev_get_drvdata(dev);
+	unsigned int ofs = sai->soc_data->reg_offset;
+
+	if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
+		return true;
+
+	if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
+		return true;
+
 	switch (reg) {
-	case FSL_SAI_TCSR:
-	case FSL_SAI_TCR1:
-	case FSL_SAI_TCR2:
-	case FSL_SAI_TCR3:
-	case FSL_SAI_TCR4:
-	case FSL_SAI_TCR5:
 	case FSL_SAI_TDR0:
 	case FSL_SAI_TDR1:
 	case FSL_SAI_TDR2:
@@ -833,12 +872,6 @@  static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
 	case FSL_SAI_TDR6:
 	case FSL_SAI_TDR7:
 	case FSL_SAI_TMR:
-	case FSL_SAI_RCSR:
-	case FSL_SAI_RCR1:
-	case FSL_SAI_RCR2:
-	case FSL_SAI_RCR3:
-	case FSL_SAI_RCR4:
-	case FSL_SAI_RCR5:
 	case FSL_SAI_RMR:
 		return true;
 	default:
@@ -846,14 +879,14 @@  static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
 	}
 }
 
-static const struct regmap_config fsl_sai_regmap_config = {
+static struct regmap_config fsl_sai_regmap_config = {
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
 
 	.max_register = FSL_SAI_RMR,
-	.reg_defaults = fsl_sai_reg_defaults,
-	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
+	.reg_defaults = fsl_sai_reg_defaults_ofs0,
+	.num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
 	.readable_reg = fsl_sai_readable_reg,
 	.volatile_reg = fsl_sai_volatile_reg,
 	.writeable_reg = fsl_sai_writeable_reg,
@@ -885,6 +918,12 @@  static int fsl_sai_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	if (sai->soc_data->reg_offset == 8) {
+		fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
+		fsl_sai_regmap_config.num_reg_defaults =
+			ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
+	}
+
 	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
 			"bus", base, &fsl_sai_regmap_config);
 
@@ -1017,11 +1056,13 @@  static int fsl_sai_remove(struct platform_device *pdev)
 static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
 	.use_imx_pcm = false,
 	.fifo_depth = 32,
+	.reg_offset = 0,
 };
 
 static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
 	.use_imx_pcm = true,
 	.fifo_depth = 32,
+	.reg_offset = 0,
 };
 
 static const struct of_device_id fsl_sai_ids[] = {
@@ -1054,6 +1095,7 @@  static int fsl_sai_runtime_suspend(struct device *dev)
 static int fsl_sai_runtime_resume(struct device *dev)
 {
 	struct fsl_sai *sai = dev_get_drvdata(dev);
+	unsigned int ofs = sai->soc_data->reg_offset;
 	int ret;
 
 	ret = clk_prepare_enable(sai->bus_clk);
@@ -1075,11 +1117,11 @@  static int fsl_sai_runtime_resume(struct device *dev)
 	}
 
 	regcache_cache_only(sai->regmap, false);
-	regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
-	regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
+	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
 	usleep_range(1000, 2000);
-	regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
-	regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+	regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+	regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
 
 	ret = regcache_sync(sai->regmap);
 	if (ret)
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index abf140951187..d20f16cc2a80 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -14,12 +14,12 @@ 
 			 SNDRV_PCM_FMTBIT_S32_LE)
 
 /* SAI Register Map Register */
-#define FSL_SAI_TCSR	0x00 /* SAI Transmit Control */
-#define FSL_SAI_TCR1	0x04 /* SAI Transmit Configuration 1 */
-#define FSL_SAI_TCR2	0x08 /* SAI Transmit Configuration 2 */
-#define FSL_SAI_TCR3	0x0c /* SAI Transmit Configuration 3 */
-#define FSL_SAI_TCR4	0x10 /* SAI Transmit Configuration 4 */
-#define FSL_SAI_TCR5	0x14 /* SAI Transmit Configuration 5 */
+#define FSL_SAI_TCSR(ofs)	(0x00 + ofs) /* SAI Transmit Control */
+#define FSL_SAI_TCR1(ofs)	(0x04 + ofs) /* SAI Transmit Configuration 1 */
+#define FSL_SAI_TCR2(ofs)	(0x08 + ofs) /* SAI Transmit Configuration 2 */
+#define FSL_SAI_TCR3(ofs)	(0x0c + ofs) /* SAI Transmit Configuration 3 */
+#define FSL_SAI_TCR4(ofs)	(0x10 + ofs) /* SAI Transmit Configuration 4 */
+#define FSL_SAI_TCR5(ofs)	(0x14 + ofs) /* SAI Transmit Configuration 5 */
 #define FSL_SAI_TDR0	0x20 /* SAI Transmit Data 0 */
 #define FSL_SAI_TDR1	0x24 /* SAI Transmit Data 1 */
 #define FSL_SAI_TDR2	0x28 /* SAI Transmit Data 2 */
@@ -37,12 +37,12 @@ 
 #define FSL_SAI_TFR6	0x58 /* SAI Transmit FIFO 6 */
 #define FSL_SAI_TFR7	0x5C /* SAI Transmit FIFO 7 */
 #define FSL_SAI_TMR	0x60 /* SAI Transmit Mask */
-#define FSL_SAI_RCSR	0x80 /* SAI Receive Control */
-#define FSL_SAI_RCR1	0x84 /* SAI Receive Configuration 1 */
-#define FSL_SAI_RCR2	0x88 /* SAI Receive Configuration 2 */
-#define FSL_SAI_RCR3	0x8c /* SAI Receive Configuration 3 */
-#define FSL_SAI_RCR4	0x90 /* SAI Receive Configuration 4 */
-#define FSL_SAI_RCR5	0x94 /* SAI Receive Configuration 5 */
+#define FSL_SAI_RCSR(ofs)	(0x80 + ofs) /* SAI Receive Control */
+#define FSL_SAI_RCR1(ofs)	(0x84 + ofs)/* SAI Receive Configuration 1 */
+#define FSL_SAI_RCR2(ofs)	(0x88 + ofs) /* SAI Receive Configuration 2 */
+#define FSL_SAI_RCR3(ofs)	(0x8c + ofs) /* SAI Receive Configuration 3 */
+#define FSL_SAI_RCR4(ofs)	(0x90 + ofs) /* SAI Receive Configuration 4 */
+#define FSL_SAI_RCR5(ofs)	(0x94 + ofs) /* SAI Receive Configuration 5 */
 #define FSL_SAI_RDR0	0xa0 /* SAI Receive Data 0 */
 #define FSL_SAI_RDR1	0xa4 /* SAI Receive Data 1 */
 #define FSL_SAI_RDR2	0xa8 /* SAI Receive Data 2 */
@@ -61,14 +61,14 @@ 
 #define FSL_SAI_RFR7	0xdc /* SAI Receive FIFO 7 */
 #define FSL_SAI_RMR	0xe0 /* SAI Receive Mask */
 
-#define FSL_SAI_xCSR(tx)	(tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
-#define FSL_SAI_xCR1(tx)	(tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
-#define FSL_SAI_xCR2(tx)	(tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
-#define FSL_SAI_xCR3(tx)	(tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
-#define FSL_SAI_xCR4(tx)	(tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
-#define FSL_SAI_xCR5(tx)	(tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
-#define FSL_SAI_xDR(tx)		(tx ? FSL_SAI_TDR : FSL_SAI_RDR)
-#define FSL_SAI_xFR(tx)		(tx ? FSL_SAI_TFR : FSL_SAI_RFR)
+#define FSL_SAI_xCSR(tx, ofs)	(tx ? FSL_SAI_TCSR(ofs) : FSL_SAI_RCSR(ofs))
+#define FSL_SAI_xCR1(tx, ofs)	(tx ? FSL_SAI_TCR1(ofs) : FSL_SAI_RCR1(ofs))
+#define FSL_SAI_xCR2(tx, ofs)	(tx ? FSL_SAI_TCR2(ofs) : FSL_SAI_RCR2(ofs))
+#define FSL_SAI_xCR3(tx, ofs)	(tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs))
+#define FSL_SAI_xCR4(tx, ofs)	(tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs))
+#define FSL_SAI_xCR5(tx, ofs)	(tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs))
+#define FSL_SAI_xDR(tx, ofs)	(tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs))
+#define FSL_SAI_xFR(tx, ofs)	(tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs))
 #define FSL_SAI_xMR(tx)		(tx ? FSL_SAI_TMR : FSL_SAI_RMR)
 
 /* SAI Transmit/Receive Control Register */
@@ -166,6 +166,7 @@ 
 struct fsl_sai_soc_data {
 	bool use_imx_pcm;
 	unsigned int fifo_depth;
+	unsigned int reg_offset;
 };
 
 struct fsl_sai {