[PATCH 3/3] ALSA: hda - Add volatile_pin_ctl flag to generic parser

From: Takashi Iwai
Date: Fri May 31 2013 - 08:24:26 EST


It turned out that some VIA codecs handle the pin control value and
EAPD dynamically in the hardware level even if you change the values
explicitly in the driver. The driver assumes that the values are
static until the driver changes the value itself, and this
inconsistency resulted in unexpected surprises like the missing
headphone outputs.

This patch adds a flag to hda_gen_spec indicating that the codec may
reset pins dynamically, so that the init and the automute functions
will write the pin control and EAPD at each time even if it's same as
the cached value.

Reported-by: Alex Riesen <raa.lkml@xxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> [v3.9]
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
---
sound/pci/hda/hda_generic.c | 20 +++++++++++++++-----
sound/pci/hda/hda_generic.h | 1 +
sound/pci/hda/patch_via.c | 1 +
3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index fbc10b6..29c9d00 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -175,13 +175,24 @@ static void parse_user_hints(struct hda_codec *codec)
spec->mixer_nid = val;
}

+/* write the cached verb; if volatile_pin_ctl is set, don't trust caches */
+static void update_pin_verb(struct hda_codec *codec, hda_nid_t nid,
+ int verb, int val)
+{
+ struct hda_gen_spec *spec = codec->spec;
+
+ if (spec->volatile_pin_ctl)
+ snd_hda_codec_write_cache(codec, nid, 0, verb, val);
+ else
+ snd_hda_codec_update_cache(codec, nid, 0, verb, val);
+}
+
/*
* pin control value accesses
*/

#define update_pin_ctl(codec, pin, val) \
- snd_hda_codec_update_cache(codec, pin, 0, \
- AC_VERB_SET_PIN_WIDGET_CONTROL, val)
+ update_pin_verb(codec, pin, AC_VERB_SET_PIN_WIDGET_CONTROL, val)

/* restore the pinctl based on the cached value */
static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
@@ -788,9 +799,8 @@ static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
return;
if (codec->inv_eapd)
enable = !enable;
- snd_hda_codec_update_cache(codec, pin, 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- enable ? 0x02 : 0x00);
+ update_pin_verb(codec, pin, AC_VERB_SET_EAPD_BTLENABLE,
+ enable ? 0x02 : 0x00);
}

/* re-initialize the path specified by the given path index */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 54e6651..2d70a7d0 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -222,6 +222,7 @@ struct hda_gen_spec {
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
unsigned int own_eapd_ctl:1; /* set EAPD by own function */
+ unsigned int volatile_pin_ctl:1; /* pin contrl&EAPDs are volatile */
unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */
unsigned int indep_hp:1; /* independent HP supported */
unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 2f16605..4bbd4f3 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -136,6 +136,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
spec->codec_type = VT1708S;
spec->no_pin_power_ctl = 1;
spec->gen.indep_hp = 1;
+ spec->gen.volatile_pin_ctl = 1;
spec->gen.pcm_playback_hook = via_playback_pcm_hook;
return spec;
}
--
1.8.3


--Multipart_Fri_May_31_15:05:00_2013-1
Content-Type: text/plain; charset=US-ASCII



--Multipart_Fri_May_31_15:05:00_2013-1--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/