/* for virtual master */
hda_nid_t vmaster_nid;
+ struct snd_kcontrol *vmaster_sw_kctl;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
int num_loopbacks;
ALC_FIXUP_ACT_PRE_PROBE,
ALC_FIXUP_ACT_PROBE,
ALC_FIXUP_ACT_INIT,
+ ALC_FIXUP_ACT_BUILD,
};
static void alc_apply_fixup(struct hda_codec *codec, int action)
}
if (!spec->no_analog &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, alc_slave_pfxs,
- "Playback Switch");
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, alc_slave_pfxs,
+ "Playback Switch",
+ true, &spec->vmaster_sw_kctl);
if (err < 0)
return err;
}
int err = __alc_build_controls(codec);
if (err < 0)
return err;
- return snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD);
+ return 0;
}
/* NID is set in alc_build_pcms */
};
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
-{
- switch (codec->subsystem_id) {
- case 0x103c1586:
- return 1;
- }
- return 0;
-}
-
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
-{
- /* update mute-LED according to the speaker mute state */
- if (nid == 0x01 || nid == 0x14) {
- int pinval;
- if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)
- pinval = 0x24;
- else
- pinval = 0x20;
- /* mic2 vref pin is used for mute LED control */
- snd_hda_codec_update_cache(codec, 0x19, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinval);
- }
- return alc_check_power_status(codec, nid);
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-
/* different alc269-variants */
enum {
ALC269_TYPE_ALC269VA,
spec->automute_hook = alc269_quanta_automute;
}
+/* update mute-LED according to the speaker mute state via mic2 VREF pin */
+static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
+{
+ struct hda_codec *codec = private_data;
+ unsigned int pinval = enabled ? 0x20 : 0x24;
+ snd_hda_codec_update_cache(codec, 0x19, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pinval);
+}
+
+static void alc269_fixup_mic2_mute(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ switch (action) {
+ case ALC_FIXUP_ACT_BUILD:
+ if (!spec->vmaster_sw_kctl)
+ return;
+ snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl,
+ alc269_fixup_mic2_mute_hook, codec);
+ /* fallthru */
+ case ALC_FIXUP_ACT_INIT:
+ snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
+ break;
+ }
+}
+
enum {
ALC269_FIXUP_SONY_VAIO,
ALC275_FIXUP_SONY_VAIO_GPIO2,
ALC269_FIXUP_DMIC,
ALC269VB_FIXUP_AMIC,
ALC269VB_FIXUP_DMIC,
+ ALC269_FIXUP_MIC2_MUTE_LED,
};
static const struct alc_fixup alc269_fixups[] = {
{ }
},
},
+ [ALC269_FIXUP_MIC2_MUTE_LED] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc269_fixup_mic2_mute,
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
#endif
spec->shutup = alc269_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (alc269_mic2_for_mute_led(codec))
- codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
-#endif
-
alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;