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

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