Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ea9a69d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda - Fix EAPD GPIO control for Sigmatel codecs



The EAPD GPIO is dynamically turned on/off for some machines with
Sigmatel codecs, but this didn't work as expected, and it resulted in
spontaneous lost of speaker outputs per HP plugging or power-saving.

This patch fixes the bug by simply including spec->eapd_mask into
spec->gpio_mask and spec->gpio_data bits.

Reported-and-tested-by: default avatarEric Shattow <lucent@gmail.com>
Cc: <stable@vger.kernel.org> [v3.9+]
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 256ca9c3
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -417,11 +417,13 @@ static void stac_update_outputs(struct hda_codec *codec)
			val &= ~spec->eapd_mask;
		else
			val |= spec->eapd_mask;
		if (spec->gpio_data != val)
		if (spec->gpio_data != val) {
			spec->gpio_data = val;
			stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir,
				      val);
		}
	}
}

static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
				  bool enable, bool do_write)
@@ -3612,20 +3614,18 @@ static int stac_parse_auto_config(struct hda_codec *codec)
static int stac_init(struct hda_codec *codec)
{
	struct sigmatel_spec *spec = codec->spec;
	unsigned int gpio;
	int i;

	/* override some hints */
	stac_store_hints(codec);

	/* set up GPIO */
	gpio = spec->gpio_data;
	/* turn on EAPD statically when spec->eapd_switch isn't set.
	 * otherwise, unsol event will turn it on/off dynamically
	 */
	if (!spec->eapd_switch)
		gpio |= spec->eapd_mask;
	stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
		spec->gpio_data |= spec->eapd_mask;
	stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);

	snd_hda_gen_init(codec);

@@ -3915,6 +3915,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
{
	struct sigmatel_spec *spec = codec->spec;

	spec->gpio_mask |= spec->eapd_mask;
	if (spec->gpio_led) {
		if (!spec->vref_mute_led_nid) {
			spec->gpio_mask |= spec->gpio_led;