]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/alsa-hda-stac-yet-more-fixes
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / alsa-hda-stac-yet-more-fixes
CommitLineData
2cb7cef9
BS
1From: Takashi Iwai <tiwai@suse.de>
2Subject: ALSA: hda - Fix AFG power management on IDT 92HD* codecs
3Patch-mainline:
4References: bnc#446025
5
6The AFG pin power-mapping isn't properly set for the fixed I/O pins
7on IDT 92HD* codecs. This resulted in the low power mode after the
8boot until any jack detection is executed, thus no output from the
9speaker.
10
11This patch fixes the power mapping for the fixed pins, and also fixes
12the GPIO bits and digital I/O pin settings properly in stac92xx_ini().
13
14Reference: Novell bnc#446025
15 https://bugzilla.novell.com/show_bug.cgi?id=446025
16
17Signed-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 {