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: Markus Pargmann <mpa@pengutronix.de> Tested-By: Michael Grzeschik <mgr@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
parent
737a6b418a
commit
4324812201
|
@ -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
|
||||||
|
|
|
@ -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,10 +781,12 @@ 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(2));
|
CCSR_SSI_SxCCR_DC_MASK,
|
||||||
write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
|
CCSR_SSI_SxCCR_DC(2));
|
||||||
CCSR_SSI_SxCCR_DC(2));
|
regmap_update_bits(regs, CCSR_SSI_SRCCR,
|
||||||
|
CCSR_SSI_SxCCR_DC_MASK,
|
||||||
|
CCSR_SSI_SxCCR_DC(2));
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_CBM_CFM:
|
||||||
ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_SLAVE;
|
ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_SLAVE;
|
||||||
|
@ -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, ®_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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue