aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-11-25 02:21:51 -0500
committerTakashi Iwai <tiwai@suse.de>2008-11-25 05:53:50 -0500
commitf73d35853e9263c7c404f0d6c0fe3d83fc6fd5c0 (patch)
treeaba108242a9324f6d4d0c2b6c4f84182350cdf9b
parent9e97697666d0e7494946cfb639f6a9faacd5f1b0 (diff)
ALSA: hda - Fix AFG power management on IDT 92HD* codecs
The AFG pin power-mapping isn't properly set for the fixed I/O pins on IDT 92HD* codecs. This resulted in the low power mode after the boot until any jack detection is executed, thus no output from the speaker. This patch fixes the power mapping for the fixed pins, and also fixes the GPIO bits and digital I/O pin settings properly in stac92xx_ini(). Reference: Novell bnc#446025 https://bugzilla.novell.com/show_bug.cgi?id=446025 Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/patch_sigmatel.c80
1 files changed, 54 insertions, 26 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 2b52a4056a9b..5a29699c6fdb 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3697,10 +3697,14 @@ static void stac92xx_power_down(struct hda_codec *codec)
3697 AC_VERB_SET_POWER_STATE, AC_PWRST_D3); 3697 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
3698} 3698}
3699 3699
3700static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
3701 int enable);
3702
3700static int stac92xx_init(struct hda_codec *codec) 3703static int stac92xx_init(struct hda_codec *codec)
3701{ 3704{
3702 struct sigmatel_spec *spec = codec->spec; 3705 struct sigmatel_spec *spec = codec->spec;
3703 struct auto_pin_cfg *cfg = &spec->autocfg; 3706 struct auto_pin_cfg *cfg = &spec->autocfg;
3707 unsigned int gpio;
3704 int i; 3708 int i;
3705 3709
3706 snd_hda_sequence_write(codec, spec->init); 3710 snd_hda_sequence_write(codec, spec->init);
@@ -3711,6 +3715,16 @@ static int stac92xx_init(struct hda_codec *codec)
3711 snd_hda_codec_write_cache(codec, 3715 snd_hda_codec_write_cache(codec,
3712 spec->adc_nids[i], 0, 3716 spec->adc_nids[i], 0,
3713 AC_VERB_SET_POWER_STATE, AC_PWRST_D3); 3717 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
3718
3719 /* set up GPIO */
3720 gpio = spec->gpio_data;
3721 /* turn on EAPD statically when spec->eapd_switch isn't set.
3722 * otherwise, unsol event will turn it on/off dynamically
3723 */
3724 if (!spec->eapd_switch)
3725 gpio |= spec->eapd_mask;
3726 stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
3727
3714 /* set up pins */ 3728 /* set up pins */
3715 if (spec->hp_detect) { 3729 if (spec->hp_detect) {
3716 /* Enable unsolicited responses on the HP widget */ 3730 /* Enable unsolicited responses on the HP widget */
@@ -3750,39 +3764,43 @@ static int stac92xx_init(struct hda_codec *codec)
3750 for (i = 0; i < spec->num_dmics; i++) 3764 for (i = 0; i < spec->num_dmics; i++)
3751 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], 3765 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
3752 AC_PINCTL_IN_EN); 3766 AC_PINCTL_IN_EN);
3767 if (cfg->dig_out_pin)
3768 stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
3769 AC_PINCTL_OUT_EN);
3770 if (cfg->dig_in_pin)
3771 stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
3772 AC_PINCTL_IN_EN);
3753 for (i = 0; i < spec->num_pwrs; i++) { 3773 for (i = 0; i < spec->num_pwrs; i++) {
3754 int event = is_nid_hp_pin(cfg, spec->pwr_nids[i]) 3774 hda_nid_t nid = spec->pwr_nids[i];
3755 ? STAC_HP_EVENT : STAC_PWR_EVENT; 3775 int pinctl, def_conf;
3756 int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i], 3776 int event = STAC_PWR_EVENT;
3757 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 3777
3758 int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i], 3778 if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
3759 0, AC_VERB_GET_CONFIG_DEFAULT, 0); 3779 continue; /* already has an unsol event */
3760 def_conf = get_defcfg_connect(def_conf); 3780
3781 pinctl = snd_hda_codec_read(codec, nid, 0,
3782 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3761 /* outputs are only ports capable of power management 3783 /* outputs are only ports capable of power management
3762 * any attempts on powering down a input port cause the 3784 * any attempts on powering down a input port cause the
3763 * referenced VREF to act quirky. 3785 * referenced VREF to act quirky.
3764 */ 3786 */
3765 if (pinctl & AC_PINCTL_IN_EN) 3787 if (pinctl & AC_PINCTL_IN_EN)
3766 continue; 3788 continue;
3789 def_conf = snd_hda_codec_read(codec, nid, 0,
3790 AC_VERB_GET_CONFIG_DEFAULT, 0);
3791 def_conf = get_defcfg_connect(def_conf);
3767 /* skip any ports that don't have jacks since presence 3792 /* skip any ports that don't have jacks since presence
3768 * detection is useless */ 3793 * detection is useless */
3769 if (def_conf && def_conf != AC_JACK_PORT_FIXED) 3794 if (def_conf != AC_JACK_PORT_COMPLEX) {
3795 if (def_conf != AC_JACK_PORT_NONE)
3796 stac_toggle_power_map(codec, nid, 1);
3770 continue; 3797 continue;
3798 }
3771 enable_pin_detect(codec, spec->pwr_nids[i], event | i); 3799 enable_pin_detect(codec, spec->pwr_nids[i], event | i);
3772 codec->patch_ops.unsol_event(codec, (event | i) << 26); 3800 codec->patch_ops.unsol_event(codec, (event | i) << 26);
3773 } 3801 }
3774 if (spec->dac_list) 3802 if (spec->dac_list)
3775 stac92xx_power_down(codec); 3803 stac92xx_power_down(codec);
3776 if (cfg->dig_out_pin)
3777 stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
3778 AC_PINCTL_OUT_EN);
3779 if (cfg->dig_in_pin)
3780 stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
3781 AC_PINCTL_IN_EN);
3782
3783 stac_gpio_set(codec, spec->gpio_mask,
3784 spec->gpio_dir, spec->gpio_data);
3785
3786 return 0; 3804 return 0;
3787} 3805}
3788 3806
@@ -3947,14 +3965,18 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3947 } 3965 }
3948} 3966}
3949 3967
3950static void stac92xx_pin_sense(struct hda_codec *codec, int idx) 3968static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
3969 int enable)
3951{ 3970{
3952 struct sigmatel_spec *spec = codec->spec; 3971 struct sigmatel_spec *spec = codec->spec;
3953 hda_nid_t nid = spec->pwr_nids[idx]; 3972 unsigned int idx, val;
3954 int presence, val; 3973
3955 val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) 3974 for (idx = 0; idx < spec->num_pwrs; idx++) {
3956 & 0x000000ff; 3975 if (spec->pwr_nids[idx] == nid)
3957 presence = get_hp_pin_presence(codec, nid); 3976 break;
3977 }
3978 if (idx >= spec->num_pwrs)
3979 return;
3958 3980
3959 /* several codecs have two power down bits */ 3981 /* several codecs have two power down bits */
3960 if (spec->pwr_mapping) 3982 if (spec->pwr_mapping)
@@ -3962,14 +3984,20 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
3962 else 3984 else
3963 idx = 1 << idx; 3985 idx = 1 << idx;
3964 3986
3965 if (presence) 3987 val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
3988 if (enable)
3966 val &= ~idx; 3989 val &= ~idx;
3967 else 3990 else
3968 val |= idx; 3991 val |= idx;
3969 3992
3970 /* power down unused output ports */ 3993 /* power down unused output ports */
3971 snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); 3994 snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val);
3972}; 3995}
3996
3997static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
3998{
3999 stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
4000}
3973 4001
3974static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) 4002static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
3975{ 4003{