From 27b9bcad2bf77e12c08e36d8d72bd6ce0db46041 Mon Sep 17 00:00:00 2001 From: wangdicheng Date: Wed, 4 Mar 2026 15:02:19 +0800 Subject: [PATCH] ALSA: hda/senary: Add hardware init verbs and fixup framework Port the essential hardware initialization logic from the vendor driver and introduce the standard HDA fixup framework to handle different machine configurations. Key changes: 1. Add hardware init verbs: - Implement `senary_init_verb` to send the vendor-specific initialization sequence required by the SN6186 chip. - Override pin capabilities for Node 0x19 to ensure proper headset microphone support. 2. Introduce fixup framework: - Define a default pin configuration table (`senary_pincfg_default`) to provide a fallback for devices with invalid BIOS configurations. - Establish a quirk table structure for future machine-specific fixes. - Since the standard quirk matching relies on Subsystem IDs, we manually apply the default fixup if `snd_hda_pick_fixup` does not find a specific match. This ensures the chip is correctly initialized during probe and resume, and provides a scalable mechanism for supporting specific hardware quirks. Signed-off-by: wangdicheng Link: https://patch.msgid.link/20260304070219.450083-1-wangdich9700@163.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/senarytech.c | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/sound/hda/codecs/senarytech.c b/sound/hda/codecs/senarytech.c index 6239a25bb8f32..f9a389df3a175 100644 --- a/sound/hda/codecs/senarytech.c +++ b/sound/hda/codecs/senarytech.c @@ -36,6 +36,32 @@ struct senary_spec { unsigned int gpio_mic_led_mask; }; +enum { + SENARY_FIXUP_PINCFG_DEFAULT, +}; + +static const struct hda_pintbl senary_pincfg_default[] = { + { 0x16, 0x02211020 }, /* Headphone */ + { 0x17, 0x40f001f0 }, /* Not used */ + { 0x18, 0x05a1904d }, /* Mic */ + { 0x19, 0x02a1104e }, /* Headset Mic */ + { 0x1a, 0x01819030 }, /* Line-in */ + { 0x1d, 0x01014010 }, /* Line-out */ + {} +}; + +static const struct hda_fixup senary_fixups[] = { + [SENARY_FIXUP_PINCFG_DEFAULT] = { + .type = HDA_FIXUP_PINS, + .v.pins = senary_pincfg_default, + }, +}; + +/* Quirk table for specific machines can be added here */ +static const struct hda_quirk sn6186_fixups[] = { + {} +}; + #ifdef CONFIG_SND_HDA_INPUT_BEEP /* additional beep mixers; private_value will be overwritten */ static const struct snd_kcontrol_new senary_beep_mixer[] = { @@ -93,6 +119,19 @@ static void senary_auto_parse_eapd(struct hda_codec *codec) } } +/* Hardware specific initialization verbs */ +static void senary_init_verb(struct hda_codec *codec) +{ + /* Vendor specific init sequence */ + snd_hda_codec_write(codec, 0x1b, 0x0, 0x05a, 0xaa); + snd_hda_codec_write(codec, 0x1b, 0x0, 0x059, 0x48); + snd_hda_codec_write(codec, 0x1b, 0x0, 0x01b, 0x00); + snd_hda_codec_write(codec, 0x1b, 0x0, 0x01c, 0x00); + + /* Override pin caps for headset mic */ + snd_hda_override_pin_caps(codec, 0x19, 0x2124); +} + static void senary_auto_turn_eapd(struct hda_codec *codec, int num_pins, const hda_nid_t *pins, bool on) { @@ -136,6 +175,7 @@ static int senary_init(struct hda_codec *codec) snd_hda_gen_init(codec); senary_init_gpio_led(codec); + senary_init_verb(codec); if (!spec->dynamic_eapd) senary_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); @@ -181,11 +221,30 @@ static int senary_probe(struct hda_codec *codec, const struct hda_device_id *id) senary_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; - if (!spec->gen.vmaster_mute.hook) - spec->gen.vmaster_mute.hook = senary_auto_vmaster_hook; + /* Setup fixups based on codec vendor ID */ + switch (codec->core.vendor_id) { + case 0x1fa86186: + codec->pin_amp_workaround = 1; + spec->gen.mixer_nid = 0x15; + snd_hda_pick_fixup(codec, NULL, sn6186_fixups, senary_fixups); + + /* If no specific quirk found, apply the default pin configuration */ + if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET) + codec->fixup_id = SENARY_FIXUP_PINCFG_DEFAULT; + break; + default: + snd_hda_pick_fixup(codec, NULL, sn6186_fixups, senary_fixups); + break; + } snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + /* Run hardware init verbs once during probe */ + senary_init_verb(codec); + + if (!spec->gen.vmaster_mute.hook) + spec->gen.vmaster_mute.hook = senary_auto_vmaster_hook; + err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, spec->parse_flags); if (err < 0) -- 2.47.3