]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.drivers/alsa-hda-stac-yet-more-fixes
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / alsa-hda-stac-yet-more-fixes
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: hda - Fix AFG power management on IDT 92HD* codecs
3 Patch-mainline:
4 References: bnc#446025
5
6 The AFG pin power-mapping isn't properly set for the fixed I/O pins
7 on IDT 92HD* codecs. This resulted in the low power mode after the
8 boot until any jack detection is executed, thus no output from the
9 speaker.
10
11 This patch fixes the power mapping for the fixed pins, and also fixes
12 the GPIO bits and digital I/O pin settings properly in stac92xx_ini().
13
14 Reference: Novell bnc#446025
15 https://bugzilla.novell.com/show_bug.cgi?id=446025
16
17 Signed-off-by: Takashi Iwai <tiwai@suse.de>
18
19 ---
20 sound/pci/hda/patch_sigmatel.c | 80 +++++++++++++++++++++++++++--------------
21 1 file changed, 54 insertions(+), 26 deletions(-)
22
23 --- a/sound/pci/hda/patch_sigmatel.c
24 +++ b/sound/pci/hda/patch_sigmatel.c
25 @@ -3700,10 +3700,14 @@ static void stac92xx_power_down(struct h
26 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
27 }
28
29 +static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
30 + int enable);
31 +
32 static int stac92xx_init(struct hda_codec *codec)
33 {
34 struct sigmatel_spec *spec = codec->spec;
35 struct auto_pin_cfg *cfg = &spec->autocfg;
36 + unsigned int gpio;
37 int i;
38
39 snd_hda_sequence_write(codec, spec->init);
40 @@ -3714,6 +3718,16 @@ static int stac92xx_init(struct hda_code
41 snd_hda_codec_write_cache(codec,
42 spec->adc_nids[i], 0,
43 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
44 +
45 + /* set up GPIO */
46 + gpio = spec->gpio_data;
47 + /* turn on EAPD statically when spec->eapd_switch isn't set.
48 + * otherwise, unsol event will turn it on/off dynamically
49 + */
50 + if (!spec->eapd_switch)
51 + gpio |= spec->eapd_mask;
52 + stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
53 +
54 /* set up pins */
55 if (spec->hp_detect) {
56 /* Enable unsolicited responses on the HP widget */
57 @@ -3753,39 +3767,43 @@ static int stac92xx_init(struct hda_code
58 for (i = 0; i < spec->num_dmics; i++)
59 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
60 AC_PINCTL_IN_EN);
61 + if (cfg->dig_out_pin)
62 + stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
63 + AC_PINCTL_OUT_EN);
64 + if (cfg->dig_in_pin)
65 + stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
66 + AC_PINCTL_IN_EN);
67 for (i = 0; i < spec->num_pwrs; i++) {
68 - int event = is_nid_hp_pin(cfg, spec->pwr_nids[i])
69 - ? STAC_HP_EVENT : STAC_PWR_EVENT;
70 - int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
71 - 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
72 - int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
73 - 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
74 - def_conf = get_defcfg_connect(def_conf);
75 + hda_nid_t nid = spec->pwr_nids[i];
76 + int pinctl, def_conf;
77 + int event = STAC_PWR_EVENT;
78 +
79 + if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
80 + continue; /* already has an unsol event */
81 +
82 + pinctl = snd_hda_codec_read(codec, nid, 0,
83 + AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
84 /* outputs are only ports capable of power management
85 * any attempts on powering down a input port cause the
86 * referenced VREF to act quirky.
87 */
88 if (pinctl & AC_PINCTL_IN_EN)
89 continue;
90 + def_conf = snd_hda_codec_read(codec, nid, 0,
91 + AC_VERB_GET_CONFIG_DEFAULT, 0);
92 + def_conf = get_defcfg_connect(def_conf);
93 /* skip any ports that don't have jacks since presence
94 * detection is useless */
95 - if (def_conf && def_conf != AC_JACK_PORT_FIXED)
96 + if (def_conf != AC_JACK_PORT_COMPLEX) {
97 + if (def_conf != AC_JACK_PORT_NONE)
98 + stac_toggle_power_map(codec, nid, 1);
99 continue;
100 + }
101 enable_pin_detect(codec, spec->pwr_nids[i], event | i);
102 codec->patch_ops.unsol_event(codec, (event | i) << 26);
103 }
104 if (spec->dac_list)
105 stac92xx_power_down(codec);
106 - if (cfg->dig_out_pin)
107 - stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
108 - AC_PINCTL_OUT_EN);
109 - if (cfg->dig_in_pin)
110 - stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
111 - AC_PINCTL_IN_EN);
112 -
113 - stac_gpio_set(codec, spec->gpio_mask,
114 - spec->gpio_dir, spec->gpio_data);
115 -
116 return 0;
117 }
118
119 @@ -3950,14 +3968,18 @@ static void stac92xx_hp_detect(struct hd
120 }
121 }
122
123 -static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
124 +static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
125 + int enable)
126 {
127 struct sigmatel_spec *spec = codec->spec;
128 - hda_nid_t nid = spec->pwr_nids[idx];
129 - int presence, val;
130 - val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0)
131 - & 0x000000ff;
132 - presence = get_hp_pin_presence(codec, nid);
133 + unsigned int idx, val;
134 +
135 + for (idx = 0; idx < spec->num_pwrs; idx++) {
136 + if (spec->pwr_nids[idx] == nid)
137 + break;
138 + }
139 + if (idx >= spec->num_pwrs)
140 + return;
141
142 /* several codecs have two power down bits */
143 if (spec->pwr_mapping)
144 @@ -3965,14 +3987,20 @@ static void stac92xx_pin_sense(struct hd
145 else
146 idx = 1 << idx;
147
148 - if (presence)
149 + val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
150 + if (enable)
151 val &= ~idx;
152 else
153 val |= idx;
154
155 /* power down unused output ports */
156 snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val);
157 -};
158 +}
159 +
160 +static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
161 +{
162 + stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
163 +}
164
165 static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
166 {