Re: [PATCH v3] ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter

From: Takashi Iwai

Date: Sun Mar 15 2026 - 05:27:30 EST


On Sat, 14 Mar 2026 20:34:34 +0100,
Sean Rhodes wrote:
>
> The initial StarFighter quirk fixed the runtime suspend pop by muting
> speakers in the shutup callback before power-down. Further hardware
> validation showed that the speaker path is controlled directly by LINE2
> EAPD on NID 0x1b together with GPIO2 for the external amplifier.
>
> Replace the shutup-delay workaround with explicit sequencing of those
> controls at playback start and stop:
> - assert LINE2 EAPD and drive GPIO2 high on PREPARE
> - deassert LINE2 EAPD and drive GPIO2 low on CLEANUP
>
> This avoids the runtime suspend pop without a sleep, and also fixes pops
> around G3 entry and display-manager start that the original workaround
> did not cover.
>
> Fixes: 1cb3c20688fc ("ALSA: hda/realtek: Fix speaker pop on Star Labs StarFighter")
> Cc: Jaroslav Kysela <perex@xxxxxxxx>
> Cc: Takashi Iwai <tiwai@xxxxxxxx>
> Cc: Stefan Binding <sbinding@xxxxxxxxxxxxxxxxxxxxx>
> Cc: Kailang Yang <kailang@xxxxxxxxxxx>
> Cc: Chris Chiu <chris.chiu@xxxxxxxxxxxxx>
> Cc: Edip Hazuri <edip@xxxxxxxxx>
> Cc: linux-sound@xxxxxxxxxxxxxxx
> Cc: linux-kernel@xxxxxxxxxxxxxxx
> Tested-by: Sean Rhodes <sean@starlabs.systems>
> Signed-off-by: Sean Rhodes <sean@starlabs.systems>

Thanks, it's better than the previous patchset, but...

> ---
> sound/hda/codecs/realtek/alc269.c | 64 ++++++++++++++++++++++---------
> 1 file changed, 45 insertions(+), 19 deletions(-)
>
> diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
> index 4c49f1195e1b..901314a7af51 100644
> --- a/sound/hda/codecs/realtek/alc269.c
> +++ b/sound/hda/codecs/realtek/alc269.c
> @@ -1017,24 +1017,6 @@ static int alc269_resume(struct hda_codec *codec)
> return 0;
> }
>
> -#define STARLABS_STARFIGHTER_SHUTUP_DELAY_MS 30
> -
> -static void starlabs_starfighter_shutup(struct hda_codec *codec)
> -{
> - if (snd_hda_gen_shutup_speakers(codec))
> - msleep(STARLABS_STARFIGHTER_SHUTUP_DELAY_MS);
> -}
> -
> -static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
> - const struct hda_fixup *fix,
> - int action)
> -{
> - struct alc_spec *spec = codec->spec;
> -
> - if (action == HDA_FIXUP_ACT_PRE_PROBE)
> - spec->shutup = starlabs_starfighter_shutup;
> -}
> -
> static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
> const struct hda_fixup *fix, int action)
> {
> @@ -1454,6 +1436,32 @@ static void alc274_hp_envy_pcm_hook(struct hda_pcm_stream *hinfo,
> }
> }
>
> +#define ALC233_STARFIGHTER_SPK_PIN 0x1b
> +#define ALC233_STARFIGHTER_GPIO2 0x04
> +
> +static void alc233_starfighter_update_amp(struct hda_codec *codec, bool on)
> +{
> + snd_hda_codec_write(codec, ALC233_STARFIGHTER_SPK_PIN, 0,
> + AC_VERB_SET_EAPD_BTLENABLE,
> + on ? AC_EAPDBTL_EAPD : 0);
> + alc_update_gpio_data(codec, ALC233_STARFIGHTER_GPIO2, on);
> +}
> +
> +static void alc233_starfighter_pcm_hook(struct hda_pcm_stream *hinfo,
> + struct hda_codec *codec,
> + struct snd_pcm_substream *substream,
> + int action)
> +{
> + switch (action) {
> + case HDA_GEN_PCM_ACT_PREPARE:
> + alc233_starfighter_update_amp(codec, true);
> + break;
> + case HDA_GEN_PCM_ACT_CLEANUP:
> + alc233_starfighter_update_amp(codec, false);
> + break;
> + }
> +}
> +
> static void alc274_fixup_hp_envy_gpio(struct hda_codec *codec,
> const struct hda_fixup *fix,
> int action)
> @@ -1467,6 +1475,24 @@ static void alc274_fixup_hp_envy_gpio(struct hda_codec *codec,
> }
> }
>
> +static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
> + const struct hda_fixup *fix,
> + int action)
> +{
> + struct alc_spec *spec = codec->spec;
> +
> + switch (action) {
> + case HDA_FIXUP_ACT_PRE_PROBE:
> + spec->gpio_mask |= ALC233_STARFIGHTER_GPIO2;
> + spec->gpio_dir |= ALC233_STARFIGHTER_GPIO2;
> + spec->gpio_data &= ~ALC233_STARFIGHTER_GPIO2;
> + break;
> + case HDA_FIXUP_ACT_PROBE:
> + spec->gen.pcm_playback_hook = alc233_starfighter_pcm_hook;
> + break;
> + }
> +}

... it'd be even better not to move the place of the function but
keeps at the same position.

> static void alc_update_coef_led(struct hda_codec *codec,
> struct alc_coef_led *led,
> bool polarity, bool on)
> @@ -4058,7 +4084,6 @@ enum {
> ALC245_FIXUP_CLEVO_NOISY_MIC,
> ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE,
> ALC233_FIXUP_MEDION_MTL_SPK,
> - ALC233_FIXUP_STARLABS_STARFIGHTER,
> ALC294_FIXUP_BASS_SPEAKER_15,
> ALC283_FIXUP_DELL_HP_RESUME,
> ALC294_FIXUP_ASUS_CS35L41_SPI_2,
> @@ -4074,6 +4099,7 @@ enum {
> ALC288_FIXUP_SURFACE_SWAP_DACS,
> ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO,
> ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY,
> + ALC233_FIXUP_STARLABS_STARFIGHTER,
> ALC245_FIXUP_BASS_HP_DAC,
> ALC245_FIXUP_ACER_MICMUTE_LED,

Ditto, there is no need for move the position.

By keeping the positions, we can concentrate only on what's really
changed.

Please resubmit with those corrections.


thanks,

Takashi