| From 17aaf0193392cb3451bf0ac75ba396ec4cbded6e Mon Sep 17 00:00:00 2001 |
| From: Giacomo Guiduzzi <guiduzzi.giacomo@gmail.com> |
| Date: Tue, 22 Mar 2022 21:06:54 +0100 |
| Subject: ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec |
| |
| From: Giacomo Guiduzzi <guiduzzi.giacomo@gmail.com> |
| |
| commit 17aaf0193392cb3451bf0ac75ba396ec4cbded6e upstream. |
| |
| Tests 72 and 78 for ALSA in kselftest fail due to reading |
| inconsistent values from some devices on a VirtualBox |
| Virtual Machine using the snd_intel8x0 driver for the AC'97 |
| Audio Controller device. |
| Taking for example test number 72, this is what the test reports: |
| "Surround Playback Volume.0 expected 1 but read 0, is_volatile 0" |
| "Surround Playback Volume.1 expected 0 but read 1, is_volatile 0" |
| These errors repeat for each value from 0 to 31. |
| |
| Taking a look at these error messages it is possible to notice |
| that the written values are read back swapped. |
| When the write is performed, these values are initially stored in |
| an array used to sanity-check them and write them in the pcmreg |
| array. To write them, the two one-byte values are packed together |
| in a two-byte variable through bitwise operations: the first |
| value is shifted left by one byte and the second value is stored in the |
| right byte through a bitwise OR. When reading the values back, |
| right shifts are performed to retrieve the previously stored |
| bytes. These shifts are executed in the wrong order, thus |
| reporting the values swapped as shown above. |
| |
| This patch fixes this mistake by reversing the read |
| operations' order. |
| |
| Signed-off-by: Giacomo Guiduzzi <guiduzzi.giacomo@gmail.com> |
| Signed-off-by: Paolo Valente <paolo.valente@linaro.org> |
| Cc: <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/20220322200653.15862-1-guiduzzi.giacomo@gmail.com |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| sound/pci/ac97/ac97_codec.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/sound/pci/ac97/ac97_codec.c |
| +++ b/sound/pci/ac97/ac97_codec.c |
| @@ -938,8 +938,8 @@ static int snd_ac97_ad18xx_pcm_get_volum |
| int codec = kcontrol->private_value & 3; |
| |
| mutex_lock(&ac97->page_mutex); |
| - ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); |
| - ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); |
| + ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); |
| + ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); |
| mutex_unlock(&ac97->page_mutex); |
| return 0; |
| } |