summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/ac97.c91
1 files changed, 60 insertions, 31 deletions
diff --git a/hw/ac97.c b/hw/ac97.c
index ba4ea1e513..83b4383081 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -158,6 +158,7 @@ typedef struct AC97LinkState {
     SWVoiceIn *voice_pi;
     SWVoiceOut *voice_po;
     SWVoiceIn *voice_mc;
+    int invalid_freq[3];
     uint8_t silence[128];
     uint32_t base[2];
     int bup_flag;
@@ -360,39 +361,61 @@ static void open_voice (AC97LinkState *s, int index, int freq)
     as.fmt = AUD_FMT_S16;
     as.endianness = 0;
 
-    switch (index) {
-    case PI_INDEX:
-        s->voice_pi = AUD_open_in (
-            &s->card,
-            s->voice_pi,
-            "ac97.pi",
-            s,
-            pi_callback,
-            &as
-            );
-        break;
+    if (freq > 0) {
+        s->invalid_freq[index] = 0;
+        switch (index) {
+        case PI_INDEX:
+            s->voice_pi = AUD_open_in (
+                &s->card,
+                s->voice_pi,
+                "ac97.pi",
+                s,
+                pi_callback,
+                &as
+                );
+            break;
 
-    case PO_INDEX:
-        s->voice_po = AUD_open_out (
-            &s->card,
-            s->voice_po,
-            "ac97.po",
-            s,
-            po_callback,
-            &as
-            );
-        break;
+        case PO_INDEX:
+            s->voice_po = AUD_open_out (
+                &s->card,
+                s->voice_po,
+                "ac97.po",
+                s,
+                po_callback,
+                &as
+                );
+            break;
 
-    case MC_INDEX:
-        s->voice_mc = AUD_open_in (
-            &s->card,
-            s->voice_mc,
-            "ac97.mc",
-            s,
-            mc_callback,
-            &as
-            );
-        break;
+        case MC_INDEX:
+            s->voice_mc = AUD_open_in (
+                &s->card,
+                s->voice_mc,
+                "ac97.mc",
+                s,
+                mc_callback,
+                &as
+                );
+            break;
+        }
+    }
+    else {
+        s->invalid_freq[index] = freq;
+        switch (index) {
+        case PI_INDEX:
+            AUD_close_in (&s->card, s->voice_pi);
+            s->voice_pi = NULL;
+            break;
+
+        case PO_INDEX:
+            AUD_close_out (&s->card, s->voice_po);
+            s->voice_po = NULL;
+            break;
+
+        case MC_INDEX:
+            AUD_close_in (&s->card, s->voice_mc);
+            s->voice_mc = NULL;
+            break;
+        }
     }
 }
 
@@ -1065,6 +1088,12 @@ static void transfer_audio (AC97LinkState *s, int index, int elapsed)
     AC97BusMasterRegs *r = &s->bm_regs[index];
     int written = 0, stop = 0;
 
+    if (s->invalid_freq[index]) {
+        AUD_log ("ac97", "attempt to use voice %d with invalid frequency %d\n",
+                 index, s->invalid_freq[index]);
+        return;
+    }
+
     if (r->sr & SR_DCH) {
         if (r->cr & CR_RPBM) {
             switch (index) {