aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_generic.c47
-rw-r--r--sound/pci/hda/hda_generic.h4
2 files changed, 50 insertions, 1 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 4b1524a861f3..1485d871d628 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -133,6 +133,9 @@ static void parse_user_hints(struct hda_codec *codec)
133 val = snd_hda_get_bool_hint(codec, "line_in_auto_switch"); 133 val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
134 if (val >= 0) 134 if (val >= 0)
135 spec->line_in_auto_switch = !!val; 135 spec->line_in_auto_switch = !!val;
136 val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
137 if (val >= 0)
138 spec->auto_mute_via_amp = !!val;
136 val = snd_hda_get_bool_hint(codec, "need_dac_fix"); 139 val = snd_hda_get_bool_hint(codec, "need_dac_fix");
137 if (val >= 0) 140 if (val >= 0)
138 spec->need_dac_fix = !!val; 141 spec->need_dac_fix = !!val;
@@ -808,6 +811,9 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
808 * Helper functions for creating mixer ctl elements 811 * Helper functions for creating mixer ctl elements
809 */ 812 */
810 813
814static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
815 struct snd_ctl_elem_value *ucontrol);
816
811enum { 817enum {
812 HDA_CTL_WIDGET_VOL, 818 HDA_CTL_WIDGET_VOL,
813 HDA_CTL_WIDGET_MUTE, 819 HDA_CTL_WIDGET_MUTE,
@@ -815,7 +821,15 @@ enum {
815}; 821};
816static const struct snd_kcontrol_new control_templates[] = { 822static const struct snd_kcontrol_new control_templates[] = {
817 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 823 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
818 HDA_CODEC_MUTE(NULL, 0, 0, 0), 824 /* only the put callback is replaced for handling the special mute */
825 {
826 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
827 .subdevice = HDA_SUBDEV_AMP_FLAG,
828 .info = snd_hda_mixer_amp_switch_info,
829 .get = snd_hda_mixer_amp_switch_get,
830 .put = hda_gen_mixer_mute_put, /* replaced */
831 .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
832 },
819 HDA_BIND_MUTE(NULL, 0, 0, 0), 833 HDA_BIND_MUTE(NULL, 0, 0, 0),
820}; 834};
821 835
@@ -922,6 +936,23 @@ static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
922 return add_sw_ctl(codec, pfx, cidx, chs, path); 936 return add_sw_ctl(codec, pfx, cidx, chs, path);
923} 937}
924 938
939/* playback mute control with the software mute bit check */
940static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
941 struct snd_ctl_elem_value *ucontrol)
942{
943 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
944 struct hda_gen_spec *spec = codec->spec;
945
946 if (spec->auto_mute_via_amp) {
947 hda_nid_t nid = get_amp_nid(kcontrol);
948 bool enabled = !((spec->mute_bits >> nid) & 1);
949 ucontrol->value.integer.value[0] &= enabled;
950 ucontrol->value.integer.value[1] &= enabled;
951 }
952
953 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
954}
955
925/* any ctl assigned to the path with the given index? */ 956/* any ctl assigned to the path with the given index? */
926static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type) 957static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
927{ 958{
@@ -3719,6 +3750,16 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3719 unsigned int val, oldval; 3750 unsigned int val, oldval;
3720 if (!nid) 3751 if (!nid)
3721 break; 3752 break;
3753
3754 if (spec->auto_mute_via_amp) {
3755 if (mute)
3756 spec->mute_bits |= (1ULL << nid);
3757 else
3758 spec->mute_bits &= ~(1ULL << nid);
3759 set_pin_eapd(codec, nid, !mute);
3760 continue;
3761 }
3762
3722 oldval = snd_hda_codec_get_pin_target(codec, nid); 3763 oldval = snd_hda_codec_get_pin_target(codec, nid);
3723 if (oldval & PIN_IN) 3764 if (oldval & PIN_IN)
3724 continue; /* no mute for inputs */ 3765 continue; /* no mute for inputs */
@@ -3786,6 +3827,10 @@ static void call_update_outputs(struct hda_codec *codec)
3786 spec->automute_hook(codec); 3827 spec->automute_hook(codec);
3787 else 3828 else
3788 snd_hda_gen_update_outputs(codec); 3829 snd_hda_gen_update_outputs(codec);
3830
3831 /* sync the whole vmaster slaves to reflect the new auto-mute status */
3832 if (spec->auto_mute_via_amp && !codec->bus->shutdown)
3833 snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
3789} 3834}
3790 3835
3791/* standard HP-automute helper */ 3836/* standard HP-automute helper */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 76200314ee95..e199a852388b 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -209,6 +209,7 @@ struct hda_gen_spec {
209 unsigned int master_mute:1; /* master mute over all */ 209 unsigned int master_mute:1; /* master mute over all */
210 unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ 210 unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
211 unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ 211 unsigned int line_in_auto_switch:1; /* allow line-in auto switch */
212 unsigned int auto_mute_via_amp:1; /* auto-mute via amp instead of pinctl */
212 213
213 /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */ 214 /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */
214 unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */ 215 unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */
@@ -237,6 +238,9 @@ struct hda_gen_spec {
237 unsigned int have_aamix_ctl:1; 238 unsigned int have_aamix_ctl:1;
238 unsigned int hp_mic_jack_modes:1; 239 unsigned int hp_mic_jack_modes:1;
239 240
241 /* additional mute flags (only effective with auto_mute_via_amp=1) */
242 u64 mute_bits;
243
240 /* badness tables for output path evaluations */ 244 /* badness tables for output path evaluations */
241 const struct badness_table *main_out_badness; 245 const struct badness_table *main_out_badness;
242 const struct badness_table *extra_out_badness; 246 const struct badness_table *extra_out_badness;