Commit de5bfae2 authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Mark Brown

ASoC: cpcap: fix microphone timeslot mask

The correct mask is 0x1f8 (Bit 3-8), but due to missing BIT() 0xf (Bit
0-3) was set instead. This means setting of CPCAP_BIT_MIC1_RX_TIMESLOT0
(Bit 3) still worked (part of both masks). On the other hand the code
does not properly clear the other MIC timeslot bits. I think this
is not a problem, since they are probably initialized to 0 and not
touched by the driver anywhere else. But the mask also contains some
wrong bits, that will be cleared. Bit 0 (CPCAP_BIT_SMB_CDC) should be
safe, since the driver enforces it to be 0 anyways.

Bit 1-2 are CPCAP_BIT_FS_INV and CPCAP_BIT_CLK_INV. This means enabling
audio recording forces the codec into SND_SOC_DAIFMT_NB_NF mode, which
is obviously bad.

The bug probably remained undetected, because there are not many use
cases for routing microphone to the CPU on platforms using cpcap and
user base is small. I do remember having some issues with bad sound
quality when testing voice recording back when I wrote the driver.
It probably was this bug.

Fixes: f6cdf2d3 ("ASoC: cpcap: new codec")
Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
Reviewed-by: default avatarTony Lindgren <tony@atomide.com>
Link: https://lore.kernel.org/r/20210123172945.3958622-1-sre@kernel.orgSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 941d3f0d
......@@ -1264,12 +1264,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
mask = 0x0000;
mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0;
mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1;
mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2;
mask |= CPCAP_BIT_MIC2_TIMESLOT0;
mask |= CPCAP_BIT_MIC2_TIMESLOT1;
mask |= CPCAP_BIT_MIC2_TIMESLOT2;
mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);
mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);
mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);
mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);
mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);
val = 0x0000;
if (channels >= 2)
val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment