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