]> Git Repo - qemu.git/blobdiff - hw/ac97.c
pci: honor PCI_COMMAND_MASTER
[qemu.git] / hw / ac97.c
index 177f729d4819382727d9e2f0999c83278cb7bfb9..0f561fa5c1cadf3cf81f79c3b58eecece78b86b1 100644 (file)
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -54,6 +54,8 @@ enum {
     AC97_6Ch_Vol_C_LFE_Mute        = 0x36,
     AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
     AC97_Vendor_Reserved           = 0x58,
+    AC97_Sigmatel_Analog           = 0x6c, /* We emulate a Sigmatel codec */
+    AC97_Sigmatel_Dac2Invert       = 0x6e, /* We emulate a Sigmatel codec */
     AC97_Vendor_ID1                = 0x7c,
     AC97_Vendor_ID2                = 0x7e
 };
@@ -342,7 +344,7 @@ static uint16_t mixer_load (AC97LinkState *s, uint32_t i)
     uint16_t val = 0xffff;
 
     if (i + 2 > sizeof (s->mixer_data)) {
-        dolog ("mixer_store: index %d out of bounds %zd\n",
+        dolog ("mixer_load: index %d out of bounds %zd\n",
                i, sizeof (s->mixer_data));
     }
     else {
@@ -456,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;
@@ -480,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;
     }
 }
 
@@ -503,14 +515,17 @@ static void mixer_reset (AC97LinkState *s)
     memset (s->mixer_data, 0, sizeof (s->mixer_data));
     memset (active, 0, sizeof (active));
     mixer_store (s, AC97_Reset                   , 0x0000); /* 6940 */
-    mixer_store (s, AC97_Master_Volume_Mono_Mute , 0x8000);
+    mixer_store (s, AC97_Headphone_Volume_Mute   , 0x0000);
+    mixer_store (s, AC97_Master_Volume_Mono_Mute , 0x0000);
+    mixer_store (s, AC97_Master_Tone_RL,           0x0000);
     mixer_store (s, AC97_PC_BEEP_Volume_Mute     , 0x0000);
-
-    mixer_store (s, AC97_Phone_Volume_Mute       , 0x8008);
-    mixer_store (s, AC97_Mic_Volume_Mute         , 0x8008);
-    mixer_store (s, AC97_CD_Volume_Mute          , 0x8808);
-    mixer_store (s, AC97_Aux_Volume_Mute         , 0x8808);
-    mixer_store (s, AC97_Record_Gain_Mic_Mute    , 0x8000);
+    mixer_store (s, AC97_Phone_Volume_Mute       , 0x0000);
+    mixer_store (s, AC97_Mic_Volume_Mute         , 0x0000);
+    mixer_store (s, AC97_Line_In_Volume_Mute     , 0x0000);
+    mixer_store (s, AC97_CD_Volume_Mute          , 0x0000);
+    mixer_store (s, AC97_Video_Volume_Mute       , 0x0000);
+    mixer_store (s, AC97_Aux_Volume_Mute         , 0x0000);
+    mixer_store (s, AC97_Record_Gain_Mic_Mute    , 0x0000);
     mixer_store (s, AC97_General_Purpose         , 0x0000);
     mixer_store (s, AC97_3D_Control              , 0x0000);
     mixer_store (s, AC97_Powerdown_Ctrl_Stat     , 0x000f);
@@ -532,7 +547,7 @@ static void mixer_reset (AC97LinkState *s)
     record_select (s, 0);
     set_volume (s, AC97_Master_Volume_Mute, 0x8000);
     set_volume (s, AC97_PCM_Out_Volume_Mute, 0x8808);
-    set_volume (s, AC97_Line_In_Volume_Mute, 0x8808);
+    set_volume (s, AC97_Record_Gain_Mute, 0x8808);
 
     reset_voices (s, active);
 }
@@ -588,14 +603,13 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
         mixer_reset (s);
         break;
     case AC97_Powerdown_Ctrl_Stat:
-        val &= ~0xf;
+        val &= ~0x800f;
         val |= mixer_load (s, index) & 0xf;
         mixer_store (s, index, val);
         break;
     case AC97_PCM_Out_Volume_Mute:
     case AC97_Master_Volume_Mute:
     case AC97_Record_Gain_Mute:
-    case AC97_Line_In_Volume_Mute:
         set_volume (s, index, val);
         break;
     case AC97_Record_Select:
@@ -657,6 +671,23 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
                     val);
         }
         break;
+    case AC97_Headphone_Volume_Mute:
+    case AC97_Master_Volume_Mono_Mute:
+    case AC97_Master_Tone_RL:
+    case AC97_PC_BEEP_Volume_Mute:
+    case AC97_Phone_Volume_Mute:
+    case AC97_Mic_Volume_Mute:
+    case AC97_Line_In_Volume_Mute:
+    case AC97_CD_Volume_Mute:
+    case AC97_Video_Volume_Mute:
+    case AC97_Aux_Volume_Mute:
+    case AC97_Record_Gain_Mic_Mute:
+    case AC97_General_Purpose:
+    case AC97_3D_Control:
+    case AC97_Sigmatel_Analog:
+    case AC97_Sigmatel_Dac2Invert:
+        /* None of the features in these regs are emulated, so they are RO */
+        break;
     default:
         dolog ("U nam writew %#x <- %#x\n", addr, val);
         mixer_store (s, index, val);
@@ -1158,8 +1189,8 @@ static int ac97_post_load (void *opaque, int version_id)
                 mixer_load (s, AC97_Master_Volume_Mute));
     set_volume (s, AC97_PCM_Out_Volume_Mute,
                 mixer_load (s, AC97_PCM_Out_Volume_Mute));
-    set_volume (s, AC97_Line_In_Volume_Mute,
-                mixer_load (s, AC97_Line_In_Volume_Mute));
+    set_volume (s, AC97_Record_Gain_Mute,
+                mixer_load (s, AC97_Record_Gain_Mute));
 
     active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
     active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
@@ -1288,13 +1319,12 @@ static int ac97_initfn (PCIDevice *dev)
     return 0;
 }
 
-static int ac97_exitfn (PCIDevice *dev)
+static void ac97_exitfn (PCIDevice *dev)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
 
     memory_region_destroy (&s->io_nam);
     memory_region_destroy (&s->io_nabm);
-    return 0;
 }
 
 int ac97_init (PCIBus *bus)
This page took 0.032365 seconds and 4 git commands to generate.