]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
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) { |