summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-06-04 12:39:38 +0200
committerTakashi Iwai <tiwai@suse.de>2008-06-06 11:54:07 +0200
commit2c3bf9abb11dd8050cd2d153917d1746c8d5af05 (patch)
tree32de0e54ba0643dac9415c605357e66f445d3db0
parent17bba1b72d190742c99a140154f0abac9c1996c3 (diff)
downloadlinux-2c3bf9abb11dd8050cd2d153917d1746c8d5af05.tar.bz2
[ALSA] hda - Fix PLL gating control on Realtek codecs
On some Realtek codecs, the analog PLL gating control bit must be set off while the default value is 1. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/patch_realtek.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 048cb84721fa..7997e13b59a6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -285,6 +285,10 @@ struct alc_spec {
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
#endif
+
+ /* for PLL fix */
+ hda_nid_t pll_nid;
+ unsigned int pll_coef_idx, pll_coef_bit;
};
/*
@@ -752,6 +756,38 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
{ }
};
+/*
+ * Fix hardware PLL issue
+ * On some codecs, the analog PLL gating control must be off while
+ * the default value is 1.
+ */
+static void alc_fix_pll(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+
+ if (!spec->pll_nid)
+ return;
+ snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
+ spec->pll_coef_idx);
+ val = snd_hda_codec_read(codec, spec->pll_nid, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
+ spec->pll_coef_idx);
+ snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
+ val & ~(1 << spec->pll_coef_bit));
+}
+
+static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int coef_idx, unsigned int coef_bit)
+{
+ struct alc_spec *spec = codec->spec;
+ spec->pll_nid = nid;
+ spec->pll_coef_idx = coef_idx;
+ spec->pll_coef_bit = coef_bit;
+ alc_fix_pll(codec);
+}
+
static void alc_sku_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -2400,6 +2436,8 @@ static int alc_init(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
unsigned int i;
+ alc_fix_pll(codec);
+
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
@@ -8286,6 +8324,8 @@ static int patch_alc883(struct hda_codec *codec)
codec->spec = spec;
+ alc_fix_pll_init(codec, 0x20, 0x0a, 10);
+
board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
alc883_models,
alc883_cfg_tbl);
@@ -9886,6 +9926,8 @@ static int patch_alc262(struct hda_codec *codec)
}
#endif
+ alc_fix_pll_init(codec, 0x20, 0x0a, 10);
+
board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
alc262_models,
alc262_cfg_tbl);
@@ -11196,6 +11238,8 @@ static int patch_alc269(struct hda_codec *codec)
codec->spec = spec;
+ alc_fix_pll_init(codec, 0x20, 0x04, 15);
+
board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
alc269_models,
alc269_cfg_tbl);
@@ -14531,6 +14575,8 @@ static int patch_alc662(struct hda_codec *codec)
codec->spec = spec;
+ alc_fix_pll_init(codec, 0x20, 0x04, 15);
+
board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
alc662_models,
alc662_cfg_tbl);