diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2020-05-11 23:01:32 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2020-05-12 17:14:43 +0100 |
commit | 39ec7e9b699910792468cf41a179d9930052e8ff (patch) | |
tree | 8d373ea24140be3b21530c4aaf93b950294aef04 /sound/soc/pxa/mmp-sspa.c | |
parent | 7d98cc648253c362ebfc582b11095a0e3f001896 (diff) |
ASoC: mmp-sspa: Set appropriate bus format for given bit width
The values set by set_dai_fmt() and hw_params() seem to be tailored only
for 32-bit formats. Negotiate the correct ones in hw_params() callback
instead.
This was essentially copied from the OLPC kernel driver and tested to
fix wrong audio output for non-32bit formats. The documentation is not
available.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Link: https://lore.kernel.org/r/20200511210134.1224532-10-lkundrak@v3.sk
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/pxa/mmp-sspa.c')
-rw-r--r-- | sound/soc/pxa/mmp-sspa.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 9cb17c4fb0c8..86277471974a 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -191,8 +191,6 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sspa->sp |= SSPA_TXSP_FPER(63); - sspa->sp |= SSPA_SP_FWID(31); sspa->ctrl |= SSPA_CTL_XDATDLY(1); break; default: @@ -216,30 +214,48 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, { struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); u32 sspa_ctrl = sspa->ctrl; - - sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; - sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); - sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; - sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS); - sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; + int bits; + int bitval; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS); + bits = 8; + bitval = SSPA_CTL_8_BITS; break; case SNDRV_PCM_FORMAT_S16_LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); + bits = 16; + bitval = SSPA_CTL_16_BITS; break; case SNDRV_PCM_FORMAT_S24_3LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); + bits = 24; + bitval = SSPA_CTL_24_BITS; break; case SNDRV_PCM_FORMAT_S32_LE: - sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS); + bits = 32; + bitval = SSPA_CTL_32_BITS; break; default: return -EINVAL; } + if (params_channels(params) == 2) + sspa_ctrl |= SSPA_CTL_XPH; + + sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; + sspa_ctrl |= SSPA_CTL_XWDLEN1(bitval); + + sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; + sspa_ctrl |= SSPA_CTL_XSSZ1(bitval); + + sspa_ctrl &= ~SSPA_CTL_XSSZ2_MASK; + sspa_ctrl |= SSPA_CTL_XSSZ2(bitval); + + sspa->sp &= ~SSPA_SP_FWID_MASK; + sspa->sp |= SSPA_SP_FWID(bits - 1); + + sspa->sp &= ~SSPA_TXSP_FPER_MASK; + sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); |