diff mbox series

ALSA: hda: generic: Always add LED controls

Message ID 20240104155838.7514-1-mail@bernhard-seibold.de (mailing list archive)
State New, archived
Headers show
Series ALSA: hda: generic: Always add LED controls | expand

Commit Message

Bernhard Seibold Jan. 4, 2024, 3:58 p.m. UTC
LEDs for mute and microphone mute can be added to any system via the
audio-mute and audio-micmute triggers, e.g. via USB HID devices.
Therefore, add the LED controls unconditionally.

Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de>
---
 sound/pci/hda/hda_generic.c | 46 ++++++++++++++++++-------------------
 sound/pci/hda/hda_generic.h |  2 --
 2 files changed, 22 insertions(+), 26 deletions(-)

Comments

Takashi Iwai Jan. 4, 2024, 4:41 p.m. UTC | #1
On Thu, 04 Jan 2024 16:58:38 +0100,
Bernhard Seibold wrote:
> 
> LEDs for mute and microphone mute can be added to any system via the
> audio-mute and audio-micmute triggers, e.g. via USB HID devices.
> Therefore, add the LED controls unconditionally.

Hmm...  Won't your change lead to the sysfs entries always,
i.e. creating sysfs entries even if the device has no LED at all?


Takashi

> 
> Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de>
> ---
>  sound/pci/hda/hda_generic.c | 46 ++++++++++++++++++-------------------
>  sound/pci/hda/hda_generic.h |  2 --
>  2 files changed, 22 insertions(+), 26 deletions(-)
> 
> diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
> index bf685d01259d..e78c0dd17c42 100644
> --- a/sound/pci/hda/hda_generic.c
> +++ b/sound/pci/hda/hda_generic.c
> @@ -3644,8 +3644,7 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
>  		return -ENOMEM;
>  	if (is_switch) {
>  		knew->put = cap_single_sw_put;
> -		if (spec->mic_mute_led)
> -			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
> +		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
>  	}
>  	if (!inv_dmic)
>  		return 0;
> @@ -3663,8 +3662,7 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
>  		return -ENOMEM;
>  	if (is_switch) {
>  		knew->put = cap_single_sw_put;
> -		if (spec->mic_mute_led)
> -			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
> +		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
>  	}
>  	return 0;
>  }
> @@ -3706,8 +3704,7 @@ static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
>  		knew->index = idx;
>  		knew->private_value = sw_ctl;
>  		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
> -		if (spec->mic_mute_led)
> -			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
> +		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
>  	}
>  	return 0;
>  }
> @@ -3979,7 +3976,6 @@ int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
>  	if (spec->vmaster_mute.hook)
>  		codec_err(codec, "vmaster hook already present before cdev!\n");
>  
> -	spec->vmaster_mute_led = 1;
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
> @@ -4002,7 +3998,6 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
>  				     int (*callback)(struct led_classdev *,
>  						     enum led_brightness))
>  {
> -	struct hda_gen_spec *spec = codec->spec;
>  	int err;
>  
>  	if (callback) {
> @@ -4013,7 +4008,6 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
>  		}
>  	}
>  
> -	spec->mic_mute_led = 1;
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
> @@ -4973,8 +4967,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
>  
>  	parse_user_hints(codec);
>  
> -	if (spec->vmaster_mute_led || spec->mic_mute_led)
> -		snd_ctl_led_request();
> +	snd_ctl_led_request();
>  
>  	if (spec->mixer_nid && !spec->mixer_merge_nid)
>  		spec->mixer_merge_nid = spec->mixer_nid;
> @@ -5173,6 +5166,7 @@ static const char * const follower_pfxs[] = {
>  int snd_hda_gen_build_controls(struct hda_codec *codec)
>  {
>  	struct hda_gen_spec *spec = codec->spec;
> +	struct snd_kcontrol *kctl;
>  	int err;
>  
>  	if (spec->kctls.used) {
> @@ -5211,19 +5205,23 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
>  		if (err < 0)
>  			return err;
>  	}
> -	if (!spec->no_analog && !spec->suppress_vmaster &&
> -	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
> -		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
> -					    NULL, follower_pfxs,
> -					    "Playback Switch", true,
> -					    spec->vmaster_mute_led ?
> -						SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
> -					    &spec->vmaster_mute.sw_kctl);
> -		if (err < 0)
> -			return err;
> -		if (spec->vmaster_mute.hook) {
> -			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
> -			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
> +	if (!spec->no_analog && !spec->suppress_vmaster) {
> +
> +		kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Switch");
> +		if (!kctl) {
> +			err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
> +						    NULL, follower_pfxs,
> +						    "Playback Switch", true,
> +						    SNDRV_CTL_ELEM_ACCESS_SPK_LED,
> +						    &spec->vmaster_mute.sw_kctl);
> +			if (err < 0)
> +				return err;
> +			if (spec->vmaster_mute.hook) {
> +				snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
> +				snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
> +			}
> +		} else {
> +			kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_SPK_LED;
>  		}
>  	}
>  
> diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
> index a8eea8367629..13db36528041 100644
> --- a/sound/pci/hda/hda_generic.h
> +++ b/sound/pci/hda/hda_generic.h
> @@ -223,8 +223,6 @@ struct hda_gen_spec {
>  	unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
>  	unsigned int own_eapd_ctl:1; /* set EAPD by own function */
>  	unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
> -	unsigned int vmaster_mute_led:1; /* add SPK-LED flag to vmaster mute switch */
> -	unsigned int mic_mute_led:1; /* add MIC-LED flag to capture mute switch */
>  	unsigned int indep_hp:1; /* independent HP supported */
>  	unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
>  	unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */
> -- 
> 2.43.0
>
Bernhard Seibold Jan. 4, 2024, 7:14 p.m. UTC | #2
On Thu, Jan 04, 2024 at 05:41:48PM +0100, Takashi Iwai wrote:
> On Thu, 04 Jan 2024 16:58:38 +0100,
> Bernhard Seibold wrote:
> > 
> > LEDs for mute and microphone mute can be added to any system via the
> > audio-mute and audio-micmute triggers, e.g. via USB HID devices.
> > Therefore, add the LED controls unconditionally.
> 
> Hmm...  Won't your change lead to the sysfs entries always,
> i.e. creating sysfs entries even if the device has no LED at all?

This patch is not affecting create_mute_led_cdev, that function is still
only called for some special systems via fixups, to create the actual
LED classdevs that are present on there.

What I'm trying to change is to have the led-ctls always available. They
serve as input to the audio-mute and audio-micmute triggers, and these
triggers should work on any system with HD Audio, not just a few.

It would be even better to move the whole functionality into the sound
core so that it works with other drivers as well, but since yesterday was
the first time I even looked at sound code, I wouldn't even know where
to start.

Regard,
Bernhard
Jaroslav Kysela Jan. 4, 2024, 9:46 p.m. UTC | #3
On 04. 01. 24 20:14, Bernhard Seibold wrote:
> On Thu, Jan 04, 2024 at 05:41:48PM +0100, Takashi Iwai wrote:
>> On Thu, 04 Jan 2024 16:58:38 +0100,
>> Bernhard Seibold wrote:
>>>
>>> LEDs for mute and microphone mute can be added to any system via the
>>> audio-mute and audio-micmute triggers, e.g. via USB HID devices.
>>> Therefore, add the LED controls unconditionally.
>>
>> Hmm...  Won't your change lead to the sysfs entries always,
>> i.e. creating sysfs entries even if the device has no LED at all?
> 
> This patch is not affecting create_mute_led_cdev, that function is still
> only called for some special systems via fixups, to create the actual
> LED classdevs that are present on there.
> 
> What I'm trying to change is to have the led-ctls always available. They
> serve as input to the audio-mute and audio-micmute triggers, and these
> triggers should work on any system with HD Audio, not just a few.
> 
> It would be even better to move the whole functionality into the sound
> core so that it works with other drivers as well, but since yesterday was
> the first time I even looked at sound code, I wouldn't even know where
> to start.

You can attach controls using sysfs for special use cases. If the system has 
audio LED driver controlled in other code, the HDA driver should be notified 
somehow to create triggers, otherwise the default (current) functionality is 
fine in my eyes.

					Jaroslav
Bernhard Seibold Jan. 4, 2024, 11:41 p.m. UTC | #4
On Thu, Jan 04, 2024 at 10:46:04PM +0100, Jaroslav Kysela wrote:
> On 04. 01. 24 20:14, Bernhard Seibold wrote:
> > On Thu, Jan 04, 2024 at 05:41:48PM +0100, Takashi Iwai wrote:
> > > On Thu, 04 Jan 2024 16:58:38 +0100,
> > > Bernhard Seibold wrote:
> > > > 
> > > > LEDs for mute and microphone mute can be added to any system via the
> > > > audio-mute and audio-micmute triggers, e.g. via USB HID devices.
> > > > Therefore, add the LED controls unconditionally.
> > > 
> > > Hmm...  Won't your change lead to the sysfs entries always,
> > > i.e. creating sysfs entries even if the device has no LED at all?
> > 
> > This patch is not affecting create_mute_led_cdev, that function is still
> > only called for some special systems via fixups, to create the actual
> > LED classdevs that are present on there.
> > 
> > What I'm trying to change is to have the led-ctls always available. They
> > serve as input to the audio-mute and audio-micmute triggers, and these
> > triggers should work on any system with HD Audio, not just a few.
> > 
> > It would be even better to move the whole functionality into the sound
> > core so that it works with other drivers as well, but since yesterday was
> > the first time I even looked at sound code, I wouldn't even know where
> > to start.
> 
> You can attach controls using sysfs for special use cases. If the system has
> audio LED driver controlled in other code, the HDA driver should be notified
> somehow to create triggers, otherwise the default (current) functionality is
> fine in my eyes.

I've got a USB keyboard that has LEDs for mute and for microphone mute,
and these currently do not work as expected. I'm not sure how special
that use-case is, but I don't think expecting users to manually fiddle
around in sysfs to get their keyboard LEDs working is a good solution.

Regards,
Bernhard
Jaroslav Kysela Jan. 5, 2024, 9:27 a.m. UTC | #5
On 05. 01. 24 0:41, Bernhard Seibold wrote:
> On Thu, Jan 04, 2024 at 10:46:04PM +0100, Jaroslav Kysela wrote:
>> On 04. 01. 24 20:14, Bernhard Seibold wrote:
>>> On Thu, Jan 04, 2024 at 05:41:48PM +0100, Takashi Iwai wrote:
>>>> On Thu, 04 Jan 2024 16:58:38 +0100,
>>>> Bernhard Seibold wrote:
>>>>>
>>>>> LEDs for mute and microphone mute can be added to any system via the
>>>>> audio-mute and audio-micmute triggers, e.g. via USB HID devices.
>>>>> Therefore, add the LED controls unconditionally.
>>>>
>>>> Hmm...  Won't your change lead to the sysfs entries always,
>>>> i.e. creating sysfs entries even if the device has no LED at all?
>>>
>>> This patch is not affecting create_mute_led_cdev, that function is still
>>> only called for some special systems via fixups, to create the actual
>>> LED classdevs that are present on there.
>>>
>>> What I'm trying to change is to have the led-ctls always available. They
>>> serve as input to the audio-mute and audio-micmute triggers, and these
>>> triggers should work on any system with HD Audio, not just a few.
>>>
>>> It would be even better to move the whole functionality into the sound
>>> core so that it works with other drivers as well, but since yesterday was
>>> the first time I even looked at sound code, I wouldn't even know where
>>> to start.
>>
>> You can attach controls using sysfs for special use cases. If the system has
>> audio LED driver controlled in other code, the HDA driver should be notified
>> somehow to create triggers, otherwise the default (current) functionality is
>> fine in my eyes.
> 
> I've got a USB keyboard that has LEDs for mute and for microphone mute,
> and these currently do not work as expected. I'm not sure how special
> that use-case is, but I don't think expecting users to manually fiddle
> around in sysfs to get their keyboard LEDs working is a good solution.

I see your point (and tracked your name to hid-lenovo.c which creates 
mute/micmute LED drivers for Lenovo keyboards). The question is, if the audio 
triggers should be enabled blindly (all time) or when a LED driver exists and 
is active (runtime). In later case, this can be covered using new udev rules. 
Obviously, no manual configuration from users is expected.

						Jaroslav
Bernhard Seibold Jan. 5, 2024, 1:46 p.m. UTC | #6
On Fri, Jan 05, 2024 at 10:27:52AM +0100, Jaroslav Kysela wrote:
> On 05. 01. 24 0:41, Bernhard Seibold wrote:
> > On Thu, Jan 04, 2024 at 10:46:04PM +0100, Jaroslav Kysela wrote:
> > > You can attach controls using sysfs for special use cases. If the system has
> > > audio LED driver controlled in other code, the HDA driver should be notified
> > > somehow to create triggers, otherwise the default (current) functionality is
> > > fine in my eyes.
> > 
> > I've got a USB keyboard that has LEDs for mute and for microphone mute,
> > and these currently do not work as expected. I'm not sure how special
> > that use-case is, but I don't think expecting users to manually fiddle
> > around in sysfs to get their keyboard LEDs working is a good solution.
> 
> I see your point (and tracked your name to hid-lenovo.c which creates
> mute/micmute LED drivers for Lenovo keyboards). The question is, if the
> audio triggers should be enabled blindly (all time) or when a LED driver
> exists and is active (runtime). In later case, this can be covered using new
> udev rules. Obviously, no manual configuration from users is expected.

That would require a rule for every keyboard or other HID device with a
mute or micmute LED. I don't think this is a good idea when it could
just work out of the box.

The HID specification defines "usages" for these LEDs, so any HID device
can contain one, and this works also without device-specific drivers.

For "mute", an LED classdev is already being created by the input-leds
module. The default trigger is not yet set correctly, but I have a patch
for that. Support for "micmute" is still missing, but I'm working on
that as well.
diff mbox series

Patch

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index bf685d01259d..e78c0dd17c42 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3644,8 +3644,7 @@  static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
 		return -ENOMEM;
 	if (is_switch) {
 		knew->put = cap_single_sw_put;
-		if (spec->mic_mute_led)
-			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
+		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
 	}
 	if (!inv_dmic)
 		return 0;
@@ -3663,8 +3662,7 @@  static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
 		return -ENOMEM;
 	if (is_switch) {
 		knew->put = cap_single_sw_put;
-		if (spec->mic_mute_led)
-			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
+		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
 	}
 	return 0;
 }
@@ -3706,8 +3704,7 @@  static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
 		knew->index = idx;
 		knew->private_value = sw_ctl;
 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
-		if (spec->mic_mute_led)
-			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
+		knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
 	}
 	return 0;
 }
@@ -3979,7 +3976,6 @@  int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
 	if (spec->vmaster_mute.hook)
 		codec_err(codec, "vmaster hook already present before cdev!\n");
 
-	spec->vmaster_mute_led = 1;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
@@ -4002,7 +3998,6 @@  int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 				     int (*callback)(struct led_classdev *,
 						     enum led_brightness))
 {
-	struct hda_gen_spec *spec = codec->spec;
 	int err;
 
 	if (callback) {
@@ -4013,7 +4008,6 @@  int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 		}
 	}
 
-	spec->mic_mute_led = 1;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
@@ -4973,8 +4967,7 @@  int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 
 	parse_user_hints(codec);
 
-	if (spec->vmaster_mute_led || spec->mic_mute_led)
-		snd_ctl_led_request();
+	snd_ctl_led_request();
 
 	if (spec->mixer_nid && !spec->mixer_merge_nid)
 		spec->mixer_merge_nid = spec->mixer_nid;
@@ -5173,6 +5166,7 @@  static const char * const follower_pfxs[] = {
 int snd_hda_gen_build_controls(struct hda_codec *codec)
 {
 	struct hda_gen_spec *spec = codec->spec;
+	struct snd_kcontrol *kctl;
 	int err;
 
 	if (spec->kctls.used) {
@@ -5211,19 +5205,23 @@  int snd_hda_gen_build_controls(struct hda_codec *codec)
 		if (err < 0)
 			return err;
 	}
-	if (!spec->no_analog && !spec->suppress_vmaster &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
-					    NULL, follower_pfxs,
-					    "Playback Switch", true,
-					    spec->vmaster_mute_led ?
-						SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
-					    &spec->vmaster_mute.sw_kctl);
-		if (err < 0)
-			return err;
-		if (spec->vmaster_mute.hook) {
-			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
-			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+	if (!spec->no_analog && !spec->suppress_vmaster) {
+
+		kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Switch");
+		if (!kctl) {
+			err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+						    NULL, follower_pfxs,
+						    "Playback Switch", true,
+						    SNDRV_CTL_ELEM_ACCESS_SPK_LED,
+						    &spec->vmaster_mute.sw_kctl);
+			if (err < 0)
+				return err;
+			if (spec->vmaster_mute.hook) {
+				snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
+				snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+			}
+		} else {
+			kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_SPK_LED;
 		}
 	}
 
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index a8eea8367629..13db36528041 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -223,8 +223,6 @@  struct hda_gen_spec {
 	unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
 	unsigned int own_eapd_ctl:1; /* set EAPD by own function */
 	unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
-	unsigned int vmaster_mute_led:1; /* add SPK-LED flag to vmaster mute switch */
-	unsigned int mic_mute_led:1; /* add MIC-LED flag to capture mute switch */
 	unsigned int indep_hp:1; /* independent HP supported */
 	unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
 	unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */