1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // 3 // Realtek ALC262 codec 4 // 5 6 #include <linux/init.h> 7 #include <linux/module.h> 8 #include "realtek.h" 9 10 static int alc262_parse_auto_config(struct hda_codec *codec) 11 { 12 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 }; 13 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 }; 14 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids); 15 } 16 17 /* 18 * Pin config fixes 19 */ 20 enum { 21 ALC262_FIXUP_FSC_H270, 22 ALC262_FIXUP_FSC_S7110, 23 ALC262_FIXUP_HP_Z200, 24 ALC262_FIXUP_TYAN, 25 ALC262_FIXUP_LENOVO_3000, 26 ALC262_FIXUP_BENQ, 27 ALC262_FIXUP_BENQ_T31, 28 ALC262_FIXUP_INV_DMIC, 29 ALC262_FIXUP_INTEL_BAYLEYBAY, 30 }; 31 32 static const struct hda_fixup alc262_fixups[] = { 33 [ALC262_FIXUP_FSC_H270] = { 34 .type = HDA_FIXUP_PINS, 35 .v.pins = (const struct hda_pintbl[]) { 36 { 0x14, 0x99130110 }, /* speaker */ 37 { 0x15, 0x0221142f }, /* front HP */ 38 { 0x1b, 0x0121141f }, /* rear HP */ 39 { } 40 } 41 }, 42 [ALC262_FIXUP_FSC_S7110] = { 43 .type = HDA_FIXUP_PINS, 44 .v.pins = (const struct hda_pintbl[]) { 45 { 0x15, 0x90170110 }, /* speaker */ 46 { } 47 }, 48 .chained = true, 49 .chain_id = ALC262_FIXUP_BENQ, 50 }, 51 [ALC262_FIXUP_HP_Z200] = { 52 .type = HDA_FIXUP_PINS, 53 .v.pins = (const struct hda_pintbl[]) { 54 { 0x16, 0x99130120 }, /* internal speaker */ 55 { } 56 } 57 }, 58 [ALC262_FIXUP_TYAN] = { 59 .type = HDA_FIXUP_PINS, 60 .v.pins = (const struct hda_pintbl[]) { 61 { 0x14, 0x1993e1f0 }, /* int AUX */ 62 { } 63 } 64 }, 65 [ALC262_FIXUP_LENOVO_3000] = { 66 .type = HDA_FIXUP_PINCTLS, 67 .v.pins = (const struct hda_pintbl[]) { 68 { 0x19, PIN_VREF50 }, 69 {} 70 }, 71 .chained = true, 72 .chain_id = ALC262_FIXUP_BENQ, 73 }, 74 [ALC262_FIXUP_BENQ] = { 75 .type = HDA_FIXUP_VERBS, 76 .v.verbs = (const struct hda_verb[]) { 77 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, 78 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, 79 {} 80 } 81 }, 82 [ALC262_FIXUP_BENQ_T31] = { 83 .type = HDA_FIXUP_VERBS, 84 .v.verbs = (const struct hda_verb[]) { 85 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, 86 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, 87 {} 88 } 89 }, 90 [ALC262_FIXUP_INV_DMIC] = { 91 .type = HDA_FIXUP_FUNC, 92 .v.func = alc_fixup_inv_dmic, 93 }, 94 [ALC262_FIXUP_INTEL_BAYLEYBAY] = { 95 .type = HDA_FIXUP_FUNC, 96 .v.func = alc_fixup_no_depop_delay, 97 }, 98 }; 99 100 static const struct hda_quirk alc262_fixup_tbl[] = { 101 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200), 102 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110), 103 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), 104 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), 105 SND_PCI_QUIRK(0x1734, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270), 106 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), 107 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), 108 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), 109 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31), 110 SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY), 111 {} 112 }; 113 114 static const struct hda_model_fixup alc262_fixup_models[] = { 115 {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, 116 {.id = ALC262_FIXUP_FSC_H270, .name = "fsc-h270"}, 117 {.id = ALC262_FIXUP_FSC_S7110, .name = "fsc-s7110"}, 118 {.id = ALC262_FIXUP_HP_Z200, .name = "hp-z200"}, 119 {.id = ALC262_FIXUP_TYAN, .name = "tyan"}, 120 {.id = ALC262_FIXUP_LENOVO_3000, .name = "lenovo-3000"}, 121 {.id = ALC262_FIXUP_BENQ, .name = "benq"}, 122 {.id = ALC262_FIXUP_BENQ_T31, .name = "benq-t31"}, 123 {.id = ALC262_FIXUP_INTEL_BAYLEYBAY, .name = "bayleybay"}, 124 {} 125 }; 126 127 /* 128 */ 129 static int alc262_probe(struct hda_codec *codec, const struct hda_device_id *id) 130 { 131 struct alc_spec *spec; 132 int err; 133 134 err = alc_alloc_spec(codec, 0x0b); 135 if (err < 0) 136 return err; 137 138 spec = codec->spec; 139 spec->gen.shared_mic_vref_pin = 0x18; 140 141 spec->shutup = alc_eapd_shutup; 142 143 #if 0 144 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is 145 * under-run 146 */ 147 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80); 148 #endif 149 alc_fix_pll_init(codec, 0x20, 0x0a, 10); 150 151 alc_pre_init(codec); 152 153 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, 154 alc262_fixups); 155 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 156 157 alc_auto_parse_customize_define(codec); 158 159 if (has_cdefine_beep(codec)) 160 spec->gen.beep_nid = 0x01; 161 162 /* automatic parse from the BIOS config */ 163 err = alc262_parse_auto_config(codec); 164 if (err < 0) 165 goto error; 166 167 if (!spec->gen.no_analog && spec->gen.beep_nid) { 168 err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); 169 if (err < 0) 170 goto error; 171 } 172 173 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 174 175 return 0; 176 177 error: 178 snd_hda_gen_remove(codec); 179 return err; 180 } 181 182 static const struct hda_codec_ops alc262_codec_ops = { 183 .probe = alc262_probe, 184 .remove = snd_hda_gen_remove, 185 .build_controls = alc_build_controls, 186 .build_pcms = snd_hda_gen_build_pcms, 187 .init = alc_init, 188 .unsol_event = snd_hda_jack_unsol_event, 189 .resume = alc_resume, 190 .suspend = alc_suspend, 191 .check_power_status = snd_hda_gen_check_power_status, 192 .stream_pm = snd_hda_gen_stream_pm, 193 }; 194 195 /* 196 * driver entries 197 */ 198 static const struct hda_device_id snd_hda_id_alc262[] = { 199 HDA_CODEC_ID(0x10ec0262, "ALC262"), 200 {} /* terminator */ 201 }; 202 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc262); 203 204 MODULE_LICENSE("GPL"); 205 MODULE_DESCRIPTION("Realtek ALC262 HD-audio codec"); 206 MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK"); 207 208 static struct hda_codec_driver alc262_driver = { 209 .id = snd_hda_id_alc262, 210 .ops = &alc262_codec_ops, 211 }; 212 213 module_hda_codec_driver(alc262_driver); 214