]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/alsa-post-ga-hda-robust-codec-probe
Changed checkfs to auto reboot after correctable fsck fixes.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-post-ga-hda-robust-codec-probe
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: hda - Make codec-probing more robust
3 Patch-mainline: 2.6.29-rc1
4 References: bnc#502733
5
6 When an error occurs during the codec probing, typically accessing to an
7 non-existing codec slot, the controller chip gets often screwed up and
8 can no longer communicate with the codecs.
9
10 This patch adds a preparation phase just to probe codec addresses before
11 actually creating codec instances. If any error occurs during this
12 probing phase, the driver resets the controller to recover.
13
14 This will (hopefully) fix the famous "single_cmd" errors.
15
16 Signed-off-by: Takashi Iwai <tiwai@suse.de>
17
18 ---
19 sound/pci/hda/hda_intel.c | 88 ++++++++++++++++++++++++++++++----------------
20 1 file changed, 59 insertions(+), 29 deletions(-)
21
22 --- a/sound/pci/hda/hda_intel.c
23 +++ b/sound/pci/hda/hda_intel.c
24 @@ -392,6 +392,7 @@ struct azx {
25 unsigned int msi :1;
26 unsigned int irq_pending_warned :1;
27 unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
28 + unsigned int probing :1; /* codec probing phase */
29
30 /* for debugging */
31 unsigned int last_cmd; /* last issued command (to sync) */
32 @@ -624,6 +625,14 @@ static unsigned int azx_rirb_get_respons
33 goto again;
34 }
35
36 + if (chip->probing) {
37 + /* If this critical timeout happens during the codec probing
38 + * phase, this is likely an access to a non-existing codec
39 + * slot. Better to return an error and reset the system.
40 + */
41 + return -1;
42 + }
43 +
44 snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
45 "switching to single_cmd mode: last cmd=0x%08x\n",
46 chip->last_cmd);
47 @@ -1178,6 +1187,26 @@ static int azx_setup_controller(struct a
48 return 0;
49 }
50
51 +/*
52 + * Probe the given codec address
53 + */
54 +static int probe_codec(struct azx *chip, int addr)
55 +{
56 + unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
57 + (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
58 + unsigned int res;
59 +
60 + chip->probing = 1;
61 + azx_send_cmd(chip->bus, cmd);
62 + res = azx_get_response(chip->bus);
63 + chip->probing = 0;
64 + if (res == -1)
65 + return -EIO;
66 + snd_printdd("hda_intel: codec #%d probed OK\n", addr);
67 + return 0;
68 +}
69 +
70 +static void azx_stop_chip(struct azx *chip);
71
72 /*
73 * Codec initialization
74 @@ -1188,21 +1217,12 @@ static unsigned int azx_max_codecs[AZX_N
75 [AZX_DRIVER_TERA] = 1,
76 };
77
78 -/* number of slots to probe as default
79 - * this can be different from azx_max_codecs[] -- e.g. some boards
80 - * report wrongly the non-existing 4th slot availability
81 - */
82 -static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = {
83 - [AZX_DRIVER_ICH] = 3,
84 - [AZX_DRIVER_ATI] = 3,
85 -};
86 -
87 static int __devinit azx_codec_create(struct azx *chip, const char *model,
88 unsigned int codec_probe_mask)
89 {
90 struct hda_bus_template bus_temp;
91 - int c, codecs, audio_codecs, err;
92 - int def_slots, max_slots;
93 + int c, codecs, err;
94 + int max_slots;
95
96 memset(&bus_temp, 0, sizeof(bus_temp));
97 bus_temp.private_data = chip;
98 @@ -1221,33 +1241,43 @@ static int __devinit azx_codec_create(st
99 if (chip->driver_type == AZX_DRIVER_NVIDIA)
100 chip->bus->needs_damn_long_delay = 1;
101
102 - codecs = audio_codecs = 0;
103 + codecs = 0;
104 max_slots = azx_max_codecs[chip->driver_type];
105 if (!max_slots)
106 max_slots = AZX_MAX_CODECS;
107 - def_slots = azx_default_codecs[chip->driver_type];
108 - if (!def_slots)
109 - def_slots = max_slots;
110 - for (c = 0; c < def_slots; c++) {
111 +
112 + /* First try to probe all given codec slots */
113 + for (c = 0; c < max_slots; c++) {
114 + if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
115 + if (probe_codec(chip, c) < 0) {
116 + /* Some BIOSen give you wrong codec addresses
117 + * that don't exist
118 + */
119 + snd_printk(KERN_WARNING
120 + "hda_intel: Codec #%d probe error; "
121 + "disabling it...\n", c);
122 + chip->codec_mask &= ~(1 << c);
123 + /* More badly, accessing to a non-existing
124 + * codec often screws up the controller chip,
125 + * and distrubs the further communications.
126 + * Thus if an error occurs during probing,
127 + * better to reset the controller chip to
128 + * get back to the sanity state.
129 + */
130 + azx_stop_chip(chip);
131 + azx_init_chip(chip);
132 + }
133 + }
134 + }
135 +
136 + /* Then create codec instances */
137 + for (c = 0; c < max_slots; c++) {
138 if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
139 struct hda_codec *codec;
140 err = snd_hda_codec_new(chip->bus, c, &codec);
141 if (err < 0)
142 continue;
143 codecs++;
144 - if (codec->afg)
145 - audio_codecs++;
146 - }
147 - }
148 - if (!audio_codecs) {
149 - /* probe additional slots if no codec is found */
150 - for (; c < max_slots; c++) {
151 - if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
152 - err = snd_hda_codec_new(chip->bus, c, NULL);
153 - if (err < 0)
154 - continue;
155 - codecs++;
156 - }
157 }
158 }
159 if (!codecs) {