Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43248122 authored by Markus Pargmann's avatar Markus Pargmann Committed by Mark Brown
Browse files

ASoC: fsl-ssi: Use regmap



This patch replaces the ssi specific functions write_ssi, read_ssi and
write_ssi_mask by standard regmap function calls.

Signed-off-by: default avatarMarkus Pargmann <mpa@pengutronix.de>
Tested-By: default avatarMichael Grzeschik <mgr@pengutronix.de>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 737a6b41
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,7 @@ config SND_SOC_FSL_SAI
	select SND_SOC_GENERIC_DMAENGINE_PCM
	select SND_SOC_GENERIC_DMAENGINE_PCM


config SND_SOC_FSL_SSI
config SND_SOC_FSL_SSI
	select REGMAP_MMIO
	tristate
	tristate


config SND_SOC_FSL_SPDIF
config SND_SOC_FSL_SPDIF
+133 −108
Original line number Original line Diff line number Diff line
@@ -53,25 +53,6 @@
#include "fsl_ssi.h"
#include "fsl_ssi.h"
#include "imx-pcm.h"
#include "imx-pcm.h"


#ifdef PPC
#define read_ssi(addr)			 in_be32(addr)
#define write_ssi(val, addr)		 out_be32(addr, val)
#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
#else
#define read_ssi(addr)			 readl(addr)
#define write_ssi(val, addr)		 writel(val, addr)
/*
 * FIXME: Proper locking should be added at write_ssi_mask caller level
 * to ensure this register read/modify/write sequence is race free.
 */
static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
{
	u32 val = readl(addr);
	val = (val & ~clear) | set;
	writel(val, addr);
}
#endif

/**
/**
 * FSLSSI_I2S_RATES: sample rates supported by the I2S
 * FSLSSI_I2S_RATES: sample rates supported by the I2S
 *
 *
@@ -131,6 +112,13 @@ struct fsl_ssi_rxtx_reg_val {
	struct fsl_ssi_reg_val rx;
	struct fsl_ssi_reg_val rx;
	struct fsl_ssi_reg_val tx;
	struct fsl_ssi_reg_val tx;
};
};
static const struct regmap_config fsl_ssi_regconfig = {
	.max_register = CCSR_SSI_SACCDIS,
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
	.val_format_endian = REGMAP_ENDIAN_NATIVE,
};


struct fsl_ssi_soc_data {
struct fsl_ssi_soc_data {
	bool imx;
	bool imx;
@@ -141,7 +129,7 @@ struct fsl_ssi_soc_data {
/**
/**
 * fsl_ssi_private: per-SSI private data
 * fsl_ssi_private: per-SSI private data
 *
 *
 * @ssi: Pointer to the memory area
 * @reg: Pointer to the regmap registers
 * @irq: IRQ of this SSI
 * @irq: IRQ of this SSI
 * @cpu_dai_drv: CPU DAI driver for this device
 * @cpu_dai_drv: CPU DAI driver for this device
 *
 *
@@ -172,7 +160,7 @@ struct fsl_ssi_soc_data {
 * @soc: SoC specifc data
 * @soc: SoC specifc data
 */
 */
struct fsl_ssi_private {
struct fsl_ssi_private {
	struct ccsr_ssi __iomem *ssi;
	struct regmap *regs;
	unsigned int irq;
	unsigned int irq;
	struct snd_soc_dai_driver cpu_dai_drv;
	struct snd_soc_dai_driver cpu_dai_drv;


@@ -285,7 +273,7 @@ static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private)
static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
{
{
	struct fsl_ssi_private *ssi_private = dev_id;
	struct fsl_ssi_private *ssi_private = dev_id;
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	__be32 sisr;
	__be32 sisr;
	__be32 sisr2;
	__be32 sisr2;


@@ -293,12 +281,12 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
	   were interrupted for.  We mask it with the Interrupt Enable register
	   were interrupted for.  We mask it with the Interrupt Enable register
	   so that we only check for events that we're interested in.
	   so that we only check for events that we're interested in.
	 */
	 */
	sisr = read_ssi(&ssi->sisr);
	regmap_read(regs, CCSR_SSI_SISR, &sisr);


	sisr2 = sisr & ssi_private->soc->sisr_write_mask;
	sisr2 = sisr & ssi_private->soc->sisr_write_mask;
	/* Clear the bits that we set */
	/* Clear the bits that we set */
	if (sisr2)
	if (sisr2)
		write_ssi(sisr2, &ssi->sisr);
		regmap_write(regs, CCSR_SSI_SISR, sisr2);


	fsl_ssi_dbg_isr(&ssi_private->dbg_stats, sisr);
	fsl_ssi_dbg_isr(&ssi_private->dbg_stats, sisr);


@@ -311,17 +299,26 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
		bool enable)
		bool enable)
{
{
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;
	struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;


	if (enable) {
	if (enable) {
		write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier);
		regmap_update_bits(regs, CCSR_SSI_SIER,
		write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr);
				vals->rx.sier | vals->tx.sier,
		write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr);
				vals->rx.sier | vals->tx.sier);
		regmap_update_bits(regs, CCSR_SSI_SRCR,
				vals->rx.srcr | vals->tx.srcr,
				vals->rx.srcr | vals->tx.srcr);
		regmap_update_bits(regs, CCSR_SSI_STCR,
				vals->rx.stcr | vals->tx.stcr,
				vals->rx.stcr | vals->tx.stcr);
	} else {
	} else {
		write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0);
		regmap_update_bits(regs, CCSR_SSI_SRCR,
		write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0);
				vals->rx.srcr | vals->tx.srcr, 0);
		write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0);
		regmap_update_bits(regs, CCSR_SSI_STCR,
				vals->rx.stcr | vals->tx.stcr, 0);
		regmap_update_bits(regs, CCSR_SSI_SIER,
				vals->rx.sier | vals->tx.sier, 0);
	}
	}
}
}


@@ -352,13 +349,17 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
		struct fsl_ssi_reg_val *vals)
		struct fsl_ssi_reg_val *vals)
{
{
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	struct fsl_ssi_reg_val *avals;
	struct fsl_ssi_reg_val *avals;
	u32 scr_val = read_ssi(&ssi->scr);
	int nr_active_streams;
	int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
	u32 scr_val;
				!!(scr_val & CCSR_SSI_SCR_RE);
	int keep_active;
	int keep_active;


	regmap_read(regs, CCSR_SSI_SCR, &scr_val);

	nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
				!!(scr_val & CCSR_SSI_SCR_RE);

	if (nr_active_streams - 1 > 0)
	if (nr_active_streams - 1 > 0)
		keep_active = 1;
		keep_active = 1;
	else
	else
@@ -375,7 +376,7 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
	if (!enable) {
	if (!enable) {
		u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
		u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
				keep_active);
				keep_active);
		write_ssi_mask(&ssi->scr, scr, 0);
		regmap_update_bits(regs, CCSR_SSI_SCR, scr, 0);
	}
	}


	/*
	/*
@@ -396,9 +397,9 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
	 * (online configuration)
	 * (online configuration)
	 */
	 */
	if (enable) {
	if (enable) {
		write_ssi_mask(&ssi->sier, 0, vals->sier);
		regmap_update_bits(regs, CCSR_SSI_SIER, vals->sier, vals->sier);
		write_ssi_mask(&ssi->srcr, 0, vals->srcr);
		regmap_update_bits(regs, CCSR_SSI_SRCR, vals->srcr, vals->srcr);
		write_ssi_mask(&ssi->stcr, 0, vals->stcr);
		regmap_update_bits(regs, CCSR_SSI_STCR, vals->stcr, vals->stcr);
	} else {
	} else {
		u32 sier;
		u32 sier;
		u32 srcr;
		u32 srcr;
@@ -421,15 +422,15 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
		stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
		stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
				keep_active);
				keep_active);


		write_ssi_mask(&ssi->srcr, srcr, 0);
		regmap_update_bits(regs, CCSR_SSI_SRCR, srcr, 0);
		write_ssi_mask(&ssi->stcr, stcr, 0);
		regmap_update_bits(regs, CCSR_SSI_STCR, stcr, 0);
		write_ssi_mask(&ssi->sier, sier, 0);
		regmap_update_bits(regs, CCSR_SSI_SIER, sier, 0);
	}
	}


config_done:
config_done:
	/* Enabling of subunits is done after configuration */
	/* Enabling of subunits is done after configuration */
	if (enable)
	if (enable)
		write_ssi_mask(&ssi->scr, 0, vals->scr);
		regmap_update_bits(regs, CCSR_SSI_SCR, vals->scr, vals->scr);
}
}




@@ -480,32 +481,33 @@ static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private)


static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
{
{
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;


	/*
	/*
	 * Setup the clock control register
	 * Setup the clock control register
	 */
	 */
	write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
	regmap_write(regs, CCSR_SSI_STCCR,
			&ssi->stccr);
			CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));
	write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
	regmap_write(regs, CCSR_SSI_SRCCR,
			&ssi->srccr);
			CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));


	/*
	/*
	 * Enable AC97 mode and startup the SSI
	 * Enable AC97 mode and startup the SSI
	 */
	 */
	write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
	regmap_write(regs, CCSR_SSI_SACNT,
			&ssi->sacnt);
			CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
	write_ssi(0xff, &ssi->saccdis);
	regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
	write_ssi(0x300, &ssi->saccen);
	regmap_write(regs, CCSR_SSI_SACCEN, 0x300);


	/*
	/*
	 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
	 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
	 * codec before a stream is started.
	 * codec before a stream is started.
	 */
	 */
	write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
	regmap_update_bits(regs, CCSR_SSI_SCR,
			CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
			CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE,
			CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);


	write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
	regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_WAIT(3));
}
}


/**
/**
@@ -549,7 +551,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *hw_params)
		struct snd_pcm_hw_params *hw_params)
{
{
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
	int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
	u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
	u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
	unsigned long clkrate, baudrate, tmprate;
	unsigned long clkrate, baudrate, tmprate;
@@ -626,9 +628,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
		CCSR_SSI_SxCCR_PSR;
		CCSR_SSI_SxCCR_PSR;


	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous)
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous)
		write_ssi_mask(&ssi->stccr, mask, stccr);
		regmap_update_bits(regs, CCSR_SSI_STCCR, mask, stccr);
	else
	else
		write_ssi_mask(&ssi->srccr, mask, stccr);
		regmap_update_bits(regs, CCSR_SSI_SRCCR, mask, stccr);


	if (!baudclk_is_used) {
	if (!baudclk_is_used) {
		ret = clk_set_rate(ssi_private->baudclk, baudrate);
		ret = clk_set_rate(ssi_private->baudclk, baudrate);
@@ -668,13 +670,17 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
{
{
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	unsigned int channels = params_channels(hw_params);
	unsigned int channels = params_channels(hw_params);
	unsigned int sample_size =
	unsigned int sample_size =
		snd_pcm_format_width(params_format(hw_params));
		snd_pcm_format_width(params_format(hw_params));
	u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
	u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
	int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
	int ret;
	int ret;
	u32 scr_val;
	int enabled;

	regmap_read(regs, CCSR_SSI_SCR, &scr_val);
	enabled = scr_val & CCSR_SSI_SCR_SSIEN;


	/*
	/*
	 * If we're in synchronous mode, and the SSI is already enabled,
	 * If we're in synchronous mode, and the SSI is already enabled,
@@ -711,12 +717,14 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
	/* In synchronous mode, the SSI uses STCCR for capture */
	/* In synchronous mode, the SSI uses STCCR for capture */
	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
	    ssi_private->cpu_dai_drv.symmetric_rates)
	    ssi_private->cpu_dai_drv.symmetric_rates)
		write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
		regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_WL_MASK,
				wl);
	else
	else
		write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
		regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK,
				wl);


	if (!fsl_ssi_is_ac97(ssi_private))
	if (!fsl_ssi_is_ac97(ssi_private))
		write_ssi_mask(&ssi->scr,
		regmap_update_bits(regs, CCSR_SSI_SCR,
				CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
				CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
				channels == 1 ? 0 : ssi_private->i2s_mode);
				channels == 1 ? 0 : ssi_private->i2s_mode);


@@ -742,7 +750,7 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream *substream,
static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
		unsigned int fmt)
		unsigned int fmt)
{
{
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	u32 strcr = 0, stcr, srcr, scr, mask;
	u32 strcr = 0, stcr, srcr, scr, mask;
	u8 wm;
	u8 wm;


@@ -755,14 +763,17 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,


	fsl_ssi_setup_reg_vals(ssi_private);
	fsl_ssi_setup_reg_vals(ssi_private);


	scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
	regmap_read(regs, CCSR_SSI_SCR, &scr);
	scr &= ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
	scr |= CCSR_SSI_SCR_SYNC_TX_FS;
	scr |= CCSR_SSI_SCR_SYNC_TX_FS;


	mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
	mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
		CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
		CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
		CCSR_SSI_STCR_TEFS;
		CCSR_SSI_STCR_TEFS;
	stcr = read_ssi(&ssi->stcr) & ~mask;
	regmap_read(regs, CCSR_SSI_STCR, &stcr);
	srcr = read_ssi(&ssi->srcr) & ~mask;
	regmap_read(regs, CCSR_SSI_SRCR, &srcr);
	stcr &= ~mask;
	srcr &= ~mask;


	ssi_private->i2s_mode = CCSR_SSI_SCR_NET;
	ssi_private->i2s_mode = CCSR_SSI_SCR_NET;
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -770,9 +781,11 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
		case SND_SOC_DAIFMT_CBS_CFS:
		case SND_SOC_DAIFMT_CBS_CFS:
			ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER;
			ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER;
			write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
			regmap_update_bits(regs, CCSR_SSI_STCCR,
					CCSR_SSI_SxCCR_DC_MASK,
					CCSR_SSI_SxCCR_DC(2));
					CCSR_SSI_SxCCR_DC(2));
			write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
			regmap_update_bits(regs, CCSR_SSI_SRCCR,
					CCSR_SSI_SxCCR_DC_MASK,
					CCSR_SSI_SxCCR_DC(2));
					CCSR_SSI_SxCCR_DC(2));
			break;
			break;
		case SND_SOC_DAIFMT_CBM_CFM:
		case SND_SOC_DAIFMT_CBM_CFM:
@@ -852,9 +865,9 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
		scr |= CCSR_SSI_SCR_SYN;
		scr |= CCSR_SSI_SCR_SYN;
	}
	}


	write_ssi(stcr, &ssi->stcr);
	regmap_write(regs, CCSR_SSI_STCR, stcr);
	write_ssi(srcr, &ssi->srcr);
	regmap_write(regs, CCSR_SSI_SRCR, srcr);
	write_ssi(scr, &ssi->scr);
	regmap_write(regs, CCSR_SSI_SCR, scr);


	/*
	/*
	 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
	 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
@@ -872,16 +885,16 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
	else
	else
		wm = ssi_private->fifo_depth;
		wm = ssi_private->fifo_depth;


	write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
	regmap_write(regs, CCSR_SSI_SFCSR,
			CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
			CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
			&ssi->sfcsr);
			CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm));


	if (ssi_private->use_dual_fifo) {
	if (ssi_private->use_dual_fifo) {
		write_ssi_mask(&ssi->srcr, CCSR_SSI_SRCR_RFEN1,
		regmap_update_bits(regs, CCSR_SSI_SRCR, CCSR_SSI_SRCR_RFEN1,
				CCSR_SSI_SRCR_RFEN1);
				CCSR_SSI_SRCR_RFEN1);
		write_ssi_mask(&ssi->stcr, CCSR_SSI_STCR_TFEN1,
		regmap_update_bits(regs, CCSR_SSI_STCR, CCSR_SSI_STCR_TFEN1,
				CCSR_SSI_STCR_TFEN1);
				CCSR_SSI_STCR_TFEN1);
		write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TCH_EN,
		regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_TCH_EN,
				CCSR_SSI_SCR_TCH_EN);
				CCSR_SSI_SCR_TCH_EN);
	}
	}


@@ -911,31 +924,34 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
				u32 rx_mask, int slots, int slot_width)
				u32 rx_mask, int slots, int slot_width)
{
{
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;
	u32 val;
	u32 val;


	/* The slot number should be >= 2 if using Network mode or I2S mode */
	/* The slot number should be >= 2 if using Network mode or I2S mode */
	val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
	regmap_read(regs, CCSR_SSI_SCR, &val);
	val &= CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET;
	if (val && slots < 2) {
	if (val && slots < 2) {
		dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
		dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
		return -EINVAL;
		return -EINVAL;
	}
	}


	write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
	regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_DC_MASK,
			CCSR_SSI_SxCCR_DC(slots));
			CCSR_SSI_SxCCR_DC(slots));
	write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
	regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_DC_MASK,
			CCSR_SSI_SxCCR_DC(slots));
			CCSR_SSI_SxCCR_DC(slots));


	/* The register SxMSKs needs SSI to provide essential clock due to
	/* The register SxMSKs needs SSI to provide essential clock due to
	 * hardware design. So we here temporarily enable SSI to set them.
	 * hardware design. So we here temporarily enable SSI to set them.
	 */
	 */
	val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
	regmap_read(regs, CCSR_SSI_SCR, &val);
	write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
	val &= CCSR_SSI_SCR_SSIEN;
	regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN,
			CCSR_SSI_SCR_SSIEN);


	write_ssi(tx_mask, &ssi->stmsk);
	regmap_write(regs, CCSR_SSI_STMSK, tx_mask);
	write_ssi(rx_mask, &ssi->srmsk);
	regmap_write(regs, CCSR_SSI_SRMSK, rx_mask);


	write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
	regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val);


	return 0;
	return 0;
}
}
@@ -954,7 +970,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
{
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
	struct regmap *regs = ssi_private->regs;


	switch (cmd) {
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_START:
@@ -981,9 +997,9 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,


	if (fsl_ssi_is_ac97(ssi_private)) {
	if (fsl_ssi_is_ac97(ssi_private)) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
			regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_TX_CLR);
		else
		else
			write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
			regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_RX_CLR);
	}
	}


	return 0;
	return 0;
@@ -1058,7 +1074,7 @@ static struct fsl_ssi_private *fsl_ac97_data;
static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
		unsigned short val)
		unsigned short val)
{
{
	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
	struct regmap *regs = fsl_ac97_data->regs;
	unsigned int lreg;
	unsigned int lreg;
	unsigned int lval;
	unsigned int lval;


@@ -1067,12 +1083,12 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,




	lreg = reg <<  12;
	lreg = reg <<  12;
	write_ssi(lreg, &ssi->sacadd);
	regmap_write(regs, CCSR_SSI_SACADD, lreg);


	lval = val << 4;
	lval = val << 4;
	write_ssi(lval , &ssi->sacdat);
	regmap_write(regs, CCSR_SSI_SACDAT, lval);


	write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
	regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
			CCSR_SSI_SACNT_WR);
			CCSR_SSI_SACNT_WR);
	udelay(100);
	udelay(100);
}
}
@@ -1080,19 +1096,21 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
		unsigned short reg)
		unsigned short reg)
{
{
	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
	struct regmap *regs = fsl_ac97_data->regs;


	unsigned short val = -1;
	unsigned short val = -1;
	u32 reg_val;
	unsigned int lreg;
	unsigned int lreg;


	lreg = (reg & 0x7f) <<  12;
	lreg = (reg & 0x7f) <<  12;
	write_ssi(lreg, &ssi->sacadd);
	regmap_write(regs, CCSR_SSI_SACADD, lreg);
	write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
	regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
			CCSR_SSI_SACNT_RD);
			CCSR_SSI_SACNT_RD);


	udelay(100);
	udelay(100);


	val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff;
	regmap_read(regs, CCSR_SSI_SACDAT, &reg_val);
	val = (reg_val >> 4) & 0xffff;


	return val;
	return val;
}
}
@@ -1151,10 +1169,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
	 */
	 */
	ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
	ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
	ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
	ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
	ssi_private->dma_params_tx.addr = ssi_private->ssi_phys +
	ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0;
			offsetof(struct ccsr_ssi, stx0);
	ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0;
	ssi_private->dma_params_rx.addr = ssi_private->ssi_phys +
			offsetof(struct ccsr_ssi, srx0);


	ret = !of_property_read_u32_array(np, "dmas", dmas, 4);
	ret = !of_property_read_u32_array(np, "dmas", dmas, 4);
	if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
	if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
@@ -1216,6 +1232,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
	const char *p, *sprop;
	const char *p, *sprop;
	const uint32_t *iprop;
	const uint32_t *iprop;
	struct resource res;
	struct resource res;
	void __iomem *iomem;
	char name[64];
	char name[64];


	/* SSIs that are not connected on the board should have a
	/* SSIs that are not connected on the board should have a
@@ -1270,12 +1287,20 @@ static int fsl_ssi_probe(struct platform_device *pdev)
		dev_err(&pdev->dev, "could not determine device resources\n");
		dev_err(&pdev->dev, "could not determine device resources\n");
		return ret;
		return ret;
	}
	}
	ssi_private->ssi = of_iomap(np, 0);
	ssi_private->ssi_phys = res.start;
	if (!ssi_private->ssi) {

	iomem = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
	if (!iomem) {
		dev_err(&pdev->dev, "could not map device resources\n");
		dev_err(&pdev->dev, "could not map device resources\n");
		return -ENOMEM;
		return -ENOMEM;
	}
	}
	ssi_private->ssi_phys = res.start;

	ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
			&fsl_ssi_regconfig);
	if (IS_ERR(ssi_private->regs)) {
		dev_err(&pdev->dev, "Failed to init register map\n");
		return PTR_ERR(ssi_private->regs);
	}


	ssi_private->irq = irq_of_parse_and_map(np, 0);
	ssi_private->irq = irq_of_parse_and_map(np, 0);
	if (!ssi_private->irq) {
	if (!ssi_private->irq) {
@@ -1301,7 +1326,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
	dev_set_drvdata(&pdev->dev, ssi_private);
	dev_set_drvdata(&pdev->dev, ssi_private);


	if (ssi_private->soc->imx) {
	if (ssi_private->soc->imx) {
		ret = fsl_ssi_imx_probe(pdev, ssi_private, ssi_private->ssi);
		ret = fsl_ssi_imx_probe(pdev, ssi_private, iomem);
		if (ret)
		if (ret)
			goto error_irqmap;
			goto error_irqmap;
	}
	}
+24 −26
Original line number Original line Diff line number Diff line
@@ -12,32 +12,30 @@
#ifndef _MPC8610_I2S_H
#ifndef _MPC8610_I2S_H
#define _MPC8610_I2S_H
#define _MPC8610_I2S_H


/* SSI Register Map */
/* SSI registers */
struct ccsr_ssi {
#define CCSR_SSI_STX0			0x00
	__be32 stx0;	/* 0x.0000 - SSI Transmit Data Register 0 */
#define CCSR_SSI_STX1			0x04
	__be32 stx1;	/* 0x.0004 - SSI Transmit Data Register 1 */
#define CCSR_SSI_SRX0			0x08
	__be32 srx0;	/* 0x.0008 - SSI Receive Data Register 0 */
#define CCSR_SSI_SRX1			0x0c
	__be32 srx1;	/* 0x.000C - SSI Receive Data Register 1 */
#define CCSR_SSI_SCR			0x10
	__be32 scr;	/* 0x.0010 - SSI Control Register */
#define CCSR_SSI_SISR			0x14
	__be32 sisr;	/* 0x.0014 - SSI Interrupt Status Register Mixed */
#define CCSR_SSI_SIER			0x18
	__be32 sier;	/* 0x.0018 - SSI Interrupt Enable Register */
#define CCSR_SSI_STCR			0x1c
	__be32 stcr;	/* 0x.001C - SSI Transmit Configuration Register */
#define CCSR_SSI_SRCR			0x20
	__be32 srcr;	/* 0x.0020 - SSI Receive Configuration Register */
#define CCSR_SSI_STCCR			0x24
	__be32 stccr;	/* 0x.0024 - SSI Transmit Clock Control Register */
#define CCSR_SSI_SRCCR			0x28
	__be32 srccr;	/* 0x.0028 - SSI Receive Clock Control Register */
#define CCSR_SSI_SFCSR			0x2c
	__be32 sfcsr;	/* 0x.002C - SSI FIFO Control/Status Register */
#define CCSR_SSI_STR			0x30
	__be32 str;	/* 0x.0030 - SSI Test Register */
#define CCSR_SSI_SOR			0x34
	__be32 sor;	/* 0x.0034 - SSI Option Register */
#define CCSR_SSI_SACNT			0x38
	__be32 sacnt;	/* 0x.0038 - SSI AC97 Control Register */
#define CCSR_SSI_SACADD			0x3c
	__be32 sacadd;	/* 0x.003C - SSI AC97 Command Address Register */
#define CCSR_SSI_SACDAT			0x40
	__be32 sacdat;	/* 0x.0040 - SSI AC97 Command Data Register */
#define CCSR_SSI_SATAG			0x44
	__be32 satag;	/* 0x.0044 - SSI AC97 Tag Register */
#define CCSR_SSI_STMSK			0x48
	__be32 stmsk;	/* 0x.0048 - SSI Transmit Time Slot Mask Register */
#define CCSR_SSI_SRMSK			0x4c
	__be32 srmsk;	/* 0x.004C - SSI Receive Time Slot Mask Register */
#define CCSR_SSI_SACCST			0x50
	__be32 saccst;	/* 0x.0050 - SSI AC97 Channel Status Register */
#define CCSR_SSI_SACCEN			0x54
	__be32 saccen;	/* 0x.0054 - SSI AC97 Channel Enable Register */
#define CCSR_SSI_SACCDIS		0x58
	__be32 saccdis; /* 0x.0058 - SSI AC97 Channel Disable Register */
};


#define CCSR_SSI_SCR_SYNC_TX_FS		0x00001000
#define CCSR_SSI_SCR_SYNC_TX_FS		0x00001000
#define CCSR_SSI_SCR_RFR_CLK_DIS	0x00000800
#define CCSR_SSI_SCR_RFR_CLK_DIS	0x00000800