提交 a54769c5 编写于 作者: L Linus Torvalds

Merge tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "Fixes for a few regressions of HD-audio, originated partly from 3.4
  and partly 3.3.

  The fixes for ThinkPad docking-station are for 3.3 kernels, thus they
  are based on 3.3 then merged back to 3.4, so that they can be merged
  to stable tree cleanly.  The non-trivial merge conflicts are because
  of this action.

  In addition, a couple of trivial fixes for documentation and a long-
  standing issue in the listing of built-in sound driver at boot time."

* tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda/conexant - Set up the missing docking-station pins
  ALSA: hda/conexant - Don't set HP pin-control bit unconditionally
  ALSA: workaround: change the timing of alsa_sound_last_init()
  ALSA: hda/sigmatel - Fix inverted mute LED
  ALSA: hda/realtek - Fix regression on Quanta/Gericom KN1
  ALSA: fix core/vmaster.c kernel-doc warning
...@@ -419,6 +419,7 @@ EXPORT_SYMBOL(snd_ctl_make_virtual_master); ...@@ -419,6 +419,7 @@ EXPORT_SYMBOL(snd_ctl_make_virtual_master);
* snd_ctl_add_vmaster_hook - Add a hook to a vmaster control * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
* @kcontrol: vmaster kctl element * @kcontrol: vmaster kctl element
* @hook: the hook function * @hook: the hook function
* @private_data: the private_data pointer to be saved
* *
* Adds the given hook to the vmaster control element so that it's called * Adds the given hook to the vmaster control element so that it's called
* at each time when the value is changed. * at each time when the value is changed.
......
...@@ -38,4 +38,4 @@ static int __init alsa_sound_last_init(void) ...@@ -38,4 +38,4 @@ static int __init alsa_sound_last_init(void)
return 0; return 0;
} }
__initcall(alsa_sound_last_init); late_initcall_sync(alsa_sound_last_init);
...@@ -3971,9 +3971,14 @@ static void cx_auto_init_output(struct hda_codec *codec) ...@@ -3971,9 +3971,14 @@ static void cx_auto_init_output(struct hda_codec *codec)
int i; int i;
mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids); mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids);
for (i = 0; i < cfg->hp_outs; i++) for (i = 0; i < cfg->hp_outs; i++) {
unsigned int val = PIN_OUT;
if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) &
AC_PINCAP_HP_DRV)
val |= AC_PINCTL_HP_EN;
snd_hda_codec_write(codec, cfg->hp_pins[i], 0, snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); AC_VERB_SET_PIN_WIDGET_CONTROL, val);
}
mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins); mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins);
...@@ -4391,8 +4396,10 @@ static void apply_pin_fixup(struct hda_codec *codec, ...@@ -4391,8 +4396,10 @@ static void apply_pin_fixup(struct hda_codec *codec,
enum { enum {
CXT_PINCFG_LENOVO_X200, CXT_PINCFG_LENOVO_X200,
CXT_PINCFG_LENOVO_TP410,
}; };
/* ThinkPad X200 & co with cxt5051 */
static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */ { 0x16, 0x042140ff }, /* HP (seq# overridden) */
{ 0x17, 0x21a11000 }, /* dock-mic */ { 0x17, 0x21a11000 }, /* dock-mic */
...@@ -4401,15 +4408,33 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { ...@@ -4401,15 +4408,33 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
{} {}
}; };
/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = {
{ 0x19, 0x042110ff }, /* HP (seq# overridden) */
{ 0x1a, 0x21a190f0 }, /* dock-mic */
{ 0x1c, 0x212140ff }, /* dock-HP */
{}
};
static const struct cxt_pincfg *cxt_pincfg_tbl[] = { static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
[CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
[CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410,
}; };
static const struct snd_pci_quirk cxt_fixups[] = { static const struct snd_pci_quirk cxt5051_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
{} {}
}; };
static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
{}
};
/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches /* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
* can be created (bko#42825) * can be created (bko#42825)
*/ */
...@@ -4446,13 +4471,13 @@ static int patch_conexant_auto(struct hda_codec *codec) ...@@ -4446,13 +4471,13 @@ static int patch_conexant_auto(struct hda_codec *codec)
case 0x14f15051: case 0x14f15051:
add_cx5051_fake_mutes(codec); add_cx5051_fake_mutes(codec);
codec->pin_amp_workaround = 1; codec->pin_amp_workaround = 1;
apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl);
break; break;
default: default:
codec->pin_amp_workaround = 1; codec->pin_amp_workaround = 1;
apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl);
} }
apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
/* Show mute-led control only on HP laptops /* Show mute-led control only on HP laptops
* This is a sort of white-list: on HP laptops, EAPD corresponds * This is a sort of white-list: on HP laptops, EAPD corresponds
* only to the mute-LED without actualy amp function. Meanwhile, * only to the mute-LED without actualy amp function. Meanwhile,
......
...@@ -1445,6 +1445,13 @@ enum { ...@@ -1445,6 +1445,13 @@ enum {
ALC_FIXUP_ACT_BUILD, ALC_FIXUP_ACT_BUILD,
}; };
static void alc_apply_pincfgs(struct hda_codec *codec,
const struct alc_pincfg *cfg)
{
for (; cfg->nid; cfg++)
snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
}
static void alc_apply_fixup(struct hda_codec *codec, int action) static void alc_apply_fixup(struct hda_codec *codec, int action)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
...@@ -1478,9 +1485,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action) ...@@ -1478,9 +1485,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
snd_printdd(KERN_INFO "hda_codec: %s: " snd_printdd(KERN_INFO "hda_codec: %s: "
"Apply pincfg for %s\n", "Apply pincfg for %s\n",
codec->chip_name, modelname); codec->chip_name, modelname);
for (; cfg->nid; cfg++) alc_apply_pincfgs(codec, cfg);
snd_hda_codec_set_pincfg(codec, cfg->nid,
cfg->val);
break; break;
case ALC_FIXUP_VERBS: case ALC_FIXUP_VERBS:
if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs) if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
...@@ -4861,6 +4866,7 @@ enum { ...@@ -4861,6 +4866,7 @@ enum {
ALC260_FIXUP_GPIO1_TOGGLE, ALC260_FIXUP_GPIO1_TOGGLE,
ALC260_FIXUP_REPLACER, ALC260_FIXUP_REPLACER,
ALC260_FIXUP_HP_B1900, ALC260_FIXUP_HP_B1900,
ALC260_FIXUP_KN1,
}; };
static void alc260_gpio1_automute(struct hda_codec *codec) static void alc260_gpio1_automute(struct hda_codec *codec)
...@@ -4888,6 +4894,36 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, ...@@ -4888,6 +4894,36 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
} }
} }
static void alc260_fixup_kn1(struct hda_codec *codec,
const struct alc_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
static const struct alc_pincfg pincfgs[] = {
{ 0x0f, 0x02214000 }, /* HP/speaker */
{ 0x12, 0x90a60160 }, /* int mic */
{ 0x13, 0x02a19000 }, /* ext mic */
{ 0x18, 0x01446000 }, /* SPDIF out */
/* disable bogus I/O pins */
{ 0x10, 0x411111f0 },
{ 0x11, 0x411111f0 },
{ 0x14, 0x411111f0 },
{ 0x15, 0x411111f0 },
{ 0x16, 0x411111f0 },
{ 0x17, 0x411111f0 },
{ 0x19, 0x411111f0 },
{ }
};
switch (action) {
case ALC_FIXUP_ACT_PRE_PROBE:
alc_apply_pincfgs(codec, pincfgs);
break;
case ALC_FIXUP_ACT_PROBE:
spec->init_amp = ALC_INIT_NONE;
break;
}
}
static const struct alc_fixup alc260_fixups[] = { static const struct alc_fixup alc260_fixups[] = {
[ALC260_FIXUP_HP_DC5750] = { [ALC260_FIXUP_HP_DC5750] = {
.type = ALC_FIXUP_PINS, .type = ALC_FIXUP_PINS,
...@@ -4938,7 +4974,11 @@ static const struct alc_fixup alc260_fixups[] = { ...@@ -4938,7 +4974,11 @@ static const struct alc_fixup alc260_fixups[] = {
.v.func = alc260_fixup_gpio1_toggle, .v.func = alc260_fixup_gpio1_toggle,
.chained = true, .chained = true,
.chain_id = ALC260_FIXUP_COEF, .chain_id = ALC260_FIXUP_COEF,
} },
[ALC260_FIXUP_KN1] = {
.type = ALC_FIXUP_FUNC,
.v.func = alc260_fixup_kn1,
},
}; };
static const struct snd_pci_quirk alc260_fixup_tbl[] = { static const struct snd_pci_quirk alc260_fixup_tbl[] = {
...@@ -4948,6 +4988,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { ...@@ -4948,6 +4988,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
{} {}
......
...@@ -5063,12 +5063,11 @@ static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) ...@@ -5063,12 +5063,11 @@ static void stac92xx_update_led_status(struct hda_codec *codec, int enabled)
if (spec->gpio_led_polarity) if (spec->gpio_led_polarity)
muted = !muted; muted = !muted;
/*polarity defines *not* muted state level*/
if (!spec->vref_mute_led_nid) { if (!spec->vref_mute_led_nid) {
if (muted) if (muted)
spec->gpio_data &= ~spec->gpio_led; /* orange */ spec->gpio_data |= spec->gpio_led;
else else
spec->gpio_data |= spec->gpio_led; /* white */ spec->gpio_data &= ~spec->gpio_led;
stac_gpio_set(codec, spec->gpio_mask, stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data); spec->gpio_dir, spec->gpio_data);
} else { } else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册