summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-05-07 09:24:37 +0200
committermalc <av1474@comtv.ru>2012-05-07 16:31:40 +0400
commit7873bfb866c89f9e6eab28b14d0c2007b361150c (patch)
tree52fae75f15b2fbdabc29f5c08e5d9964f487a6b3 /hw
parentf94e9b9b3535ea977c5a919f88adf36da95a8292 (diff)
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>
Diffstat (limited to 'hw')
-rw-r--r--hw/ac97.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/hw/ac97.c b/hw/ac97.c
index d175870798..b009257434 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -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;
}
}