diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 120 | 
1 files changed, 44 insertions, 76 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 2cb1e08f962..7db8228f1b8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -36,6 +36,7 @@  #include <sound/tlv.h>  #include "hda_codec.h"  #include "hda_local.h" +#include "hda_auto_parser.h"  #include "hda_beep.h"  #include "hda_jack.h" @@ -221,6 +222,7 @@ struct sigmatel_spec {  	unsigned char aloopback_shift;  	/* power management */ +	unsigned int power_map_bits;  	unsigned int num_pwrs;  	const hda_nid_t *pwr_nids;  	const hda_nid_t *dac_list; @@ -314,6 +316,9 @@ struct sigmatel_spec {  	struct hda_vmaster_mute_hook vmaster_mute;  }; +#define AC_VERB_IDT_SET_POWER_MAP	0x7ec +#define AC_VERB_IDT_GET_POWER_MAP	0xfec +  static const hda_nid_t stac9200_adc_nids[1] = {          0x03,  }; @@ -681,8 +686,7 @@ static int stac_vrefout_set(struct hda_codec *codec,  	pinctl &= ~AC_PINCTL_VREFEN;  	pinctl |= (new_vref & AC_PINCTL_VREFEN); -	error = snd_hda_codec_write_cache(codec, nid, 0, -					AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); +	error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl);  	if (error < 0)  		return error; @@ -706,8 +710,7 @@ static unsigned int stac92xx_vref_set(struct hda_codec *codec,  	else  		pincfg |= AC_PINCTL_IN_EN; -	error = snd_hda_codec_write_cache(codec, nid, 0, -					AC_VERB_SET_PIN_WIDGET_CONTROL, pincfg); +	error = snd_hda_set_pin_ctl_cache(codec, nid, pincfg);  	if (error < 0)  		return error;  	else @@ -2505,27 +2508,10 @@ static int stac92xx_build_pcms(struct hda_codec *codec)  	return 0;  } -static unsigned int stac92xx_get_default_vref(struct hda_codec *codec, -					hda_nid_t nid) -{ -	unsigned int pincap = snd_hda_query_pin_caps(codec, nid); -	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; -	if (pincap & AC_PINCAP_VREF_100) -		return AC_PINCTL_VREF_100; -	if (pincap & AC_PINCAP_VREF_80) -		return AC_PINCTL_VREF_80; -	if (pincap & AC_PINCAP_VREF_50) -		return AC_PINCTL_VREF_50; -	if (pincap & AC_PINCAP_VREF_GRD) -		return AC_PINCTL_VREF_GRD; -	return 0; -} -  static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)  { -	snd_hda_codec_write_cache(codec, nid, 0, -				  AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); +	snd_hda_set_pin_ctl_cache(codec, nid, pin_type);  }  #define stac92xx_hp_switch_info		snd_ctl_boolean_mono_info @@ -2594,7 +2580,7 @@ static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,  	hda_nid_t nid = kcontrol->private_value;  	unsigned int vref = stac92xx_vref_get(codec, nid); -	if (vref == stac92xx_get_default_vref(codec, nid)) +	if (vref == snd_hda_get_default_vref(codec, nid))  		ucontrol->value.enumerated.item[0] = 0;  	else if (vref == AC_PINCTL_VREF_GRD)  		ucontrol->value.enumerated.item[0] = 1; @@ -2613,7 +2599,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,  	hda_nid_t nid = kcontrol->private_value;  	if (ucontrol->value.enumerated.item[0] == 0) -		new_vref = stac92xx_get_default_vref(codec, nid); +		new_vref = snd_hda_get_default_vref(codec, nid);  	else if (ucontrol->value.enumerated.item[0] == 1)  		new_vref = AC_PINCTL_VREF_GRD;  	else if (ucontrol->value.enumerated.item[0] == 2) @@ -2679,7 +2665,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_  	else {  		unsigned int pinctl = AC_PINCTL_IN_EN;  		if (io_idx) /* set VREF for mic */ -			pinctl |= stac92xx_get_default_vref(codec, nid); +			pinctl |= snd_hda_get_default_vref(codec, nid);  		stac92xx_auto_set_pinctl(codec, nid, pinctl);  	} @@ -2847,7 +2833,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,  	char name[22];  	if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { -		if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD +		if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD  			&& nid == spec->line_switch)  			control = STAC_CTL_WIDGET_IO_SWITCH;  		else if (snd_hda_query_pin_caps(codec, nid) @@ -4250,13 +4236,6 @@ static void stac_store_hints(struct hda_codec *codec)  	val = snd_hda_get_bool_hint(codec, "eapd_switch");  	if (val >= 0)  		spec->eapd_switch = val; -	get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); -	if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { -		spec->gpio_mask |= spec->gpio_led; -		spec->gpio_dir |= spec->gpio_led; -		if (spec->gpio_led_polarity) -			spec->gpio_data |= spec->gpio_led; -	}  }  static void stac_issue_unsol_events(struct hda_codec *codec, int num_pins, @@ -4354,7 +4333,7 @@ static int stac92xx_init(struct hda_codec *codec)  		unsigned int pinctl, conf;  		if (type == AUTO_PIN_MIC) {  			/* for mic pins, force to initialize */ -			pinctl = stac92xx_get_default_vref(codec, nid); +			pinctl = snd_hda_get_default_vref(codec, nid);  			pinctl |= AC_PINCTL_IN_EN;  			stac92xx_auto_set_pinctl(codec, nid, pinctl);  		} else { @@ -4390,10 +4369,18 @@ static int stac92xx_init(struct hda_codec *codec)  		hda_nid_t nid = spec->pwr_nids[i];  		int pinctl, def_conf; +		def_conf = snd_hda_codec_get_pincfg(codec, nid); +		def_conf = get_defcfg_connect(def_conf); +		if (def_conf == AC_JACK_PORT_NONE) { +			/* power off unused ports */ +			stac_toggle_power_map(codec, nid, 0); +			continue; +		}  		/* power on when no jack detection is available */  		/* or when the VREF is used for controlling LED */  		if (!spec->hp_detect || -		    spec->vref_mute_led_nid == nid) { +		    spec->vref_mute_led_nid == nid || +		    !is_jack_detectable(codec, nid)) {  			stac_toggle_power_map(codec, nid, 1);  			continue;  		} @@ -4411,15 +4398,6 @@ static int stac92xx_init(struct hda_codec *codec)  			stac_toggle_power_map(codec, nid, 1);  			continue;  		} -		def_conf = snd_hda_codec_get_pincfg(codec, nid); -		def_conf = get_defcfg_connect(def_conf); -		/* skip any ports that don't have jacks since presence - 		 * detection is useless */ -		if (def_conf != AC_JACK_PORT_NONE && -		    !is_jack_detectable(codec, nid)) { -			stac_toggle_power_map(codec, nid, 1); -			continue; -		}  		if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {  			stac_issue_unsol_event(codec, nid);  			continue; @@ -4432,6 +4410,12 @@ static int stac92xx_init(struct hda_codec *codec)  	/* sync mute LED */  	snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + +	/* sync the power-map */ +	if (spec->num_pwrs) +		snd_hda_codec_write(codec, codec->afg, 0, +				    AC_VERB_IDT_SET_POWER_MAP, +				    spec->power_map_bits);  	if (spec->dac_list)  		stac92xx_power_down(codec);  	return 0; @@ -4460,8 +4444,7 @@ static void stac92xx_shutup_pins(struct hda_codec *codec)  		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);  		def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);  		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) -			snd_hda_codec_write(codec, pin->nid, 0, -				    AC_VERB_SET_PIN_WIDGET_CONTROL, 0); +			snd_hda_set_pin_ctl(codec, pin->nid, 0);  	}  } @@ -4517,9 +4500,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,  	pin_ctl |= flag;  	if (old_ctl != pin_ctl) -		snd_hda_codec_write_cache(codec, nid, 0, -					  AC_VERB_SET_PIN_WIDGET_CONTROL, -					  pin_ctl); +		snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl);  }  static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, @@ -4528,9 +4509,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,  	unsigned int pin_ctl = snd_hda_codec_read(codec, nid,  			0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);  	if (pin_ctl & flag) -		snd_hda_codec_write_cache(codec, nid, 0, -					  AC_VERB_SET_PIN_WIDGET_CONTROL, -					  pin_ctl & ~flag); +		snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl & ~flag);  }  static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) @@ -4682,14 +4661,18 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,  	idx = 1 << idx; -	val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff; +	val = spec->power_map_bits;  	if (enable)  		val &= ~idx;  	else  		val |= idx;  	/* power down unused output ports */ -	snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); +	if (val != spec->power_map_bits) { +		spec->power_map_bits = val; +		snd_hda_codec_write(codec, codec->afg, 0, +				    AC_VERB_IDT_SET_POWER_MAP, val); +	}  }  static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) @@ -4866,6 +4849,11 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)  	struct sigmatel_spec *spec = codec->spec;  	const struct dmi_device *dev = NULL; +	if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { +		get_int_hint(codec, "gpio_led_polarity", +			     &spec->gpio_led_polarity); +		return 1; +	}  	if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {  		while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,  								NULL, dev))) { @@ -4952,7 +4940,8 @@ static void stac92hd_proc_hook(struct snd_info_buffer *buffer,  {  	if (nid == codec->afg)  		snd_iprintf(buffer, "Power-Map: 0x%02x\n",  -			    snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0)); +			    snd_hda_codec_read(codec, nid, 0, +					       AC_VERB_IDT_GET_POWER_MAP, 0));  }  static void analog_loop_proc_hook(struct snd_info_buffer *buffer, @@ -5009,20 +4998,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)  	return 0;  } -static int stac92xx_pre_resume(struct hda_codec *codec) -{ -	struct sigmatel_spec *spec = codec->spec; - -	/* sync mute LED */ -	if (spec->vref_mute_led_nid) -		stac_vrefout_set(codec, spec->vref_mute_led_nid, -				 spec->vref_led); -	else if (spec->gpio_led) -		stac_gpio_set(codec, spec->gpio_mask, -			      spec->gpio_dir, spec->gpio_data); -	return 0; -} -  static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,  				unsigned int power_state)  { @@ -5046,7 +5021,6 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,  #else  #define stac92xx_suspend	NULL  #define stac92xx_resume		NULL -#define stac92xx_pre_resume	NULL  #define stac92xx_set_power_state NULL  #endif /* CONFIG_PM */ @@ -5592,9 +5566,6 @@ again:  			codec->patch_ops.set_power_state =  					stac92xx_set_power_state;  		} -#ifdef CONFIG_PM -		codec->patch_ops.pre_resume = stac92xx_pre_resume; -#endif  	}  	err = stac92xx_parse_auto_config(codec); @@ -5901,9 +5872,6 @@ again:  			codec->patch_ops.set_power_state =  					stac92xx_set_power_state;  		} -#ifdef CONFIG_PM -		codec->patch_ops.pre_resume = stac92xx_pre_resume; -#endif  	}  	spec->multiout.dac_nids = spec->dac_nids;  |