[alsa-devel] [RFC PATCH] HDA: Generic input jack handling

Takashi Iwai tiwai at suse.de
Fri Oct 7 14:08:37 CEST 2011


At Fri, 07 Oct 2011 13:49:46 +0200,
David Henningsson wrote:
> 
> So, this is what I had in mind for 3.2. Assuming positive feedback from 
> Takashi I'll go ahead and make a real patch out of this, and to clean up 
> the Realtek implementation, as well as probably add this method for more 
> codecs.
> 
> Thoughts:
> 
> 1) The unsol event tags vary wildly between different vendors. How about 
> standardising that as well?

Generalization is good.  But tags aren't always constant.  It'd be
better to assign each tag dynamically like in patch_sigmatel.c.
The reason is that you'd need to know the pin NID from the unsol
event, so the tag has to be unique even for the same purpose.  E.g. if
a machine has two headphones, both are the same type but they should
issue unsol events with different tags.

> 2) If alc_init_jacks would call the new method, that might regress 
> model-based (non auto) parsers. Is that a big deal these days?

I don't think so.  And most of all model-based entries will vanish in
3.3.  In 3.2, already a half of realtek quirks are gone.

> 3) Todo for realtek parser is to clean up all other calls to 
> snd_input_jack_report so that jacks are not reported twice.


thanks,

Takashi

> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> index e9b039c..69390fd 100644
> --- a/sound/pci/hda/hda_codec.c
> +++ b/sound/pci/hda/hda_codec.c
> @@ -5284,6 +5284,142 @@ int snd_hda_input_jack_add(struct hda_codec 
> *codec, hda_nid_t nid, int type,
>   }
>   EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
> 
> +/**
> + * snd_hda_input_auto_jack_add - Add relevant input jacks based on
> + * auto pin configuration.
> + * @param unsol_tags lists of jack types to enable, terminate with
> + * list entry with jack_type set to 0. If unsol_tag is set to 0,
> + * unsol events will not be enabled for that jack type.
> + * @return 0 or error code
> + */
> +int snd_hda_input_auto_jack_add(struct hda_codec *codec,
> +				const struct auto_pin_cfg *cfg,
> +				const struct hda_unsol_jack_tag* unsol_tags)
> +{
> +	for (; unsol_tags->jack_type; unsol_tags++) {
> +		hda_nid_t nid_list_storage[AUTO_CFG_MAX_INS];
> +		const hda_nid_t *nid_list;
> +		int nid_count = 0;
> +		int i;
> +		int input_match = AUTO_PIN_MIC;
> +
> +		switch (unsol_tags->jack_type) {
> +		case SND_JACK_LINEIN:
> +			input_match = AUTO_PIN_LINE_IN;
> +			/* Fall through */
> +		case SND_JACK_MICROPHONE:
> +			for (i = 0; i < cfg->num_inputs; i++) {
> +				if (cfg->inputs[i].type == input_match)
> +					nid_list_storage[nid_count++] = cfg->inputs[i].pin;
> +			}
> +			nid_list = nid_list_storage;
> +			break;
> +		case SND_JACK_HEADPHONE:
> +			if (cfg->line_out_type == AUTO_PIN_HP_OUT) {
> +				nid_list = cfg->line_out_pins;
> +				nid_count = cfg->line_outs;
> +			} else {
> +				nid_list = cfg->hp_pins;
> +				nid_count = cfg->hp_outs;
> +			}
> +			break;
> +		case SND_JACK_LINEOUT:
> +			if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
> +				nid_list = cfg->line_out_pins;
> +				nid_count = cfg->line_outs;
> +			}
> +			break;			
> +		}
> +
> +		for (i = 0; i < nid_count; i++) {
> +			int pin = nid_list[i];
> +			int err;
> +			if (!is_jack_detectable(codec, pin))
> +				continue;
> +
> +			if (unsol_tags->unsol_tag) {
> +				err = snd_hda_codec_write(codec, pin, 0,
> +					AC_VERB_SET_UNSOLICITED_ENABLE,
> +					AC_USRSP_EN | unsol_tags->unsol_tag);
> +				if (err)
> +					return err;
> +			}
> +
> +			err = snd_hda_input_jack_add(codec, pin,
> +					unsol_tags->jack_type, NULL);
> +			if (err)
> +				return err;
> +			snd_hda_input_jack_report(codec, pin);
> +		}
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL_HDA(snd_hda_input_auto_jack_add);
> +
> +void snd_hda_input_jack_report_type(struct hda_codec *codec, int jack_type)
> +{
> +	struct hda_jack_item *jacks = codec->jacks.list;
> +	int i;
> +
> +	if (!jacks)
> +		return;
> +
> +	for (i = 0; i < codec->jacks.used; i++, jacks++)
> +		if (jacks->type == jack_type)
> +			snd_hda_input_jack_report(codec, jacks->nid);
> +}
> +EXPORT_SYMBOL_HDA(snd_hda_input_jack_report_type);
> +
> +
>   void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
>   {
>   	struct hda_jack_item *jacks = codec->jacks.list;
> diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
> index 46c581c..bb59a3f 100644
> --- a/sound/pci/hda/hda_local.h
> +++ b/sound/pci/hda/hda_local.h
> @@ -678,11 +678,21 @@ void snd_print_channel_allocation(int spk_alloc, 
> char *buf, int buflen);
>   /*
>    * Input-jack notification support
>    */
> +
> +struct hda_unsol_jack_tag {
> +	int jack_type; /* SND_JACK_xxx constant */
> +	int unsol_tag; /* event tag */
> +};
> +
>   #ifdef CONFIG_SND_HDA_INPUT_JACK
>   int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int 
> type,
>   			   const char *name);
>   void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);
> +void snd_hda_input_jack_report_type(struct hda_codec *codec, int 
> jack_type);
>   void snd_hda_input_jack_free(struct hda_codec *codec);
> +int snd_hda_input_auto_jack_add(struct hda_codec *codec,
> +				const struct auto_pin_cfg *cfg,
> +				const struct hda_unsol_jack_tag *unsol_tags);
>   #else /* CONFIG_SND_HDA_INPUT_JACK */
>   static inline int snd_hda_input_jack_add(struct hda_codec *codec,
>   					 hda_nid_t nid, int type,
> @@ -694,9 +704,19 @@ static inline void snd_hda_input_jack_report(struct 
> hda_codec *codec,
>   					     hda_nid_t nid)
>   {
>   }
> +static inline void snd_hda_input_jack_report_type(struct hda_codec *codec,
> +						  int jack_type)
> +{
> +}
>   static inline void snd_hda_input_jack_free(struct hda_codec *codec)
>   {
>   }
> +static inline int snd_hda_input_auto_jack_add(struct hda_codec *codec,
> +				const struct auto_pin_cfg *cfg,
> +				const struct hda_unsol_jack_tag *unsol_tags)
> +{
> +	return 0;
> +}
>   #endif /* CONFIG_SND_HDA_INPUT_JACK */
> 
>   #endif /* __SOUND_HDA_LOCAL_H */
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index bf53663..90cdd6c 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -38,6 +38,7 @@
>   #define ALC_DCVOL_EVENT		0x02
>   #define ALC_HP_EVENT		0x04
>   #define ALC_MIC_EVENT		0x08
> +#define ALC_LINEIN_EVENT	0x10
> 
>   /* for GPIO Poll */
>   #define GPIO_MASK	0x03
> @@ -441,11 +442,21 @@ static void alc_fix_pll_init(struct hda_codec 
> *codec, hda_nid_t nid,
>    * Jack-reporting via input-jack layer
>    */
> 
> +static const struct hda_unsol_jack_tag unsol_tags[] = {
> +	{.jack_type = SND_JACK_HEADPHONE, .unsol_tag = ALC_HP_EVENT },
> +	{.jack_type = SND_JACK_LINEOUT, .unsol_tag = ALC_FRONT_EVENT },
> +	{.jack_type = SND_JACK_MICROPHONE, .unsol_tag = ALC_MIC_EVENT },
> +	{.jack_type = SND_JACK_LINEIN, .unsol_tag = ALC_LINEIN_EVENT },
> +	{} /* Zero terminator */
> +};
> +
>   /* initialization of jacks; currently checks only a few known pins */
>   static int alc_init_jacks(struct hda_codec *codec)
>   {
>   #ifdef CONFIG_SND_HDA_INPUT_JACK
>   	struct alc_spec *spec = codec->spec;
> +	snd_hda_input_auto_jack_add(codec, &spec->autocfg, unsol_tags);
> +/*	;
>   	int err;
>   	unsigned int hp_nid = spec->autocfg.hp_pins[0];
>   	unsigned int mic_nid = spec->ext_mic_pin;
> @@ -472,7 +483,7 @@ static int alc_init_jacks(struct hda_codec *codec)
>   		if (err < 0)
>   			return err;
>   		snd_hda_input_jack_report(codec, dock_nid);
> -	}
> +	}*/
>   #endif /* CONFIG_SND_HDA_INPUT_JACK */
>   	return 0;
>   }
> @@ -645,12 +656,18 @@ static void alc_sku_unsol_event(struct hda_codec 
> *codec, unsigned int res)
>   	switch (res) {
>   	case ALC_HP_EVENT:
>   		alc_hp_automute(codec);
> +		snd_hda_input_jack_report_type(codec, SND_JACK_HEADPHONE);
>   		break;
>   	case ALC_FRONT_EVENT:
>   		alc_line_automute(codec);
> +		snd_hda_input_jack_report_type(codec, SND_JACK_LINEOUT);
>   		break;
>   	case ALC_MIC_EVENT:
>   		alc_mic_automute(codec);
> +		snd_hda_input_jack_report_type(codec, SND_JACK_MICROPHONE);
> +		break;
> +	case ALC_LINEIN_EVENT:
> +		snd_hda_input_jack_report_type(codec, SND_JACK_LINEIN);
>   		break;
>   	}
>   }
> 
> -- 
> David Henningsson, Canonical Ltd.
> http://launchpad.net/~diwic
> 


More information about the Alsa-devel mailing list