]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/alsa-post-ga-hda-codec-verb-retry
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / alsa-post-ga-hda-codec-verb-retry
CommitLineData
2cb7cef9
BS
1From: Takashi Iwai <tiwai@suse.de>
2Subject: ALSA: Add codec bus reset and verb-retry at critical errors
3Patch-mainline:
4References: bnc#502903
5
6The Volna machine causes a severe CORB/RIRB stall when PA is started
7together with fglrx. This cannot be recovered without the controller
8reset.
9
10This patch allows the bus controller reset at critical errors so
11that the communication gets recovered again.
12
13Signed-off-by: Takashi Iwai <tiwai@suse.de>
14
15---
16 sound/pci/hda/hda_codec.c | 13 +++++++++++--
17 sound/pci/hda/hda_codec.h | 7 ++++++-
18 sound/pci/hda/hda_intel.c | 37 +++++++++++++++++++++++++++++++++----
19 3 files changed, 50 insertions(+), 7 deletions(-)
20
21--- a/sound/pci/hda/hda_codec.h
22+++ b/sound/pci/hda/hda_codec.h
23@@ -541,6 +541,8 @@
24 unsigned int (*get_response)(struct hda_bus *bus);
25 /* free the private data */
26 void (*private_free)(struct hda_bus *);
27+ /* reset bus for retry verb */
28+ void (*bus_reset)(struct hda_bus *bus);
29 #ifdef CONFIG_SND_HDA_POWER_SAVE
30 /* notify power-up/down from codec to controller */
31 void (*pm_notify)(struct hda_bus *bus);
32@@ -586,6 +588,9 @@
33
34 /* misc op flags */
35 unsigned int needs_damn_long_delay :1;
36+ unsigned int rirb_error:1; /* error in codec communication */
37+ unsigned int response_reset:1; /* controller was reset */
38+ unsigned int in_reset:1; /* during reset operation */
39 };
40
41 /*
42@@ -827,7 +832,7 @@
43 * power management
44 */
45 #ifdef CONFIG_PM
46-int snd_hda_suspend(struct hda_bus *bus, pm_message_t state);
47+int snd_hda_suspend(struct hda_bus *bus);
48 int snd_hda_resume(struct hda_bus *bus);
49 #endif
50
51--- a/sound/pci/hda/hda_codec.c
52+++ b/sound/pci/hda/hda_codec.c
53@@ -187,6 +187,7 @@
54
55 if (res)
56 *res = -1;
57+ again:
58 snd_hda_power_up(codec);
59 mutex_lock(&bus->cmd_mutex);
60 err = bus->ops.command(bus, cmd);
61@@ -194,6 +195,15 @@
62 *res = bus->ops.get_response(bus);
63 mutex_unlock(&bus->cmd_mutex);
64 snd_hda_power_down(codec);
65+ if (res && *res == -1 && bus->rirb_error) {
66+ if (bus->response_reset) {
67+ snd_printd("hda_codec: resetting BUS due to "
68+ "fatal communication error\n");
69+ bus->ops.bus_reset(bus);
70+ }
71+ goto again;
72+ }
73+ bus->response_reset = 0;
74 return err;
75 }
76
77@@ -3279,11 +3289,10 @@
78 /**
79 * snd_hda_suspend - suspend the codecs
80 * @bus: the HDA bus
81- * @state: suspsend state
82 *
83 * Returns 0 if successful.
84 */
85-int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
86+int snd_hda_suspend(struct hda_bus *bus)
87 {
88 struct hda_codec *codec;
89
90--- a/sound/pci/hda/hda_intel.c
91+++ b/sound/pci/hda/hda_intel.c
92@@ -600,6 +600,7 @@
93 }
94 if (!chip->rirb.cmds) {
95 smp_rmb();
96+ bus->rirb_error = 0;
97 return chip->rirb.res; /* the last value */
98 }
99 if (time_after(jiffies, timeout))
100@@ -640,14 +641,23 @@
101 return -1;
102 }
103
104+ /* a fatal communication error; need either to reset or to fallback
105+ * to the single_cmd mode
106+ */
107+ bus->rirb_error = 1;
108+ if (!bus->response_reset && !bus->in_reset) {
109+ bus->response_reset = 1;
110+ return -1; /* give a chance to retry */
111+ }
112+
113 snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
114 "switching to single_cmd mode: last cmd=0x%08x\n",
115 chip->last_cmd);
116- chip->rirb.rp = azx_readb(chip, RIRBWP);
117- chip->rirb.cmds = 0;
118- /* switch to single_cmd mode */
119 chip->single_cmd = 1;
120+ bus->response_reset = 0;
121+ /* re-initialize CORB/RIRB */
122 azx_free_cmd_io(chip);
123+ azx_init_cmd_io(chip);
124 return -1;
125 }
126
127@@ -688,6 +698,7 @@
128 struct azx *chip = bus->private_data;
129 int timeout = 50;
130
131+ bus->rirb_error = 0;
132 while (timeout--) {
133 /* check ICB busy bit */
134 if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
135@@ -1227,6 +1238,23 @@
136
137 static void azx_stop_chip(struct azx *chip);
138
139+static void azx_bus_reset(struct hda_bus *bus)
140+{
141+ struct azx *chip = bus->private_data;
142+ int i;
143+
144+ bus->in_reset = 1;
145+ azx_stop_chip(chip);
146+ azx_init_chip(chip);
147+ if (chip->initialized) {
148+ for (i = 0; i < AZX_MAX_PCMS; i++)
149+ snd_pcm_suspend_all(chip->pcm[i]);
150+ snd_hda_suspend(chip->bus);
151+ snd_hda_resume(chip->bus);
152+ }
153+ bus->in_reset = 0;
154+}
155+
156 /*
157 * Codec initialization
158 */
159@@ -1248,6 +1276,7 @@
160 bus_temp.pci = chip->pci;
161 bus_temp.ops.command = azx_send_cmd;
162 bus_temp.ops.get_response = azx_get_response;
163+ bus_temp.ops.bus_reset = azx_bus_reset;
164 #ifdef CONFIG_SND_HDA_POWER_SAVE
165 bus_temp.ops.pm_notify = azx_power_notify;
166 #endif
167@@ -2013,7 +2042,7 @@
168 for (i = 0; i < AZX_MAX_PCMS; i++)
169 snd_pcm_suspend_all(chip->pcm[i]);
170 if (chip->initialized)
171- snd_hda_suspend(chip->bus, state);
172+ snd_hda_suspend(chip->bus);
173 azx_stop_chip(chip);
174 if (chip->irq >= 0) {
175 free_irq(chip->irq, chip);