[alsa-devel] [PATCH] hda: add SW_LINEOUT_INSERT support

Takashi Iwai tiwai at suse.de
Fri Oct 17 08:06:21 CEST 2008


At Thu, 16 Oct 2008 22:18:40 -0400,
Matthew Ranostay wrote:
> 
> Add support for detecting line out pin insertion and reporting
> back to userspace with the jack abstraction layer. Line outs
> are reported with the macro defined SW_LINEOUT_INSERT code.
> 
> Signed-off-by: Matthew Ranostay <mranostay at embeddedalley.com>

Thanks for the patch.  Added Dmitry and Mark to Cc for review.

Adding one element should be fine, but I'm wondering whether more and
more pin type would come up in future...

More comments below.

> diff --git a/include/linux/input.h b/include/linux/input.h
> index a5802c9..7323d2f 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -644,6 +644,7 @@ struct input_absinfo {
>  #define SW_RADIO		SW_RFKILL_ALL	/* deprecated */
>  #define SW_MICROPHONE_INSERT	0x04  /* set = inserted */
>  #define SW_DOCK			0x05  /* set = plugged into dock */
> +#define SW_LINEOUT_INSERT	0x06  /* set = inserted */
>  #define SW_MAX			0x0f
>  #define SW_CNT			(SW_MAX+1)
> 
> diff --git a/include/sound/jack.h b/include/sound/jack.h
> index b1b2b8b..7cb25f4 100644
> --- a/include/sound/jack.h
> +++ b/include/sound/jack.h
> @@ -35,6 +35,7 @@ enum snd_jack_types {
>  	SND_JACK_HEADPHONE	= 0x0001,
>  	SND_JACK_MICROPHONE	= 0x0002,
>  	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
> +	SND_JACK_LINEOUT	= 0x0004,
>  };

So, you don't need to judge different line-outs, such as front and
rear?

>  struct snd_jack {
> diff --git a/sound/core/jack.c b/sound/core/jack.c
> index bd2d9e6..4978db1 100644
> --- a/sound/core/jack.c
> +++ b/sound/core/jack.c
> @@ -102,6 +102,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
>  	if (type & SND_JACK_HEADPHONE)
>  		input_set_capability(jack->input_dev, EV_SW,
>  				     SW_HEADPHONE_INSERT);
> +	if (type & SND_JACK_LINEOUT)
> +		input_set_capability(jack->input_dev, EV_SW,
> +				     SW_LINEOUT_INSERT);
>  	if (type & SND_JACK_MICROPHONE)
>  		input_set_capability(jack->input_dev, EV_SW,
>  				     SW_MICROPHONE_INSERT);
> @@ -153,6 +156,9 @@ void snd_jack_report(struct snd_jack *jack, int status)
>  	if (jack->type & SND_JACK_HEADPHONE)
>  		input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
>  				    status & SND_JACK_HEADPHONE);
> +	if (jack->type & SND_JACK_LINEOUT)
> +		input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
> +				    status & SND_JACK_LINEOUT);
>  	if (jack->type & SND_JACK_MICROPHONE)
>  		input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
>  				    status & SND_JACK_MICROPHONE);
> diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
> index d106ea5..1b3cba8 100644
> --- a/sound/pci/hda/patch_sigmatel.c
> +++ b/sound/pci/hda/patch_sigmatel.c
> @@ -36,6 +36,7 @@
>  #include "hda_patch.h"
>  #include "hda_beep.h"
> 
> +#define STAC_LINEOUT_EVENT	0x10
>  #define STAC_PWR_EVENT		0x20
>  #define STAC_HP_EVENT		0x30
>  #define STAC_VREF_EVENT		0x40
> @@ -217,7 +218,8 @@ struct sigmatel_spec {
>  	struct hda_pcm pcm_rec[2];	/* PCM information */
> 
>  	/* jack detection */
> -	struct snd_jack *jack;
> +	struct snd_jack *hp_jack;
> +	struct snd_jack *lineout_jack;
> 
>  	/* dynamic controls and input_mux */
>  	struct auto_pin_cfg autocfg;
> @@ -3635,9 +3637,15 @@ static int stac92xx_init(struct hda_codec *codec)
>  		/* jack detection */
>  		err = snd_jack_new(codec->bus->card,
>  			"Headphone Jack",
> -			SND_JACK_HEADPHONE, &spec->jack);
> +			SND_JACK_HEADPHONE, &spec->hp_jack);
>  		if (err < 0)
>  			return err;
> +		err = snd_jack_new(codec->bus->card,
> +			"Lineout Jack",
> +			SND_JACK_LINEOUT, &spec->lineout_jack);
> +		if (err < 0)
> +			return err;
> +
>  		/* fake event to set up pins */
>  		codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
>  	} else {
> @@ -3661,6 +3669,16 @@ static int stac92xx_init(struct hda_codec *codec)
>  	for (i = 0; i < spec->num_dmics; i++)
>  		stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
>  					AC_PINCTL_IN_EN);
> +	for (i = 0; i < cfg->line_outs; i++) {
> +		int def_conf = snd_hda_codec_read(codec, cfg->line_out_pins[i],
> +					0, AC_VERB_GET_CONFIG_DEFAULT, 0);
> +		def_conf = get_defcfg_connect(def_conf);
> +
> +		if (def_conf && def_conf != AC_JACK_PORT_FIXED)
> +			continue;
> +		enable_pin_detect(codec, cfg->line_out_pins[i],
> +			STAC_LINEOUT_EVENT);
> +	}
>  	for (i = 0; i < spec->num_pwrs; i++)  {
>  		int event = is_nid_hp_pin(cfg, spec->pwr_nids[i])
>  					? STAC_HP_EVENT : STAC_PWR_EVENT;
> @@ -3717,8 +3735,10 @@ static void stac92xx_free(struct hda_codec *codec)
>  	if (! spec)
>  		return;
> 
> -	if (spec->jack)
> -		snd_device_free(codec->bus->card, spec->jack);
> +	if (spec->hp_jack)
> +		snd_device_free(codec->bus->card, spec->hp_jack);
> +	if (spec->lineout_jack)
> +		snd_device_free(codec->bus->card, spec->lineout_jack);

Good that you already caught the recent change ;)

> 
>  	if (spec->bios_pin_configs)
>  		kfree(spec->bios_pin_configs);
> @@ -3804,7 +3824,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
>  			break;
>  		presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
>  	}
> -	snd_jack_report(spec->jack,
> +	snd_jack_report(spec->hp_jack,
>  		presence ? SND_JACK_HEADPHONE : 0);
> 
>  	if (presence) {
> @@ -3840,6 +3860,28 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
>  		stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
>  }
> 
> +static void stac92xx_lineout_detect(struct hda_codec *codec)
> +{
> +	struct sigmatel_spec *spec = codec->spec;
> +	struct auto_pin_cfg *cfg = &spec->autocfg;
> +	int presence, i;
> +
> +	for (i = 0; i < cfg->line_outs; i++) {
> +		int def_conf = snd_hda_codec_read(codec,
> +			cfg->line_out_pins[i], 0,
> +			AC_VERB_GET_CONFIG_DEFAULT, 0);
> +		def_conf = get_defcfg_connect(def_conf);
> +
> +		if (def_conf && def_conf != AC_JACK_PORT_FIXED)
> +			continue;
> +		presence = get_hp_pin_presence(codec,
> +			cfg->line_out_pins[i]);
> +		if (presence)
> +			break;
> +	}
> +	snd_jack_report(spec->lineout_jack, presence ? SND_JACK_LINEOUT : 0);
> +}
> +
>  static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
>  {
>  	struct sigmatel_spec *spec = codec->spec;
> @@ -3868,15 +3910,20 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
>  {
>  	struct sigmatel_spec *spec = codec->spec;
>  	int idx = res >> 26 & 0x0f;
> +	int event = (res >> 26) & 0x70;
> 
> -	switch ((res >> 26) & 0x70) {
> +	switch (event) {
>  	case STAC_HP_EVENT:
>  		stac92xx_hp_detect(codec, res);
>  		/* fallthru */
>  	case STAC_PWR_EVENT:
>  		if (spec->num_pwrs > 0)
>  			stac92xx_pin_sense(codec, idx);
> -		break;
> +		/* fallthru */
> +	case STAC_LINEOUT_EVENT:
> +		if (event == STAC_HP_EVENT)
> +			break;
> +		stac92xx_lineout_detect(codec);

Is here also fallthru?
Then I'd suggest you to rewrite with a simple if, or separate somehow
better.  Too many fallthru in a switch is difficult to follow the code
flow.


thanks,

Takashi


More information about the Alsa-devel mailing list