Blame 0219-hda-do-not-mix-output-and-input-stream-states-RHBZ-7.patch

cd9d16
From 51a747e171a66d0dc1e4b47c0238fb2e7fa6b118 Mon Sep 17 00:00:00 2001
cd9d16
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
cd9d16
Date: Tue, 25 Oct 2011 16:53:01 +0200
cd9d16
Subject: [PATCH] hda: do not mix output and input stream states, RHBZ #740493
cd9d16
MIME-Version: 1.0
cd9d16
Content-Type: text/plain; charset=UTF-8
cd9d16
Content-Transfer-Encoding: 8bit
cd9d16
cd9d16
Windows 7 may use the same stream number for input and output.
cd9d16
Current code will confuse streams.
cd9d16
cd9d16
Changes since v1:
cd9d16
- keep running_compat[] for migration version 1
cd9d16
- add running_real[] for migration version 2
cd9d16
cd9d16
Signed-off-by: Marc-Andr? Lureau <marcandre.lureau@redhat.com>
cd9d16
Signed-off-by: malc <av1474@comtv.ru>
cd9d16
(cherry picked from commit ba43d28916c4f51c19bd7366089155ce81bee058)
cd9d16
cd9d16
Signed-off-by: Bruce Rogers <brogers@suse.com>
cd9d16
Signed-off-by: Andreas Färber <afaerber@suse.de>
cd9d16
---
cd9d16
 hw/hda-audio.c | 26 +++++++++++++++++++-------
cd9d16
 hw/intel-hda.c |  9 +++++----
cd9d16
 hw/intel-hda.h |  2 +-
cd9d16
 3 files changed, 25 insertions(+), 12 deletions(-)
cd9d16
cd9d16
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
cd9d16
index c699d6f..9b089e6 100644
cd9d16
--- a/hw/hda-audio.c
cd9d16
+++ b/hw/hda-audio.c
cd9d16
@@ -466,7 +466,8 @@ struct HDAAudioState {
cd9d16
     QEMUSoundCard card;
cd9d16
     const desc_codec *desc;
cd9d16
     HDAAudioStream st[4];
cd9d16
-    bool running[16];
cd9d16
+    bool running_compat[16];
cd9d16
+    bool running_real[2 * 16];
cd9d16
 
cd9d16
     /* properties */
cd9d16
     uint32_t debug;
cd9d16
@@ -663,7 +664,7 @@ static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
cd9d16
         st->channel = payload & 0x0f;
cd9d16
         dprint(a, 2, "%s: stream %d, channel %d\n",
cd9d16
                st->node->name, st->stream, st->channel);
cd9d16
-        hda_audio_set_running(st, a->running[st->stream]);
cd9d16
+        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
cd9d16
         hda_codec_response(hda, true, 0);
cd9d16
         break;
cd9d16
     case AC_VERB_GET_CONV:
cd9d16
@@ -746,16 +747,20 @@ fail:
cd9d16
     hda_codec_response(hda, true, 0);
cd9d16
 }
cd9d16
 
cd9d16
-static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running)
cd9d16
+static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
cd9d16
 {
cd9d16
     HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
cd9d16
     int s;
cd9d16
 
cd9d16
-    a->running[stnr] = running;
cd9d16
+    a->running_compat[stnr] = running;
cd9d16
+    a->running_real[output * 16 + stnr] = running;
cd9d16
     for (s = 0; s < ARRAY_SIZE(a->st); s++) {
cd9d16
         if (a->st[s].node == NULL) {
cd9d16
             continue;
cd9d16
         }
cd9d16
+        if (a->st[s].output != output) {
cd9d16
+            continue;
cd9d16
+        }
cd9d16
         if (a->st[s].stream != stnr) {
cd9d16
             continue;
cd9d16
         }
cd9d16
@@ -837,6 +842,12 @@ static int hda_audio_post_load(void *opaque, int version)
cd9d16
     int i;
cd9d16
 
cd9d16
     dprint(a, 1, "%s\n", __FUNCTION__);
cd9d16
+    if (version == 1) {
cd9d16
+        /* assume running_compat[] is for output streams */
cd9d16
+        for (i = 0; i < ARRAY_SIZE(a->running_compat); i++)
cd9d16
+            a->running_real[16 + i] = a->running_compat[i];
cd9d16
+    }
cd9d16
+
cd9d16
     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
cd9d16
         st = a->st + i;
cd9d16
         if (st->node == NULL)
cd9d16
@@ -844,7 +855,7 @@ static int hda_audio_post_load(void *opaque, int version)
cd9d16
         hda_codec_parse_fmt(st->format, &st->as);
cd9d16
         hda_audio_setup(st);
cd9d16
         hda_audio_set_amp(st);
cd9d16
-        hda_audio_set_running(st, a->running[st->stream]);
cd9d16
+        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
cd9d16
     }
cd9d16
     return 0;
cd9d16
 }
cd9d16
@@ -868,13 +879,14 @@ static const VMStateDescription vmstate_hda_audio_stream = {
cd9d16
 
cd9d16
 static const VMStateDescription vmstate_hda_audio = {
cd9d16
     .name = "hda-audio",
cd9d16
-    .version_id = 1,
cd9d16
+    .version_id = 2,
cd9d16
     .post_load = hda_audio_post_load,
cd9d16
     .fields = (VMStateField []) {
cd9d16
         VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
cd9d16
                              vmstate_hda_audio_stream,
cd9d16
                              HDAAudioStream),
cd9d16
-        VMSTATE_BOOL_ARRAY(running, HDAAudioState, 16),
cd9d16
+        VMSTATE_BOOL_ARRAY(running_compat, HDAAudioState, 16),
cd9d16
+        VMSTATE_BOOL_ARRAY_V(running_real, HDAAudioState, 2 * 16, 2),
cd9d16
         VMSTATE_END_OF_LIST()
cd9d16
     }
cd9d16
 };
cd9d16
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
cd9d16
index 7d02558..904e4fc 100644
cd9d16
--- a/hw/intel-hda.c
cd9d16
+++ b/hw/intel-hda.c
cd9d16
@@ -485,7 +485,7 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st)
cd9d16
     st->bp    = 0;
cd9d16
 }
cd9d16
 
cd9d16
-static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running)
cd9d16
+static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output)
cd9d16
 {
cd9d16
     DeviceState *qdev;
cd9d16
     HDACodecDevice *cdev;
cd9d16
@@ -493,7 +493,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
cd9d16
     QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
cd9d16
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
cd9d16
         if (cdev->info->stream) {
cd9d16
-            cdev->info->stream(cdev, stream, running);
cd9d16
+            cdev->info->stream(cdev, stream, running, output);
cd9d16
         }
cd9d16
     }
cd9d16
 }
cd9d16
@@ -567,6 +567,7 @@ static void intel_hda_set_ics(IntelHDAState *d, const IntelHDAReg *reg, uint32_t
cd9d16
 
cd9d16
 static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
cd9d16
 {
cd9d16
+    bool output = reg->stream >= 4;
cd9d16
     IntelHDAStream *st = d->st + reg->stream;
cd9d16
 
cd9d16
     if (st->ctl & 0x01) {
cd9d16
@@ -582,11 +583,11 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3
cd9d16
             dprint(d, 1, "st #%d: start %d (ring buf %d bytes)\n",
cd9d16
                    reg->stream, stnr, st->cbl);
cd9d16
             intel_hda_parse_bdl(d, st);
cd9d16
-            intel_hda_notify_codecs(d, stnr, true);
cd9d16
+            intel_hda_notify_codecs(d, stnr, true, output);
cd9d16
         } else {
cd9d16
             /* stop */
cd9d16
             dprint(d, 1, "st #%d: stop %d\n", reg->stream, stnr);
cd9d16
-            intel_hda_notify_codecs(d, stnr, false);
cd9d16
+            intel_hda_notify_codecs(d, stnr, false, output);
cd9d16
         }
cd9d16
     }
cd9d16
     intel_hda_update_irq(d);
cd9d16
diff --git a/hw/intel-hda.h b/hw/intel-hda.h
cd9d16
index 4e44e38..65fd2a8 100644
cd9d16
--- a/hw/intel-hda.h
cd9d16
+++ b/hw/intel-hda.h
cd9d16
@@ -34,7 +34,7 @@ struct HDACodecDeviceInfo {
cd9d16
     int (*init)(HDACodecDevice *dev);
cd9d16
     int (*exit)(HDACodecDevice *dev);
cd9d16
     void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
cd9d16
-    void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running);
cd9d16
+    void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);
cd9d16
 };
cd9d16
 
cd9d16
 void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus,
cd9d16
-- 
cd9d16
1.7.11.2
cd9d16