xref: /linux/sound/hda/codecs/realtek/alc880.c (revision 177bf8620cf4ed290ee170a6c5966adc0924b336)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // Realtek ALC880 codec
4 //
5 
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include "realtek.h"
9 
alc880_unsol_event(struct hda_codec * codec,unsigned int res)10 static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
11 {
12 	/* For some reason, the res given from ALC880 is broken.
13 	   Here we adjust it properly. */
14 	snd_hda_jack_unsol_event(codec, res >> 2);
15 }
16 
alc880_parse_auto_config(struct hda_codec * codec)17 static int alc880_parse_auto_config(struct hda_codec *codec)
18 {
19 	static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
20 	static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
21 	return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
22 }
23 
24 /*
25  * ALC880 fix-ups
26  */
27 enum {
28 	ALC880_FIXUP_GPIO1,
29 	ALC880_FIXUP_GPIO2,
30 	ALC880_FIXUP_MEDION_RIM,
31 	ALC880_FIXUP_LG,
32 	ALC880_FIXUP_LG_LW25,
33 	ALC880_FIXUP_W810,
34 	ALC880_FIXUP_EAPD_COEF,
35 	ALC880_FIXUP_TCL_S700,
36 	ALC880_FIXUP_VOL_KNOB,
37 	ALC880_FIXUP_FUJITSU,
38 	ALC880_FIXUP_F1734,
39 	ALC880_FIXUP_UNIWILL,
40 	ALC880_FIXUP_UNIWILL_DIG,
41 	ALC880_FIXUP_Z71V,
42 	ALC880_FIXUP_ASUS_W5A,
43 	ALC880_FIXUP_3ST_BASE,
44 	ALC880_FIXUP_3ST,
45 	ALC880_FIXUP_3ST_DIG,
46 	ALC880_FIXUP_5ST_BASE,
47 	ALC880_FIXUP_5ST,
48 	ALC880_FIXUP_5ST_DIG,
49 	ALC880_FIXUP_6ST_BASE,
50 	ALC880_FIXUP_6ST,
51 	ALC880_FIXUP_6ST_DIG,
52 	ALC880_FIXUP_6ST_AUTOMUTE,
53 };
54 
55 /* enable the volume-knob widget support on NID 0x21 */
alc880_fixup_vol_knob(struct hda_codec * codec,const struct hda_fixup * fix,int action)56 static void alc880_fixup_vol_knob(struct hda_codec *codec,
57 				  const struct hda_fixup *fix, int action)
58 {
59 	if (action == HDA_FIXUP_ACT_PROBE)
60 		snd_hda_jack_detect_enable_callback(codec, 0x21,
61 						    alc_update_knob_master);
62 }
63 
64 static const struct hda_fixup alc880_fixups[] = {
65 	[ALC880_FIXUP_GPIO1] = {
66 		.type = HDA_FIXUP_FUNC,
67 		.v.func = alc_fixup_gpio1,
68 	},
69 	[ALC880_FIXUP_GPIO2] = {
70 		.type = HDA_FIXUP_FUNC,
71 		.v.func = alc_fixup_gpio2,
72 	},
73 	[ALC880_FIXUP_MEDION_RIM] = {
74 		.type = HDA_FIXUP_VERBS,
75 		.v.verbs = (const struct hda_verb[]) {
76 			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
77 			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3060 },
78 			{ }
79 		},
80 		.chained = true,
81 		.chain_id = ALC880_FIXUP_GPIO2,
82 	},
83 	[ALC880_FIXUP_LG] = {
84 		.type = HDA_FIXUP_PINS,
85 		.v.pins = (const struct hda_pintbl[]) {
86 			/* disable bogus unused pins */
87 			{ 0x16, 0x411111f0 },
88 			{ 0x18, 0x411111f0 },
89 			{ 0x1a, 0x411111f0 },
90 			{ }
91 		}
92 	},
93 	[ALC880_FIXUP_LG_LW25] = {
94 		.type = HDA_FIXUP_PINS,
95 		.v.pins = (const struct hda_pintbl[]) {
96 			{ 0x1a, 0x0181344f }, /* line-in */
97 			{ 0x1b, 0x0321403f }, /* headphone */
98 			{ }
99 		}
100 	},
101 	[ALC880_FIXUP_W810] = {
102 		.type = HDA_FIXUP_PINS,
103 		.v.pins = (const struct hda_pintbl[]) {
104 			/* disable bogus unused pins */
105 			{ 0x17, 0x411111f0 },
106 			{ }
107 		},
108 		.chained = true,
109 		.chain_id = ALC880_FIXUP_GPIO2,
110 	},
111 	[ALC880_FIXUP_EAPD_COEF] = {
112 		.type = HDA_FIXUP_VERBS,
113 		.v.verbs = (const struct hda_verb[]) {
114 			/* change to EAPD mode */
115 			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
116 			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3060 },
117 			{}
118 		},
119 	},
120 	[ALC880_FIXUP_TCL_S700] = {
121 		.type = HDA_FIXUP_VERBS,
122 		.v.verbs = (const struct hda_verb[]) {
123 			/* change to EAPD mode */
124 			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
125 			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3070 },
126 			{}
127 		},
128 		.chained = true,
129 		.chain_id = ALC880_FIXUP_GPIO2,
130 	},
131 	[ALC880_FIXUP_VOL_KNOB] = {
132 		.type = HDA_FIXUP_FUNC,
133 		.v.func = alc880_fixup_vol_knob,
134 	},
135 	[ALC880_FIXUP_FUJITSU] = {
136 		/* override all pins as BIOS on old Amilo is broken */
137 		.type = HDA_FIXUP_PINS,
138 		.v.pins = (const struct hda_pintbl[]) {
139 			{ 0x14, 0x0121401f }, /* HP */
140 			{ 0x15, 0x99030120 }, /* speaker */
141 			{ 0x16, 0x99030130 }, /* bass speaker */
142 			{ 0x17, 0x411111f0 }, /* N/A */
143 			{ 0x18, 0x411111f0 }, /* N/A */
144 			{ 0x19, 0x01a19950 }, /* mic-in */
145 			{ 0x1a, 0x411111f0 }, /* N/A */
146 			{ 0x1b, 0x411111f0 }, /* N/A */
147 			{ 0x1c, 0x411111f0 }, /* N/A */
148 			{ 0x1d, 0x411111f0 }, /* N/A */
149 			{ 0x1e, 0x01454140 }, /* SPDIF out */
150 			{ }
151 		},
152 		.chained = true,
153 		.chain_id = ALC880_FIXUP_VOL_KNOB,
154 	},
155 	[ALC880_FIXUP_F1734] = {
156 		/* almost compatible with FUJITSU, but no bass and SPDIF */
157 		.type = HDA_FIXUP_PINS,
158 		.v.pins = (const struct hda_pintbl[]) {
159 			{ 0x14, 0x0121401f }, /* HP */
160 			{ 0x15, 0x99030120 }, /* speaker */
161 			{ 0x16, 0x411111f0 }, /* N/A */
162 			{ 0x17, 0x411111f0 }, /* N/A */
163 			{ 0x18, 0x411111f0 }, /* N/A */
164 			{ 0x19, 0x01a19950 }, /* mic-in */
165 			{ 0x1a, 0x411111f0 }, /* N/A */
166 			{ 0x1b, 0x411111f0 }, /* N/A */
167 			{ 0x1c, 0x411111f0 }, /* N/A */
168 			{ 0x1d, 0x411111f0 }, /* N/A */
169 			{ 0x1e, 0x411111f0 }, /* N/A */
170 			{ }
171 		},
172 		.chained = true,
173 		.chain_id = ALC880_FIXUP_VOL_KNOB,
174 	},
175 	[ALC880_FIXUP_UNIWILL] = {
176 		/* need to fix HP and speaker pins to be parsed correctly */
177 		.type = HDA_FIXUP_PINS,
178 		.v.pins = (const struct hda_pintbl[]) {
179 			{ 0x14, 0x0121411f }, /* HP */
180 			{ 0x15, 0x99030120 }, /* speaker */
181 			{ 0x16, 0x99030130 }, /* bass speaker */
182 			{ }
183 		},
184 	},
185 	[ALC880_FIXUP_UNIWILL_DIG] = {
186 		.type = HDA_FIXUP_PINS,
187 		.v.pins = (const struct hda_pintbl[]) {
188 			/* disable bogus unused pins */
189 			{ 0x17, 0x411111f0 },
190 			{ 0x19, 0x411111f0 },
191 			{ 0x1b, 0x411111f0 },
192 			{ 0x1f, 0x411111f0 },
193 			{ }
194 		}
195 	},
196 	[ALC880_FIXUP_Z71V] = {
197 		.type = HDA_FIXUP_PINS,
198 		.v.pins = (const struct hda_pintbl[]) {
199 			/* set up the whole pins as BIOS is utterly broken */
200 			{ 0x14, 0x99030120 }, /* speaker */
201 			{ 0x15, 0x0121411f }, /* HP */
202 			{ 0x16, 0x411111f0 }, /* N/A */
203 			{ 0x17, 0x411111f0 }, /* N/A */
204 			{ 0x18, 0x01a19950 }, /* mic-in */
205 			{ 0x19, 0x411111f0 }, /* N/A */
206 			{ 0x1a, 0x01813031 }, /* line-in */
207 			{ 0x1b, 0x411111f0 }, /* N/A */
208 			{ 0x1c, 0x411111f0 }, /* N/A */
209 			{ 0x1d, 0x411111f0 }, /* N/A */
210 			{ 0x1e, 0x0144111e }, /* SPDIF */
211 			{ }
212 		}
213 	},
214 	[ALC880_FIXUP_ASUS_W5A] = {
215 		.type = HDA_FIXUP_PINS,
216 		.v.pins = (const struct hda_pintbl[]) {
217 			/* set up the whole pins as BIOS is utterly broken */
218 			{ 0x14, 0x0121411f }, /* HP */
219 			{ 0x15, 0x411111f0 }, /* N/A */
220 			{ 0x16, 0x411111f0 }, /* N/A */
221 			{ 0x17, 0x411111f0 }, /* N/A */
222 			{ 0x18, 0x90a60160 }, /* mic */
223 			{ 0x19, 0x411111f0 }, /* N/A */
224 			{ 0x1a, 0x411111f0 }, /* N/A */
225 			{ 0x1b, 0x411111f0 }, /* N/A */
226 			{ 0x1c, 0x411111f0 }, /* N/A */
227 			{ 0x1d, 0x411111f0 }, /* N/A */
228 			{ 0x1e, 0xb743111e }, /* SPDIF out */
229 			{ }
230 		},
231 		.chained = true,
232 		.chain_id = ALC880_FIXUP_GPIO1,
233 	},
234 	[ALC880_FIXUP_3ST_BASE] = {
235 		.type = HDA_FIXUP_PINS,
236 		.v.pins = (const struct hda_pintbl[]) {
237 			{ 0x14, 0x01014010 }, /* line-out */
238 			{ 0x15, 0x411111f0 }, /* N/A */
239 			{ 0x16, 0x411111f0 }, /* N/A */
240 			{ 0x17, 0x411111f0 }, /* N/A */
241 			{ 0x18, 0x01a19c30 }, /* mic-in */
242 			{ 0x19, 0x0121411f }, /* HP */
243 			{ 0x1a, 0x01813031 }, /* line-in */
244 			{ 0x1b, 0x02a19c40 }, /* front-mic */
245 			{ 0x1c, 0x411111f0 }, /* N/A */
246 			{ 0x1d, 0x411111f0 }, /* N/A */
247 			/* 0x1e is filled in below */
248 			{ 0x1f, 0x411111f0 }, /* N/A */
249 			{ }
250 		}
251 	},
252 	[ALC880_FIXUP_3ST] = {
253 		.type = HDA_FIXUP_PINS,
254 		.v.pins = (const struct hda_pintbl[]) {
255 			{ 0x1e, 0x411111f0 }, /* N/A */
256 			{ }
257 		},
258 		.chained = true,
259 		.chain_id = ALC880_FIXUP_3ST_BASE,
260 	},
261 	[ALC880_FIXUP_3ST_DIG] = {
262 		.type = HDA_FIXUP_PINS,
263 		.v.pins = (const struct hda_pintbl[]) {
264 			{ 0x1e, 0x0144111e }, /* SPDIF */
265 			{ }
266 		},
267 		.chained = true,
268 		.chain_id = ALC880_FIXUP_3ST_BASE,
269 	},
270 	[ALC880_FIXUP_5ST_BASE] = {
271 		.type = HDA_FIXUP_PINS,
272 		.v.pins = (const struct hda_pintbl[]) {
273 			{ 0x14, 0x01014010 }, /* front */
274 			{ 0x15, 0x411111f0 }, /* N/A */
275 			{ 0x16, 0x01011411 }, /* CLFE */
276 			{ 0x17, 0x01016412 }, /* surr */
277 			{ 0x18, 0x01a19c30 }, /* mic-in */
278 			{ 0x19, 0x0121411f }, /* HP */
279 			{ 0x1a, 0x01813031 }, /* line-in */
280 			{ 0x1b, 0x02a19c40 }, /* front-mic */
281 			{ 0x1c, 0x411111f0 }, /* N/A */
282 			{ 0x1d, 0x411111f0 }, /* N/A */
283 			/* 0x1e is filled in below */
284 			{ 0x1f, 0x411111f0 }, /* N/A */
285 			{ }
286 		}
287 	},
288 	[ALC880_FIXUP_5ST] = {
289 		.type = HDA_FIXUP_PINS,
290 		.v.pins = (const struct hda_pintbl[]) {
291 			{ 0x1e, 0x411111f0 }, /* N/A */
292 			{ }
293 		},
294 		.chained = true,
295 		.chain_id = ALC880_FIXUP_5ST_BASE,
296 	},
297 	[ALC880_FIXUP_5ST_DIG] = {
298 		.type = HDA_FIXUP_PINS,
299 		.v.pins = (const struct hda_pintbl[]) {
300 			{ 0x1e, 0x0144111e }, /* SPDIF */
301 			{ }
302 		},
303 		.chained = true,
304 		.chain_id = ALC880_FIXUP_5ST_BASE,
305 	},
306 	[ALC880_FIXUP_6ST_BASE] = {
307 		.type = HDA_FIXUP_PINS,
308 		.v.pins = (const struct hda_pintbl[]) {
309 			{ 0x14, 0x01014010 }, /* front */
310 			{ 0x15, 0x01016412 }, /* surr */
311 			{ 0x16, 0x01011411 }, /* CLFE */
312 			{ 0x17, 0x01012414 }, /* side */
313 			{ 0x18, 0x01a19c30 }, /* mic-in */
314 			{ 0x19, 0x02a19c40 }, /* front-mic */
315 			{ 0x1a, 0x01813031 }, /* line-in */
316 			{ 0x1b, 0x0121411f }, /* HP */
317 			{ 0x1c, 0x411111f0 }, /* N/A */
318 			{ 0x1d, 0x411111f0 }, /* N/A */
319 			/* 0x1e is filled in below */
320 			{ 0x1f, 0x411111f0 }, /* N/A */
321 			{ }
322 		}
323 	},
324 	[ALC880_FIXUP_6ST] = {
325 		.type = HDA_FIXUP_PINS,
326 		.v.pins = (const struct hda_pintbl[]) {
327 			{ 0x1e, 0x411111f0 }, /* N/A */
328 			{ }
329 		},
330 		.chained = true,
331 		.chain_id = ALC880_FIXUP_6ST_BASE,
332 	},
333 	[ALC880_FIXUP_6ST_DIG] = {
334 		.type = HDA_FIXUP_PINS,
335 		.v.pins = (const struct hda_pintbl[]) {
336 			{ 0x1e, 0x0144111e }, /* SPDIF */
337 			{ }
338 		},
339 		.chained = true,
340 		.chain_id = ALC880_FIXUP_6ST_BASE,
341 	},
342 	[ALC880_FIXUP_6ST_AUTOMUTE] = {
343 		.type = HDA_FIXUP_PINS,
344 		.v.pins = (const struct hda_pintbl[]) {
345 			{ 0x1b, 0x0121401f }, /* HP with jack detect */
346 			{ }
347 		},
348 		.chained_before = true,
349 		.chain_id = ALC880_FIXUP_6ST_BASE,
350 	},
351 };
352 
353 static const struct hda_quirk alc880_fixup_tbl[] = {
354 	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
355 	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
356 	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
357 	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
358 	SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE),
359 	SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
360 	SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
361 	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
362 	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
363 	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
364 	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
365 	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
366 	SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
367 	SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
368 	SND_PCI_QUIRK(0x1734, 0x107c, "FSC Amilo M1437", ALC880_FIXUP_FUJITSU),
369 	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
370 	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
371 	SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
372 	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
373 	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
374 	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
375 	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
376 	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
377 
378 	/* Below is the copied entries from alc880_quirks.c.
379 	 * It's not quite sure whether BIOS sets the correct pin-config table
380 	 * on these machines, thus they are kept to be compatible with
381 	 * the old static quirks.  Once when it's confirmed to work without
382 	 * these overrides, it'd be better to remove.
383 	 */
384 	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
385 	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
386 	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
387 	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
388 	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
389 	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
390 	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
391 	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
392 	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
393 	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
394 	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
395 	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
396 	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
397 	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
398 	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
399 	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
400 	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
401 	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
402 	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
403 	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
404 	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
405 	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
406 	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
407 	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
408 	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
409 	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
410 	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
411 	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
412 	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
413 	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
414 	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
415 	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
416 	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
417 	/* default Intel */
418 	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
419 	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
420 	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
421 	{}
422 };
423 
424 static const struct hda_model_fixup alc880_fixup_models[] = {
425 	{.id = ALC880_FIXUP_3ST, .name = "3stack"},
426 	{.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
427 	{.id = ALC880_FIXUP_5ST, .name = "5stack"},
428 	{.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
429 	{.id = ALC880_FIXUP_6ST, .name = "6stack"},
430 	{.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
431 	{.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
432 	{}
433 };
434 
435 
436 /*
437  * OK, here we have finally the probe for ALC880
438  */
alc880_probe(struct hda_codec * codec,const struct hda_device_id * id)439 static int alc880_probe(struct hda_codec *codec, const struct hda_device_id *id)
440 {
441 	struct alc_spec *spec;
442 	int err;
443 
444 	err = alc_alloc_spec(codec, 0x0b);
445 	if (err < 0)
446 		return err;
447 
448 	spec = codec->spec;
449 	spec->gen.need_dac_fix = 1;
450 	spec->gen.beep_nid = 0x01;
451 
452 	alc_pre_init(codec);
453 
454 	snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
455 		       alc880_fixups);
456 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
457 
458 	/* automatic parse from the BIOS config */
459 	err = alc880_parse_auto_config(codec);
460 	if (err < 0)
461 		goto error;
462 
463 	if (!spec->gen.no_analog) {
464 		err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
465 		if (err < 0)
466 			goto error;
467 	}
468 
469 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
470 
471 	return 0;
472 
473  error:
474 	snd_hda_gen_remove(codec);
475 	return err;
476 }
477 
478 static const struct hda_codec_ops alc880_codec_ops = {
479 	.probe = alc880_probe,
480 	.remove = snd_hda_gen_remove,
481 	.build_controls = alc_build_controls,
482 	.build_pcms = snd_hda_gen_build_pcms,
483 	.init = alc_init,
484 	.unsol_event = alc880_unsol_event,
485 	.resume = alc_resume,
486 	.suspend = alc_suspend,
487 	.check_power_status = snd_hda_gen_check_power_status,
488 	.stream_pm = snd_hda_gen_stream_pm,
489 };
490 
491 /*
492  * driver entries
493  */
494 static const struct hda_device_id snd_hda_id_alc880[] = {
495 	HDA_CODEC_ID(0x10ec0880, "ALC880"),
496 	{} /* terminator */
497 };
498 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc880);
499 
500 MODULE_LICENSE("GPL");
501 MODULE_DESCRIPTION("Realtek ALC880 HD-audio codec");
502 MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
503 
504 static struct hda_codec_driver alc880_driver = {
505 	.id = snd_hda_id_alc880,
506 	.ops = &alc880_codec_ops,
507 };
508 
509 module_hda_codec_driver(alc880_driver);
510