ASoC: fsl_sai: Support multiple data channel enable bits

One data channel is one data line. From imx7ulp, the SAI IP is
enhanced to support multiple data channels.

If there is only two channels input and slots is 2, then enable one
data channel is enough for data transfer. So enable the TCE/RCE and
transmit/receive mask register according to the input channels and
slots configuration.

Move the data channel enablement from startup() to hw_params().

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/1598958068-10552-1-git-send-email-shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Shengjiu Wang 2020-09-01 19:01:08 +08:00 committed by Mark Brown
parent a57307ca6b
commit 770f58d7d2
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
2 changed files with 13 additions and 19 deletions

View file

@ -443,6 +443,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
u32 slots = (channels == 1) ? 2 : channels;
u32 slot_width = word_width;
int adir = tx ? RX : TX;
u32 pins;
int ret;
if (sai->slots)
@ -451,6 +452,8 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
if (sai->slot_width)
slot_width = sai->slot_width;
pins = DIV_ROUND_UP(channels, slots);
if (!sai->is_slave_mode) {
if (sai->bclk_ratio)
ret = fsl_sai_set_bclk(cpu_dai, tx,
@ -501,13 +504,17 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
FSL_SAI_CR5_FBT_MASK, val_cr5);
}
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK,
FSL_SAI_CR3_TRCE((1 << pins) - 1));
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, 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));
regmap_write(sai->regmap, FSL_SAI_xMR(tx),
~0UL - ((1 << min(channels, slots)) - 1));
return 0;
}
@ -517,6 +524,10 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int ofs = sai->soc_data->reg_offset;
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK, 0);
if (!sai->is_slave_mode &&
sai->mclk_streams & BIT(substream->stream)) {
@ -651,14 +662,9 @@ 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, ofs),
FSL_SAI_CR3_TRCE_MASK,
FSL_SAI_CR3_TRCE);
/*
* EDMA controller needs period size to be a multiple of
* tx/rx maxburst
@ -675,17 +681,6 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
return ret;
}
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, ofs),
FSL_SAI_CR3_TRCE_MASK, 0);
}
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
.set_bclk_ratio = fsl_sai_set_dai_bclk_ratio,
.set_sysclk = fsl_sai_set_dai_sysclk,
@ -695,7 +690,6 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
.hw_free = fsl_sai_hw_free,
.trigger = fsl_sai_trigger,
.startup = fsl_sai_startup,
.shutdown = fsl_sai_shutdown,
};
static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)

View file

@ -109,7 +109,7 @@
#define FSL_SAI_CR2_DIV_MASK 0xff
/* SAI Transmit and Receive Configuration 3 Register */
#define FSL_SAI_CR3_TRCE BIT(16)
#define FSL_SAI_CR3_TRCE(x) ((x) << 16)
#define FSL_SAI_CR3_TRCE_MASK GENMASK(23, 16)
#define FSL_SAI_CR3_WDFL(x) (x)
#define FSL_SAI_CR3_WDFL_MASK 0x1f