summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com>2010-09-15 10:02:29 +0200
committerTakashi Iwai <tiwai@suse.de>2010-09-16 07:32:30 +0200
commit977ddd6b2e63716cfefe669bbdb30ec0bcea1fe4 (patch)
treeb82f3eb46002e981a84e6f12221025b923cbb2d4 /sound/pci
parentALSA: hda - Add input jack layer support to Realtek codec (diff)
downloadlinux-977ddd6b2e63716cfefe669bbdb30ec0bcea1fe4.tar.xz
linux-977ddd6b2e63716cfefe669bbdb30ec0bcea1fe4.zip
ALSA: hda - Set up COEFs for ALC269 to avoid click noises at power-saving
For avoiding the click noises at power-saving, set some COEF values for ALC269* codecs. Signed-off-by: Kailang Yang <kailang@realtek.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_realtek.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3b040870365d..ab2947d87232 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1673,6 +1673,15 @@ static int alc_read_coef_idx(struct hda_codec *codec,
return val;
}
+static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
+ unsigned int coef_val)
+{
+ snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
+ coef_idx);
+ snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
+ coef_val);
+}
+
/* set right pin controls for digital I/O */
static void alc_auto_init_digital(struct hda_codec *codec)
{
@@ -14598,6 +14607,68 @@ static void alc269_auto_init(struct hda_codec *codec)
alc_inithook(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ struct alc_spec *spec = codec->spec;
+ int val;
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power down output pin */
+ alc_write_coef_idx(codec, 0x04, val & ~(1<<11));
+ }
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power down output pin */
+ alc_write_coef_idx(codec, 0x04, val & ~(1<<11));
+ msleep(150);
+ }
+
+ alc_shutup(codec);
+ if (spec && spec->power_hook)
+ spec->power_hook(codec);
+ return 0;
+}
+#endif
+#ifdef SND_HDA_NEEDS_RESUME
+static int alc269_resume(struct hda_codec *codec)
+{
+ int val;
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power down output pin */
+ alc_write_coef_idx(codec, 0x04, val & ~(1<<11));
+ msleep(150);
+ }
+
+ codec->patch_ops.init(codec);
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power up output pin */
+ alc_write_coef_idx(codec, 0x04, val | (1<<11));
+ msleep(200);
+ }
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power up output pin */
+ alc_write_coef_idx(codec, 0x04, val | (1<<11));
+ }
+
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (codec->patch_ops.check_power_status)
+ codec->patch_ops.check_power_status(codec, 0x01);
+#endif
+ return 0;
+}
+#endif
+
enum {
ALC269_FIXUP_SONY_VAIO,
};
@@ -14814,6 +14885,41 @@ static struct alc_config_preset alc269_presets[] = {
},
};
+static int alc269_fill_coef(struct hda_codec *codec)
+{
+ int val;
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
+ alc_write_coef_idx(codec, 0xf, 0x960b);
+ alc_write_coef_idx(codec, 0xe, 0x8817);
+ }
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
+ alc_write_coef_idx(codec, 0xf, 0x960b);
+ alc_write_coef_idx(codec, 0xe, 0x8814);
+ }
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+ val = alc_read_coef_idx(codec, 0x04);
+ /* Power up output pin */
+ alc_write_coef_idx(codec, 0x04, val | (1<<11));
+ }
+
+ if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ val = alc_read_coef_idx(codec, 0xd);
+ if ((val & 0x0c00) >> 10 != 0x1) {
+ /* Capless ramp up clock control */
+ alc_write_coef_idx(codec, 0xd, val | 1<<10);
+ }
+ val = alc_read_coef_idx(codec, 0x17);
+ if ((val & 0x01c0) >> 6 != 0x4) {
+ /* Class D power on reset */
+ alc_write_coef_idx(codec, 0x17, val | 1<<7);
+ }
+ }
+ return 0;
+}
+
static int patch_alc269(struct hda_codec *codec)
{
struct alc_spec *spec;
@@ -14839,6 +14945,8 @@ static int patch_alc269(struct hda_codec *codec)
} else
alc_fix_pll_init(codec, 0x20, 0x04, 15);
+ alc269_fill_coef(codec);
+
board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
alc269_models,
alc269_cfg_tbl);
@@ -14917,6 +15025,12 @@ static int patch_alc269(struct hda_codec *codec)
spec->vmaster_nid = 0x02;
codec->patch_ops = alc_patch_ops;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ codec->patch_ops.suspend = alc269_suspend;
+#endif
+#ifdef SND_HDA_NEEDS_RESUME
+ codec->patch_ops.resume = alc269_resume;
+#endif
if (board_config == ALC269_AUTO)
spec->init_hook = alc269_auto_init;
#ifdef CONFIG_SND_HDA_POWER_SAVE