Skip to content

Commit

Permalink
ALSA: hda - Restore default pin configs for realtek codecs
Browse files Browse the repository at this point in the history
Some machines have broken BIOS resume that doesn't restore the default
pin configuration properly, which results in a wrong detection of HP
pin.  This causes a silent speaker output due to missing HP detection.
Related bug: Novell bug#406101
	https://bugzilla.novell.com/show_bug.cgi?id=406101

This patch fixes the issue by saving/restoring the default pin configs
by the driver itself.

Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Oct 27, 2008
1 parent da74ae3 commit e044c39
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ struct alc_spec {
/* for PLL fix */
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;

#ifdef SND_HDA_NEEDS_RESUME
#define ALC_MAX_PINS 16
unsigned int num_pins;
hda_nid_t pin_nids[ALC_MAX_PINS];
unsigned int pin_cfgs[ALC_MAX_PINS];
#endif
};

/*
Expand Down Expand Up @@ -2778,6 +2785,64 @@ static void alc_free(struct hda_codec *codec)
codec->spec = NULL; /* to be sure */
}

#ifdef SND_HDA_NEEDS_RESUME
static void store_pin_configs(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
hda_nid_t nid, end_nid;

end_nid = codec->start_nid + codec->num_nodes;
for (nid = codec->start_nid; nid < end_nid; nid++) {
unsigned int wid_caps = get_wcaps(codec, nid);
unsigned int wid_type =
(wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
if (wid_type != AC_WID_PIN)
continue;
if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids))
break;
spec->pin_nids[spec->num_pins] = nid;
spec->pin_cfgs[spec->num_pins] =
snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_CONFIG_DEFAULT, 0);
spec->num_pins++;
}
}

static void resume_pin_configs(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int i;

for (i = 0; i < spec->num_pins; i++) {
hda_nid_t pin_nid = spec->pin_nids[i];
unsigned int pin_config = spec->pin_cfgs[i];
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
pin_config & 0x000000ff);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
(pin_config & 0x0000ff00) >> 8);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
(pin_config & 0x00ff0000) >> 16);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
pin_config >> 24);
}
}

static int alc_resume(struct hda_codec *codec)
{
resume_pin_configs(codec);
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
return 0;
}
#else
#define store_pin_configs(codec)
#endif

/*
*/
static struct hda_codec_ops alc_patch_ops = {
Expand All @@ -2786,6 +2851,9 @@ static struct hda_codec_ops alc_patch_ops = {
.init = alc_init,
.free = alc_free,
.unsol_event = alc_unsol_event,
#ifdef SND_HDA_NEEDS_RESUME
.resume = alc_resume,
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE
.check_power_status = alc_check_power_status,
#endif
Expand Down Expand Up @@ -3832,6 +3900,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -5250,6 +5319,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
}
spec->num_mixers++;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -10313,6 +10383,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -11447,6 +11518,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -12230,6 +12302,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
spec->mixers[spec->num_mixers] = alc269_capture_mixer;
spec->num_mixers++;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -13316,6 +13389,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->mixers[spec->num_mixers] = alc861_capture_mixer;
spec->num_mixers++;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -14427,6 +14501,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;

store_pin_configs(codec);
return 1;
}

Expand Down Expand Up @@ -16258,6 +16333,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)

spec->mixers[spec->num_mixers] = alc662_capture_mixer;
spec->num_mixers++;

store_pin_configs(codec);
return 1;
}

Expand Down

0 comments on commit e044c39

Please sign in to comment.