]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/alsa-post-ga-hda-codec-verb-retry
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-post-ga-hda-codec-verb-retry
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: Add codec bus reset and verb-retry at critical errors
3 Patch-mainline:
4 References: bnc#502903
5
6 The Volna machine causes a severe CORB/RIRB stall when PA is started
7 together with fglrx. This cannot be recovered without the controller
8 reset.
9
10 This patch allows the bus controller reset at critical errors so
11 that the communication gets recovered again.
12
13 Signed-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);