peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame 0505-hw-ac97-add-support-for-volume-control.patch

56753f
From 41d13bd2047a3a3ae8f451ff4aaf0585231ba1c6 Mon Sep 17 00:00:00 2001
56753f
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
56753f
Date: Tue, 17 Apr 2012 14:32:39 +0200
56753f
Subject: [PATCH 505/509] hw/ac97: add support for volume control
56753f
56753f
Combine output volume with Master and PCM registers values.
56753f
Use default values in mixer_reset ().
56753f
Set volume on post-load to update backend values.
56753f
56753f
v4,v5:
56753f
- fix some code style
56753f
56753f
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
56753f
Signed-off-by: malc <av1474@comtv.ru>
56753f
---
56753f
 hw/ac97.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56753f
 1 file changed, 81 insertions(+)
56753f
56753f
diff --git a/hw/ac97.c b/hw/ac97.c
56753f
index aa1babf..dd4917b 100644
56753f
--- a/hw/ac97.c
56753f
+++ b/hw/ac97.c
56753f
@@ -433,6 +433,65 @@ static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX])
56753f
     AUD_set_active_in (s->voice_mc, active[MC_INDEX]);
56753f
 }
56753f
 
56753f
+static void get_volume (uint16_t vol, uint16_t mask, int inverse,
56753f
+                        int *mute, uint8_t *lvol, uint8_t *rvol)
56753f
+{
56753f
+    *mute = (vol >> MUTE_SHIFT) & 1;
56753f
+    *rvol = (255 * (vol & mask)) / mask;
56753f
+    *lvol = (255 * ((vol >> 8) & mask)) / mask;
56753f
+
56753f
+    if (inverse) {
56753f
+        *rvol = 255 - *rvol;
56753f
+        *lvol = 255 - *lvol;
56753f
+    }
56753f
+}
56753f
+
56753f
+static void update_combined_volume_out (AC97LinkState *s)
56753f
+{
56753f
+    uint8_t lvol, rvol, plvol, prvol;
56753f
+    int mute, pmute;
56753f
+
56753f
+    get_volume (mixer_load (s, AC97_Master_Volume_Mute), 0x3f, 1,
56753f
+                &mute, &lvol, &rvol);
56753f
+    /* FIXME: should be 1f according to spec */
56753f
+    get_volume (mixer_load (s, AC97_PCM_Out_Volume_Mute), 0x3f, 1,
56753f
+                &pmute, &plvol, &prvol);
56753f
+
56753f
+    mute = mute | pmute;
56753f
+    lvol = (lvol * plvol) / 255;
56753f
+    rvol = (rvol * prvol) / 255;
56753f
+
56753f
+    AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
56753f
+}
56753f
+
56753f
+static void update_volume_in (AC97LinkState *s)
56753f
+{
56753f
+    uint8_t lvol, rvol;
56753f
+    int mute;
56753f
+
56753f
+    get_volume (mixer_load (s, AC97_Record_Gain_Mute), 0x0f, 0,
56753f
+                &mute, &lvol, &rvol);
56753f
+
56753f
+    AUD_set_volume_in (s->voice_pi, mute, lvol, rvol);
56753f
+}
56753f
+
56753f
+static void set_volume (AC97LinkState *s, int index, uint32_t val)
56753f
+{
56753f
+    mixer_store (s, index, val);
56753f
+    if (index == AC97_Master_Volume_Mute || index == AC97_PCM_Out_Volume_Mute) {
56753f
+        update_combined_volume_out (s);
56753f
+    } else if (index == AC97_Record_Gain_Mute) {
56753f
+        update_volume_in (s);
56753f
+    }
56753f
+}
56753f
+
56753f
+static void record_select (AC97LinkState *s, uint32_t val)
56753f
+{
56753f
+    uint8_t rs = val & REC_MASK;
56753f
+    uint8_t ls = (val >> 8) & REC_MASK;
56753f
+    mixer_store (s, AC97_Record_Select, rs | (ls << 8));
56753f
+}
56753f
+
56753f
 static void mixer_reset (AC97LinkState *s)
56753f
 {
56753f
     uint8_t active[LAST_INDEX];
56753f
@@ -467,6 +526,11 @@ static void mixer_reset (AC97LinkState *s)
56753f
     mixer_store (s, AC97_PCM_LR_ADC_Rate         , 0xbb80);
56753f
     mixer_store (s, AC97_MIC_ADC_Rate            , 0xbb80);
56753f
 
56753f
+    record_select (s, 0);
56753f
+    set_volume (s, AC97_Master_Volume_Mute, 0x8000);
56753f
+    set_volume (s, AC97_PCM_Out_Volume_Mute, 0x8808);
56753f
+    set_volume (s, AC97_Line_In_Volume_Mute, 0x8808);
56753f
+
56753f
     reset_voices (s, active);
56753f
 }
56753f
 
56753f
@@ -525,6 +589,15 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
56753f
         val |= mixer_load (s, index) & 0xf;
56753f
         mixer_store (s, index, val);
56753f
         break;
56753f
+    case AC97_PCM_Out_Volume_Mute:
56753f
+    case AC97_Master_Volume_Mute:
56753f
+    case AC97_Record_Gain_Mute:
56753f
+    case AC97_Line_In_Volume_Mute:
56753f
+        set_volume (s, index, val);
56753f
+        break;
56753f
+    case AC97_Record_Select:
56753f
+        record_select (s, val);
56753f
+        break;
56753f
     case AC97_Vendor_ID1:
56753f
     case AC97_Vendor_ID2:
56753f
         dolog ("Attempt to write vendor ID to %#x\n", val);
56753f
@@ -1077,6 +1150,14 @@ static int ac97_post_load (void *opaque, int version_id)
56753f
     uint8_t active[LAST_INDEX];
56753f
     AC97LinkState *s = opaque;
56753f
 
56753f
+    record_select (s, mixer_load (s, AC97_Record_Select));
56753f
+    set_volume (s, AC97_Master_Volume_Mute,
56753f
+                mixer_load (s, AC97_Master_Volume_Mute));
56753f
+    set_volume (s, AC97_PCM_Out_Volume_Mute,
56753f
+                mixer_load (s, AC97_PCM_Out_Volume_Mute));
56753f
+    set_volume (s, AC97_Line_In_Volume_Mute,
56753f
+                mixer_load (s, AC97_Line_In_Volume_Mute));
56753f
+
56753f
     active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
56753f
     active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
56753f
     active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);
56753f
-- 
56753f
1.7.10
56753f