DAPM PIN switches do not update in alsamixer when changed through UCM profile

Hans de Goede hdegoede at redhat.com
Sun Oct 3 18:32:13 CEST 2021


Hi Takashi,

On 10/3/21 4:46 PM, Takashi Iwai wrote:
> On Sun, 03 Oct 2021 15:12:57 +0200,
> Hans de Goede wrote:
>>
>> Hi All,
>>
>> I notice that DAPM PIN switches, such as e.g. the "Headphone"
>> SOC_DAPM_PIN_SWITCH defined in:
>> sound/soc/intel/boards/cht_bsw_nau8824.c:
>>
>> static const struct snd_kcontrol_new cht_mc_controls[] = {
>>         SOC_DAPM_PIN_SWITCH("Headphone"),
>>         SOC_DAPM_PIN_SWITCH("Headset Mic"),
>>         SOC_DAPM_PIN_SWITCH("Int Mic"),
>>         SOC_DAPM_PIN_SWITCH("Ext Spk"),
>> };
>>
>> Do not get updated to reflect state-changes when the output
>> is switched between e.g. Headphone / "Ext Spk" by
>> pulseaudio/pipewire through the UCM profile mechanism.
>>
>> If I exit alsa-mixer after changing the output and
>> start it again then the control does show the expect
>> value. So it seems that we are failing to send a change
>> event about this somewhere?
> 
> Does the patch below work?

Thank you for the quick response.

This works for the "Speaker" DAPM PIN switch on a rt5640
board:


static const struct snd_kcontrol_new byt_rt5640_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
        SOC_DAPM_PIN_SWITCH("Headset Mic 2"),
        SOC_DAPM_PIN_SWITCH("Internal Mic"),
        SOC_DAPM_PIN_SWITCH("Speaker"),
        SOC_DAPM_PIN_SWITCH("Line Out"),
};

But it does not work for the "Headphone" and "Line Out" switches,
these are actually hooked up to jack-detect, so I guess that the
jack-detection is already flipping them and then when the UCM
profile changes them it is a no-op causing the UCM setting of
the control to not cause an event because it is not a change.

Relevant jack-detect bits from sound/soc/intel/boards/bytcr_rt5640.c:


static struct snd_soc_jack_pin rt5640_pins[] = {
        {
                .pin    = "Headphone",
                .mask   = SND_JACK_HEADPHONE,
        },
        {
                .pin    = "Headset Mic",
                .mask   = SND_JACK_MICROPHONE,
        },
};

static struct snd_soc_jack_pin rt5640_pins2[] = {
        {
                /* The 2nd headset jack uses lineout with an external HP-amp */
                .pin    = "Line Out",
                .mask   = SND_JACK_HEADPHONE,
        },
        {
                .pin    = "Headset Mic 2",
                .mask   = SND_JACK_MICROPHONE,
        },
};


                ret = snd_soc_card_jack_new(card, "Headset",
                                            SND_JACK_HEADSET | SND_JACK_BTN_0,
                                            &priv->jack, rt5640_pins,
                                            ARRAY_SIZE(rt5640_pins));

                ret = snd_soc_card_jack_new(card, "Headset 2",
                                            SND_JACK_HEADSET,
                                            &priv->jack2, rt5640_pins2,
                                            ARRAY_SIZE(rt5640_pins2));

I tried both jacks a HP Elitepad 1000G2 with dock (one on the tablet
and one on the dock).

With your patch the SOC_DAPM_PIN_SWITCH("Speaker") control correctly
updates (which it did not do before). But the "Line Out" (used for
the second headset jack) and the "Headphone" controls do not update.

(exiting alsa-mixer and starting it again does show the "Line Out"
and "Headphone" controls have changed.

Regards,

Hans



> --- a/sound/soc/soc-dapm.c
> +++ b/sound/soc/soc-dapm.c
> @@ -2561,6 +2561,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
>  				const char *pin, int status)
>  {
>  	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
> +	int ret = 0;
>  
>  	dapm_assert_locked(dapm);
>  
> @@ -2573,13 +2574,14 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
>  		dapm_mark_dirty(w, "pin configuration");
>  		dapm_widget_invalidate_input_paths(w);
>  		dapm_widget_invalidate_output_paths(w);
> +		ret = 1;
>  	}
>  
>  	w->connected = status;
>  	if (status == 0)
>  		w->force = 0;
>  
> -	return 0;
> +	return ret;
>  }
>  
>  /**
> @@ -3583,14 +3585,15 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
>  {
>  	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
>  	const char *pin = (const char *)kcontrol->private_value;
> +	int ret;
>  
>  	if (ucontrol->value.integer.value[0])
> -		snd_soc_dapm_enable_pin(&card->dapm, pin);
> +		ret = snd_soc_dapm_enable_pin(&card->dapm, pin);
>  	else
> -		snd_soc_dapm_disable_pin(&card->dapm, pin);
> +		ret = snd_soc_dapm_disable_pin(&card->dapm, pin);
>  
>  	snd_soc_dapm_sync(&card->dapm);
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
>  
> @@ -4023,7 +4026,7 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
>  
>  	rtd->params_select = ucontrol->value.enumerated.item[0];
>  
> -	return 0;
> +	return 1;
>  }
>  
>  static void
> 



More information about the Alsa-devel mailing list