Re: [PATCH] ALSA: hda/realtek: Enable PC beep passthrough for HP EliteBook 855 G7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Wed, 01 Jan 2025 14:16:05 +0100,
Maciej S. Szmigiero wrote:
> 
> PC speaker works well on this platform in BIOS and in Linux until sound
> card drivers are loaded. Then it stops working.
> 
> There seems to be a beep generator node at 0x1a in this CODEC
> (ALC269_TYPE_ALC215) but it seems to be only connected to capture mixers
> at nodes 0x22 and 0x23.
> If I unmute the mixer input for 0x1a at node 0x23 and start recording
> from its "ALC285 Analog" capture device I can clearly hear beeps in that
> recording.
> 
> So the beep generator is indeed working properly, however I wasn't able to
> figure out any way to connect it to speakers.
> 
> However, the bits in the "Passthrough Control" register (0x36) seems to
> work at least partially: by zeroing "B" and "h" and setting "S" I can at
> least make the PIT PC speaker output appear either in this laptop speakers
> or headphones (depending on whether they are connected or not).
> 
> 
> There are some caveats, however:
> * If the CODEC gets runtime-suspended the beeps stop so it needs HDA beep
> device for keeping it awake during beeping.
> 
> * If the beep generator node is generating any beep the PC beep passthrough
> seems to be temporarily inhibited, so the HDA beep device has to be
> prevented from using the actual beep generator node - but the beep device
> is still necessary due to the previous point.
> 
> * In contrast with other platforms here beep amplification has to be
> disabled otherwise the beeps output are WAY louder than they were on pure
> BIOS setup.
> 
> 
> Unless someone (from Realtek probably) knows how to make the beep generator
> node output appear in speakers / headphones using PC beep passthrough seems
> to be the only way to make PC speaker beeping actually work on this
> platform.
> 
> Signed-off-by: Maciej S. Szmigiero <mail@xxxxxxxxxxxxxxxxxxxxx>

It's a change that does handle things completely differently from the
current implementation, and it uses undocumented Realtek-specific
things, so I'd rather want comments from Realtek.

Kailang, is this feature correct and can be used safely?


thanks,

Takashi

> ---
>  include/sound/hda_codec.h     |  1 +
>  sound/pci/hda/hda_beep.c      | 15 +++++++++------
>  sound/pci/hda/patch_realtek.c | 33 ++++++++++++++++++++++++++++++++-
>  3 files changed, 42 insertions(+), 7 deletions(-)
> 
> diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
> index 575e55aa08ca..c1fe6290d04d 100644
> --- a/include/sound/hda_codec.h
> +++ b/include/sound/hda_codec.h
> @@ -195,6 +195,7 @@ struct hda_codec {
>  	/* beep device */
>  	struct hda_beep *beep;
>  	unsigned int beep_mode;
> +	bool beep_just_power_on;
>  
>  	/* widget capabilities cache */
>  	u32 *wcaps;
> diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
> index e51d47572557..13a7d92e8d8d 100644
> --- a/sound/pci/hda/hda_beep.c
> +++ b/sound/pci/hda/hda_beep.c
> @@ -31,8 +31,9 @@ static void generate_tone(struct hda_beep *beep, int tone)
>  			beep->power_hook(beep, true);
>  		beep->playing = 1;
>  	}
> -	snd_hda_codec_write(codec, beep->nid, 0,
> -			    AC_VERB_SET_BEEP_CONTROL, tone);
> +	if (!codec->beep_just_power_on)
> +		snd_hda_codec_write(codec, beep->nid, 0,
> +				    AC_VERB_SET_BEEP_CONTROL, tone);
>  	if (!tone && beep->playing) {
>  		beep->playing = 0;
>  		if (beep->power_hook)
> @@ -212,10 +213,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
>  	struct hda_beep *beep;
>  	int err;
>  
> -	if (!snd_hda_get_bool_hint(codec, "beep"))
> -		return 0; /* disabled explicitly by hints */
> -	if (codec->beep_mode == HDA_BEEP_MODE_OFF)
> -		return 0; /* disabled by module option */
> +	if (!codec->beep_just_power_on) {
> +		if (!snd_hda_get_bool_hint(codec, "beep"))
> +			return 0; /* disabled explicitly by hints */
> +		if (codec->beep_mode == HDA_BEEP_MODE_OFF)
> +			return 0; /* disabled by module option */
> +	}
>  
>  	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
>  	if (beep == NULL)
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 61ba5dc35b8b..90b51aa2322d 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -28,6 +28,7 @@
>  #include <sound/hda_codec.h>
>  #include "hda_local.h"
>  #include "hda_auto_parser.h"
> +#include "hda_beep.h"
>  #include "hda_jack.h"
>  #include "hda_generic.h"
>  #include "hda_component.h"
> @@ -6924,6 +6925,29 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
>  	}
>  }
>  
> +static void alc285_fixup_hp_beep(struct hda_codec *codec,
> +				 const struct hda_fixup *fix, int action)
> +{
> +	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
> +		codec->beep_just_power_on = true;
> +	} else  if (action == HDA_FIXUP_ACT_INIT) {
> +#ifdef CONFIG_SND_HDA_INPUT_BEEP
> +		/*
> +		 * Just enable loopback to internal speaker and headphone jack.
> +		 * Disable amplification to get about the same beep volume as
> +		 * was on pure BIOS setup before loading the driver.
> +		 */
> +		alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13));
> +
> +		snd_hda_enable_beep_device(codec, 1);
> +
> +#if !IS_ENABLED(CONFIG_INPUT_PCSPKR)
> +		codec_warn(codec, "enable CONFIG_INPUT_PCSPKR to get PC beeps\n")
> +#endif
> +#endif
> +	}
> +}
> +
>  /* for hda_fixup_thinkpad_acpi() */
>  #include "thinkpad_helper.c"
>  
> @@ -7683,6 +7707,7 @@ enum {
>  	ALC285_FIXUP_HP_GPIO_LED,
>  	ALC285_FIXUP_HP_MUTE_LED,
>  	ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
> +	ALC285_FIXUP_HP_BEEP_MICMUTE_LED,
>  	ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
>  	ALC236_FIXUP_HP_GPIO_LED,
>  	ALC236_FIXUP_HP_MUTE_LED,
> @@ -9271,6 +9296,12 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.type = HDA_FIXUP_FUNC,
>  		.v.func = alc285_fixup_hp_spectre_x360_mute_led,
>  	},
> +	[ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = {
> +		.type = HDA_FIXUP_FUNC,
> +		.v.func = alc285_fixup_hp_beep,
> +		.chained = true,
> +		.chain_id = ALC285_FIXUP_HP_MUTE_LED,
> +	},
>  	[ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
>  	    .type = HDA_FIXUP_FUNC,
>  	    .v.func = alc236_fixup_hp_mute_led_coefbit2,
> @@ -10348,7 +10379,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
>  	SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
>  	SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
>  	SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
> -	SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
> +	SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED),
>  	SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
>  	SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
>  	SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),




[Index of Archives]     [Pulseaudio]     [Linux Audio Users]     [ALSA Devel]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux