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 Original line Diff line number Diff line
@@ -417,11 +417,13 @@ static void stac_update_outputs(struct hda_codec *codec)
			val &= ~spec->eapd_mask;
			val &= ~spec->eapd_mask;
		else
		else
			val |= spec->eapd_mask;
			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,
			stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir,
				      val);
				      val);
		}
		}
	}
	}
}


static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
				  bool enable, bool do_write)
				  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)
static int stac_init(struct hda_codec *codec)
{
{
	struct sigmatel_spec *spec = codec->spec;
	struct sigmatel_spec *spec = codec->spec;
	unsigned int gpio;
	int i;
	int i;


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


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


	snd_hda_gen_init(codec);
	snd_hda_gen_init(codec);


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


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