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 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 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 */ 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 */ 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