[alsa-devel] [PATCH 14/31] HDA patch_via.c: Add Jack detect feature for VT1708.

Takashi Iwai tiwai at suse.de
Mon Oct 5 17:12:43 CEST 2009


At Mon, 5 Oct 2009 22:27:20 +0800,
Li Bo wrote:
> 
> [ALSA] HDA VIA: Add Jack detect feature for VT1708.

Why is it needed?  Isn't the unsolicited event handled properly at
HP plugging?

Also, this implementation doesn't look good.  If I understand
correctly, it invokes a workqueue which re-schedules itself at each
100ms...


Takashi

> Signed-off-by: Lydia Wang <lydiawang at viatech.com.cn>
> 
> Index: sound-2.6/sound/pci/hda/patch_via.c
> ===================================================================
> --- sound-2.6.orig/sound/pci/hda/patch_via.c	2009-10-05 15:10:22.000000000 +0800
> +++ sound-2.6/sound/pci/hda/patch_via.c	2009-10-05 15:10:36.000000000 +0800
> @@ -257,6 +257,11 @@
>  	unsigned int smart51_enabled;
>  	enum VIA_HDA_CODEC codec_type;
> 
> +	/* work to check hp jack state */
> +	struct hda_codec *codec;
> +	struct delayed_work hp_jack_work;
> +	int vt1708_jack_detectect;
> +
>  #ifdef CONFIG_SND_HDA_POWER_SAVE
>  	struct hda_loopback_check loopback;
>  #endif
> @@ -966,6 +971,8 @@
>  	{0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
>  	/* PW9 Output enable */
>  	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
> +	/* power down jack detect function */
> +	{0x1, 0xf81, 0x1},
>  	{ }
>  };
> 
> @@ -1340,6 +1347,10 @@
>  		return;
> 
>  	via_free_kctls(codec);
> +	if (spec->codec_type == VT1708) {
> +		cancel_delayed_work(&spec->hp_jack_work);
> +		flush_scheduled_work();
> +	}
>  	kfree(codec->spec);
>  }
> 
> @@ -1724,6 +1735,52 @@
>  	return;
>  }
> 
> +static int vt1708_jack_detectect_get(struct snd_kcontrol *kcontrol,
> +				     struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct via_spec *spec = codec->spec;
> +
> +	if (spec->codec_type != VT1708)
> +		return 0;
> +	spec->vt1708_jack_detectect =
> +		!((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
> +	ucontrol->value.integer.value[0] = spec->vt1708_jack_detectect;
> +	return 0;
> +}
> +
> +static int vt1708_jack_detectect_put(struct snd_kcontrol *kcontrol,
> +				     struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct via_spec *spec = codec->spec;
> +	int change;
> +
> +	if (spec->codec_type != VT1708)
> +		return 0;
> +	spec->vt1708_jack_detectect = ucontrol->value.integer.value[0];
> +	snd_hda_codec_write(codec, 0x1, 0, 0xf81, !spec->vt1708_jack_detectect);
> +	change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
> +		== !spec->vt1708_jack_detectect;
> +	if (spec->vt1708_jack_detectect) {
> +		mute_aa_path(codec, 1);
> +		notify_aa_path_ctls(codec);
> +	}
> +	return change;
> +}
> +
> +static struct snd_kcontrol_new vt1708_jack_detectect[] = {
> +	{
> +		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
> +		.name = "Jack Detect",
> +		.count = 1,
> +		.info = snd_ctl_boolean_mono_info,
> +		.get = vt1708_jack_detectect_get,
> +		.put = vt1708_jack_detectect_put,
> +	},
> +	{} /* end */
> +};
> +
>  static int vt1708_parse_auto_config(struct hda_codec *codec)
>  {
>  	struct via_spec *spec = codec->spec;
> @@ -1751,6 +1808,10 @@
>  	err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
>  	if (err < 0)
>  		return err;
> +	/* add jack detect on/off control */
> +	err = snd_hda_add_new_ctls(codec, vt1708_jack_detectect);
> +	if (err < 0)
> +		return err;
> 
>  	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
> 
> @@ -1784,6 +1845,24 @@
>  	return 0;
>  }
> 
> +static void update_hp_jack_state(struct work_struct *work)
> +{
> +	struct via_spec *spec = container_of(work, struct via_spec,
> +					     hp_jack_work.work);
> +	static int present = 1;
> +
> +	if (spec->codec_type != VT1708)
> +		return;
> +	/* if jack state toggled */
> +	if (present
> +	    != (snd_hda_codec_read(spec->codec, spec->autocfg.hp_pins[0], 0,
> +				   AC_VERB_GET_PIN_SENSE, 0) >> 31)) {
> +		present ^= 1;
> +		via_hp_automute(spec->codec);
> +	}
> +	schedule_delayed_work(&spec->hp_jack_work, msecs_to_jiffies(100));
> +}
> +
>  static int get_mux_nids(struct hda_codec *codec)
>  {
>  	struct via_spec *spec = codec->spec;
> @@ -1860,7 +1939,9 @@
>  #ifdef CONFIG_SND_HDA_POWER_SAVE
>  	spec->loopback.amplist = vt1708_loopbacks;
>  #endif
> -
> +	spec->codec = codec;
> +	INIT_DELAYED_WORK(&spec->hp_jack_work, update_hp_jack_state);
> +	schedule_delayed_work(&spec->hp_jack_work, msecs_to_jiffies(100));
>  	return 0;
>  }
> 


More information about the Alsa-devel mailing list