aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c199
1 files changed, 156 insertions, 43 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index fcf4c7142103..aa376b59c006 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -213,6 +213,7 @@ struct sigmatel_spec {
213 unsigned int gpio_mute; 213 unsigned int gpio_mute;
214 unsigned int gpio_led; 214 unsigned int gpio_led;
215 unsigned int gpio_led_polarity; 215 unsigned int gpio_led_polarity;
216 unsigned int vref_led;
216 217
217 /* stream */ 218 /* stream */
218 unsigned int stream_delay; 219 unsigned int stream_delay;
@@ -672,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
672 return 0; 673 return 0;
673} 674}
674 675
676static int stac_vrefout_set(struct hda_codec *codec,
677 hda_nid_t nid, unsigned int new_vref)
678{
679 int error, pinctl;
680
681 snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref);
682 pinctl = snd_hda_codec_read(codec, nid, 0,
683 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
684
685 if (pinctl < 0)
686 return pinctl;
687
688 pinctl &= 0xff;
689 pinctl &= ~AC_PINCTL_VREFEN;
690 pinctl |= (new_vref & AC_PINCTL_VREFEN);
691
692 error = snd_hda_codec_write_cache(codec, nid, 0,
693 AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
694 if (error < 0)
695 return error;
696
697 return 1;
698}
699
675static unsigned int stac92xx_vref_set(struct hda_codec *codec, 700static unsigned int stac92xx_vref_set(struct hda_codec *codec,
676 hda_nid_t nid, unsigned int new_vref) 701 hda_nid_t nid, unsigned int new_vref)
677{ 702{
@@ -4069,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
4069{ 4094{
4070 unsigned int gpiostate, gpiomask, gpiodir; 4095 unsigned int gpiostate, gpiomask, gpiodir;
4071 4096
4097 snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
4098
4072 gpiostate = snd_hda_codec_read(codec, codec->afg, 0, 4099 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
4073 AC_VERB_GET_GPIO_DATA, 0); 4100 AC_VERB_GET_GPIO_DATA, 0);
4074 gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); 4101 gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
@@ -4258,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec)
4258 spec->eapd_switch = val; 4285 spec->eapd_switch = val;
4259 get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); 4286 get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
4260 if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { 4287 if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
4261 spec->gpio_mask |= spec->gpio_led; 4288 if (spec->gpio_led <= 8) {
4262 spec->gpio_dir |= spec->gpio_led; 4289 spec->gpio_mask |= spec->gpio_led;
4263 if (spec->gpio_led_polarity) 4290 spec->gpio_dir |= spec->gpio_led;
4264 spec->gpio_data |= spec->gpio_led; 4291 if (spec->gpio_led_polarity)
4292 spec->gpio_data |= spec->gpio_led;
4293 }
4265 } 4294 }
4266} 4295}
4267 4296
@@ -4431,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
4431 snd_array_free(&spec->kctls); 4460 snd_array_free(&spec->kctls);
4432} 4461}
4433 4462
4463static void stac92xx_shutup_pins(struct hda_codec *codec)
4464{
4465 unsigned int i, def_conf;
4466
4467 if (codec->bus->shutdown)
4468 return;
4469 for (i = 0; i < codec->init_pins.used; i++) {
4470 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
4471 def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
4472 if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
4473 snd_hda_codec_write(codec, pin->nid, 0,
4474 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
4475 }
4476}
4477
4434static void stac92xx_shutup(struct hda_codec *codec) 4478static void stac92xx_shutup(struct hda_codec *codec)
4435{ 4479{
4436 struct sigmatel_spec *spec = codec->spec; 4480 struct sigmatel_spec *spec = codec->spec;
4437 4481
4438 snd_hda_shutup_pins(codec); 4482 stac92xx_shutup_pins(codec);
4439 4483
4440 if (spec->eapd_mask) 4484 if (spec->eapd_mask)
4441 stac_gpio_set(codec, spec->gpio_mask, 4485 stac_gpio_set(codec, spec->gpio_mask,
@@ -4833,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
4833 if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { 4877 if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
4834 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, 4878 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
4835 NULL, dev))) { 4879 NULL, dev))) {
4836 if (sscanf(dev->name, "HP_Mute_LED_%d_%d", 4880 if (sscanf(dev->name, "HP_Mute_LED_%d_%x",
4837 &spec->gpio_led_polarity, 4881 &spec->gpio_led_polarity,
4838 &spec->gpio_led) == 2) { 4882 &spec->gpio_led) == 2) {
4839 spec->gpio_led = 1 << spec->gpio_led; 4883 if (spec->gpio_led < 4)
4884 spec->gpio_led = 1 << spec->gpio_led;
4840 return 1; 4885 return 1;
4841 } 4886 }
4842 if (sscanf(dev->name, "HP_Mute_LED_%d", 4887 if (sscanf(dev->name, "HP_Mute_LED_%d",
@@ -4935,17 +4980,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
4935#endif 4980#endif
4936 4981
4937#ifdef CONFIG_PM 4982#ifdef CONFIG_PM
4938static int stac92xx_pre_resume(struct hda_codec *codec)
4939{
4940 struct sigmatel_spec *spec = codec->spec;
4941
4942 /* sync mute LED */
4943 if (spec->gpio_led)
4944 stac_gpio_set(codec, spec->gpio_mask,
4945 spec->gpio_dir, spec->gpio_data);
4946 return 0;
4947}
4948
4949static int stac92xx_resume(struct hda_codec *codec) 4983static int stac92xx_resume(struct hda_codec *codec)
4950{ 4984{
4951 struct sigmatel_spec *spec = codec->spec; 4985 struct sigmatel_spec *spec = codec->spec;
@@ -4964,7 +4998,65 @@ static int stac92xx_resume(struct hda_codec *codec)
4964 return 0; 4998 return 0;
4965} 4999}
4966 5000
5001static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
5002{
5003 stac92xx_shutup(codec);
5004 return 0;
5005}
5006
4967#ifdef CONFIG_SND_HDA_POWER_SAVE 5007#ifdef CONFIG_SND_HDA_POWER_SAVE
5008static int stac92xx_pre_resume(struct hda_codec *codec)
5009{
5010 struct sigmatel_spec *spec = codec->spec;
5011
5012 /* sync mute LED */
5013 if (spec->gpio_led) {
5014 if (spec->gpio_led <= 8) {
5015 stac_gpio_set(codec, spec->gpio_mask,
5016 spec->gpio_dir, spec->gpio_data);
5017 } else {
5018 stac_vrefout_set(codec,
5019 spec->gpio_led, spec->vref_led);
5020 }
5021 }
5022 return 0;
5023}
5024
5025static int stac92xx_post_suspend(struct hda_codec *codec)
5026{
5027 struct sigmatel_spec *spec = codec->spec;
5028 if (spec->gpio_led > 8) {
5029 /* with vref-out pin used for mute led control
5030 * codec AFG is prevented from D3 state, but on
5031 * system suspend it can (and should) be used
5032 */
5033 snd_hda_codec_read(codec, codec->afg, 0,
5034 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
5035 }
5036 return 0;
5037}
5038
5039static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
5040 unsigned int power_state)
5041{
5042 unsigned int afg_power_state = power_state;
5043 struct sigmatel_spec *spec = codec->spec;
5044
5045 if (power_state == AC_PWRST_D3) {
5046 if (spec->gpio_led > 8) {
5047 /* with vref-out pin used for mute led control
5048 * codec AFG is prevented from D3 state
5049 */
5050 afg_power_state = AC_PWRST_D1;
5051 }
5052 /* this delay seems necessary to avoid click noise at power-down */
5053 msleep(100);
5054 }
5055 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
5056 afg_power_state);
5057 snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
5058}
5059
4968/* 5060/*
4969 * For this feature CONFIG_SND_HDA_POWER_SAVE is needed 5061 * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
4970 * as mute LED state is updated in check_power_status hook 5062 * as mute LED state is updated in check_power_status hook
@@ -4973,8 +5065,12 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
4973{ 5065{
4974 struct sigmatel_spec *spec = codec->spec; 5066 struct sigmatel_spec *spec = codec->spec;
4975 int i, num_ext_dacs, muted = 1; 5067 int i, num_ext_dacs, muted = 1;
5068 unsigned int muted_lvl, notmtd_lvl;
4976 hda_nid_t nid; 5069 hda_nid_t nid;
4977 5070
5071 if (!spec->gpio_led)
5072 return 0;
5073
4978 for (i = 0; i < spec->multiout.num_dacs; i++) { 5074 for (i = 0; i < spec->multiout.num_dacs; i++) {
4979 nid = spec->multiout.dac_nids[i]; 5075 nid = spec->multiout.dac_nids[i];
4980 if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & 5076 if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
@@ -4999,17 +5095,27 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
4999 muted = 0; /* extra output is not muted */ 5095 muted = 0; /* extra output is not muted */
5000 } 5096 }
5001 } 5097 }
5002 if (muted) 5098 /*polarity defines *not* muted state level*/
5003 spec->gpio_data &= ~spec->gpio_led; /* orange */ 5099 if (spec->gpio_led <= 8) {
5004 else 5100 if (muted)
5005 spec->gpio_data |= spec->gpio_led; /* white */ 5101 spec->gpio_data &= ~spec->gpio_led; /* orange */
5102 else
5103 spec->gpio_data |= spec->gpio_led; /* white */
5006 5104
5007 if (!spec->gpio_led_polarity) { 5105 if (!spec->gpio_led_polarity) {
5008 /* LED state is inverted on these systems */ 5106 /* LED state is inverted on these systems */
5009 spec->gpio_data ^= spec->gpio_led; 5107 spec->gpio_data ^= spec->gpio_led;
5108 }
5109 stac_gpio_set(codec, spec->gpio_mask,
5110 spec->gpio_dir, spec->gpio_data);
5111 } else {
5112 notmtd_lvl = spec->gpio_led_polarity ?
5113 AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
5114 muted_lvl = spec->gpio_led_polarity ?
5115 AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
5116 spec->vref_led = muted ? muted_lvl : notmtd_lvl;
5117 stac_vrefout_set(codec, spec->gpio_led, spec->vref_led);
5010 } 5118 }
5011
5012 stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
5013 return 0; 5119 return 0;
5014} 5120}
5015 5121
@@ -5023,13 +5129,7 @@ static int stac92xx_check_power_status(struct hda_codec *codec,
5023 5129
5024 return 0; 5130 return 0;
5025} 5131}
5026#endif 5132#endif /* CONFIG_SND_HDA_POWER_SAVE */
5027
5028static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
5029{
5030 stac92xx_shutup(codec);
5031 return 0;
5032}
5033#endif /* CONFIG_PM */ 5133#endif /* CONFIG_PM */
5034 5134
5035static const struct hda_codec_ops stac92xx_patch_ops = { 5135static const struct hda_codec_ops stac92xx_patch_ops = {
@@ -5041,7 +5141,6 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
5041#ifdef CONFIG_PM 5141#ifdef CONFIG_PM
5042 .suspend = stac92xx_suspend, 5142 .suspend = stac92xx_suspend,
5043 .resume = stac92xx_resume, 5143 .resume = stac92xx_resume,
5044 .pre_resume = stac92xx_pre_resume,
5045#endif 5144#endif
5046 .reboot_notify = stac92xx_shutup, 5145 .reboot_notify = stac92xx_shutup,
5047}; 5146};
@@ -5555,10 +5654,17 @@ again:
5555 5654
5556#ifdef CONFIG_SND_HDA_POWER_SAVE 5655#ifdef CONFIG_SND_HDA_POWER_SAVE
5557 if (spec->gpio_led) { 5656 if (spec->gpio_led) {
5558 spec->gpio_mask |= spec->gpio_led; 5657 if (spec->gpio_led <= 8) {
5559 spec->gpio_dir |= spec->gpio_led; 5658 spec->gpio_mask |= spec->gpio_led;
5560 spec->gpio_data |= spec->gpio_led; 5659 spec->gpio_dir |= spec->gpio_led;
5561 /* register check_power_status callback. */ 5660 spec->gpio_data |= spec->gpio_led;
5661 } else {
5662 codec->patch_ops.set_power_state =
5663 stac92xx_set_power_state;
5664 codec->patch_ops.post_suspend =
5665 stac92xx_post_suspend;
5666 }
5667 codec->patch_ops.pre_resume = stac92xx_pre_resume;
5562 codec->patch_ops.check_power_status = 5668 codec->patch_ops.check_power_status =
5563 stac92xx_check_power_status; 5669 stac92xx_check_power_status;
5564 } 5670 }
@@ -5883,10 +5989,17 @@ again:
5883 5989
5884#ifdef CONFIG_SND_HDA_POWER_SAVE 5990#ifdef CONFIG_SND_HDA_POWER_SAVE
5885 if (spec->gpio_led) { 5991 if (spec->gpio_led) {
5886 spec->gpio_mask |= spec->gpio_led; 5992 if (spec->gpio_led <= 8) {
5887 spec->gpio_dir |= spec->gpio_led; 5993 spec->gpio_mask |= spec->gpio_led;
5888 spec->gpio_data |= spec->gpio_led; 5994 spec->gpio_dir |= spec->gpio_led;
5889 /* register check_power_status callback. */ 5995 spec->gpio_data |= spec->gpio_led;
5996 } else {
5997 codec->patch_ops.set_power_state =
5998 stac92xx_set_power_state;
5999 codec->patch_ops.post_suspend =
6000 stac92xx_post_suspend;
6001 }
6002 codec->patch_ops.pre_resume = stac92xx_pre_resume;
5890 codec->patch_ops.check_power_status = 6003 codec->patch_ops.check_power_status =
5891 stac92xx_check_power_status; 6004 stac92xx_check_power_status;
5892 } 6005 }