diff options
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
| -rw-r--r-- | sound/pci/hda/patch_analog.c | 117 | 
1 files changed, 111 insertions, 6 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 69a941c7b15..e6d1bdff1b6 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -174,6 +174,7 @@ static struct snd_kcontrol_new ad_beep_mixer[] = {  static int ad198x_build_controls(struct hda_codec *codec)  {  	struct ad198x_spec *spec = codec->spec; +	struct snd_kcontrol *kctl;  	unsigned int i;  	int err; @@ -208,9 +209,7 @@ static int ad198x_build_controls(struct hda_codec *codec)  			if (!kctl)  				return -ENOMEM;  			kctl->private_value = spec->beep_amp; -			err = snd_hda_ctl_add(codec, -						get_amp_nid_(spec->beep_amp), -						kctl); +			err = snd_hda_ctl_add(codec, 0, kctl);  			if (err < 0)  				return err;  		} @@ -239,6 +238,27 @@ static int ad198x_build_controls(struct hda_codec *codec)  	}  	ad198x_free_kctls(codec); /* no longer needed */ + +	/* assign Capture Source enums to NID */ +	kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); +	if (!kctl) +		kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); +	for (i = 0; kctl && i < kctl->count; i++) { +		err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]); +		if (err < 0) +			return err; +	} + +	/* assign IEC958 enums to NID */ +	kctl = snd_hda_find_mixer_ctl(codec, +			SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source"); +	if (kctl) { +		err = snd_hda_add_nid(codec, kctl, 0, +				      spec->multiout.dig_out_nid); +		if (err < 0) +			return err; +	} +  	return 0;  } @@ -421,6 +441,11 @@ static int ad198x_build_pcms(struct hda_codec *codec)  	return 0;  } +static inline void ad198x_shutup(struct hda_codec *codec) +{ +	snd_hda_shutup_pins(codec); +} +  static void ad198x_free_kctls(struct hda_codec *codec)  {  	struct ad198x_spec *spec = codec->spec; @@ -434,6 +459,46 @@ static void ad198x_free_kctls(struct hda_codec *codec)  	snd_array_free(&spec->kctls);  } +static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, +				hda_nid_t hp) +{ +	struct ad198x_spec *spec = codec->spec; +	snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, +			    !spec->inv_eapd ? 0x00 : 0x02); +	snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, +			    !spec->inv_eapd ? 0x00 : 0x02); +} + +static void ad198x_power_eapd(struct hda_codec *codec) +{ +	/* We currently only handle front, HP */ +	switch (codec->vendor_id) { +	case 0x11d41882: +	case 0x11d4882a: +	case 0x11d41884: +	case 0x11d41984: +	case 0x11d41883: +	case 0x11d4184a: +	case 0x11d4194a: +	case 0x11d4194b: +		ad198x_power_eapd_write(codec, 0x12, 0x11); +		break; +	case 0x11d41981: +	case 0x11d41983: +		ad198x_power_eapd_write(codec, 0x05, 0x06); +		break; +	case 0x11d41986: +		ad198x_power_eapd_write(codec, 0x1b, 0x1a); +		break; +	case 0x11d41988: +	case 0x11d4198b: +	case 0x11d4989a: +	case 0x11d4989b: +		ad198x_power_eapd_write(codec, 0x29, 0x22); +		break; +	} +} +  static void ad198x_free(struct hda_codec *codec)  {  	struct ad198x_spec *spec = codec->spec; @@ -441,11 +506,29 @@ static void ad198x_free(struct hda_codec *codec)  	if (!spec)  		return; +	ad198x_shutup(codec);  	ad198x_free_kctls(codec);  	kfree(spec);  	snd_hda_detach_beep_device(codec);  } +#ifdef SND_HDA_NEEDS_RESUME +static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) +{ +	ad198x_shutup(codec); +	ad198x_power_eapd(codec); +	return 0; +} + +static int ad198x_resume(struct hda_codec *codec) +{ +	ad198x_init(codec); +	snd_hda_codec_resume_amp(codec); +	snd_hda_codec_resume_cache(codec); +	return 0; +} +#endif +  static struct hda_codec_ops ad198x_patch_ops = {  	.build_controls = ad198x_build_controls,  	.build_pcms = ad198x_build_pcms, @@ -454,6 +537,11 @@ static struct hda_codec_ops ad198x_patch_ops = {  #ifdef CONFIG_SND_HDA_POWER_SAVE  	.check_power_status = ad198x_check_power_status,  #endif +#ifdef SND_HDA_NEEDS_RESUME +	.suspend = ad198x_suspend, +	.resume = ad198x_resume, +#endif +	.reboot_notify = ad198x_shutup,  }; @@ -701,6 +789,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "External Amplifier", +		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,  		.info = ad198x_eapd_info,  		.get = ad198x_eapd_get,  		.put = ad198x_eapd_put, @@ -808,6 +897,7 @@ static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "Master Playback Switch", +		.subdevice = HDA_SUBDEV_AMP_FLAG,  		.info = snd_hda_mixer_amp_switch_info,  		.get = snd_hda_mixer_amp_switch_get,  		.put = ad1986a_hp_master_sw_put, @@ -1008,7 +1098,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {  	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),  	SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),  	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), -	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), +	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),  	SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),  	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),  	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), @@ -1612,6 +1702,7 @@ static struct snd_kcontrol_new ad1981_hp_mixers[] = {  	HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, +		.subdevice = HDA_SUBDEV_NID_FLAG | 0x05,  		.name = "Master Playback Switch",  		.info = ad198x_eapd_info,  		.get = ad198x_eapd_get, @@ -2136,6 +2227,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "External Amplifier", +		.subdevice = HDA_SUBDEV_NID_FLAG | 0x12,  		.info = ad198x_eapd_info,  		.get = ad198x_eapd_get,  		.put = ad198x_eapd_put, @@ -2257,6 +2349,7 @@ static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "IEC958 Playback Source", +		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,  		.info = ad1988_spdif_playback_source_info,  		.get = ad1988_spdif_playback_source_get,  		.put = ad1988_spdif_playback_source_put, @@ -2372,6 +2465,12 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {  	{ }  }; +static struct hda_verb ad1988_spdif_in_init_verbs[] = { +	/* unmute SPDIF input pin */ +	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, +	{ } +}; +  /* AD1989 has no ADC -> SPDIF route */  static struct hda_verb ad1989_spdif_init_verbs[] = {  	/* SPDIF-1 out pin */ @@ -2589,7 +2688,7 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,  	if (! knew->name)  		return -ENOMEM;  	if (get_amp_nid_(val)) -		knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); +		knew->subdevice = HDA_SUBDEV_AMP_FLAG;  	knew->private_value = val;  	return 0;  } @@ -3107,8 +3206,11 @@ static int patch_ad1988(struct hda_codec *codec)  				ad1988_spdif_init_verbs;  		}  	} -	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) +	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {  		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; +		spec->init_verbs[spec->num_init_verbs++] = +			ad1988_spdif_in_init_verbs; +	}  	codec->patch_ops = ad198x_patch_ops;  	switch (board_config) { @@ -3747,6 +3849,7 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "Master Playback Switch", +		.subdevice = HDA_SUBDEV_AMP_FLAG,  		.info = snd_hda_mixer_amp_switch_info,  		.get = snd_hda_mixer_amp_switch_get,  		.put = ad1884a_mobile_master_sw_put, @@ -3775,6 +3878,7 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = "Master Playback Switch", +		.subdevice = HDA_SUBDEV_AMP_FLAG,  		.info = snd_hda_mixer_amp_switch_info,  		.get = snd_hda_mixer_amp_switch_get,  		.put = ad1884a_mobile_master_sw_put, @@ -4116,6 +4220,7 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {  /*	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/  	{  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, +		.subdevice = HDA_SUBDEV_AMP_FLAG,  		.name = "Master Playback Switch",  		.info = snd_hda_mixer_amp_switch_info,  		.get = snd_hda_mixer_amp_switch_get,  |