hw/ac97: Mask out unused bits of volume controls

The Linux ac97 drivers does a number of register read/write tests to
see how much resolution a volume control actually has.

This patch takes this into account by masking out any bits written to
a volume control reg which should not be there according to the spec.

After this the Linux ac97 driver correctly uses a range of 0 - 0x1f for
the PCM out volume, as stated in the spec, and we can fix the FIXME
in update_combined_volume_out().

This patch was also tested with a Windows XP guest without any issues.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
This commit is contained in:
Hans de Goede 2012-05-07 09:24:37 +02:00 committed by malc
parent f94e9b9b35
commit 7873bfb866
1 changed files with 15 additions and 5 deletions

View File

@ -458,8 +458,7 @@ static void update_combined_volume_out (AC97LinkState *s)
get_volume (mixer_load (s, AC97_Master_Volume_Mute), 0x3f, 1,
&mute, &lvol, &rvol);
/* FIXME: should be 1f according to spec */
get_volume (mixer_load (s, AC97_PCM_Out_Volume_Mute), 0x3f, 1,
get_volume (mixer_load (s, AC97_PCM_Out_Volume_Mute), 0x1f, 1,
&pmute, &plvol, &prvol);
mute = mute | pmute;
@ -482,11 +481,22 @@ static void update_volume_in (AC97LinkState *s)
static void set_volume (AC97LinkState *s, int index, uint32_t val)
{
mixer_store (s, index, val);
if (index == AC97_Master_Volume_Mute || index == AC97_PCM_Out_Volume_Mute) {
switch (index) {
case AC97_Master_Volume_Mute:
val &= 0xbf3f;
mixer_store (s, index, val);
update_combined_volume_out (s);
} else if (index == AC97_Record_Gain_Mute) {
break;
case AC97_PCM_Out_Volume_Mute:
val &= 0x9f1f;
mixer_store (s, index, val);
update_combined_volume_out (s);
break;
case AC97_Record_Gain_Mute:
val &= 0x8f0f;
mixer_store (s, index, val);
update_volume_in (s);
break;
}
}