aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_generic.c110
-rw-r--r--sound/pci/hda/hda_generic.h1
2 files changed, 111 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index fb4d84394b7b..55b7897444a0 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1959,6 +1959,101 @@ static int create_shared_input(struct hda_codec *codec)
1959 return 0; 1959 return 0;
1960} 1960}
1961 1961
1962/*
1963 * output jack mode
1964 */
1965static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
1966 struct snd_ctl_elem_info *uinfo)
1967{
1968 static const char * const texts[] = {
1969 "Line Out", "Headphone Out",
1970 };
1971 return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
1972}
1973
1974static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
1975 struct snd_ctl_elem_value *ucontrol)
1976{
1977 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1978 hda_nid_t nid = kcontrol->private_value;
1979 if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
1980 ucontrol->value.enumerated.item[0] = 1;
1981 else
1982 ucontrol->value.enumerated.item[0] = 0;
1983 return 0;
1984}
1985
1986static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
1987 struct snd_ctl_elem_value *ucontrol)
1988{
1989 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1990 hda_nid_t nid = kcontrol->private_value;
1991 unsigned int val;
1992
1993 val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
1994 if (snd_hda_codec_get_pin_target(codec, nid) == val)
1995 return 0;
1996 snd_hda_set_pin_ctl_cache(codec, nid, val);
1997 return 1;
1998}
1999
2000static const struct snd_kcontrol_new out_jack_mode_enum = {
2001 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2002 .info = out_jack_mode_info,
2003 .get = out_jack_mode_get,
2004 .put = out_jack_mode_put,
2005};
2006
2007static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2008{
2009 struct hda_gen_spec *spec = codec->spec;
2010 int i;
2011
2012 for (i = 0; i < spec->kctls.used; i++) {
2013 struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2014 if (!strcmp(kctl->name, name) && kctl->index == idx)
2015 return true;
2016 }
2017 return false;
2018}
2019
2020static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2021 char *name, size_t name_len)
2022{
2023 struct hda_gen_spec *spec = codec->spec;
2024 int idx = 0;
2025
2026 snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2027 strlcat(name, " Jack Mode", name_len);
2028
2029 for (; find_kctl_name(codec, name, idx); idx++)
2030 ;
2031}
2032
2033static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2034 hda_nid_t *pins)
2035{
2036 struct hda_gen_spec *spec = codec->spec;
2037 int i;
2038
2039 for (i = 0; i < num_pins; i++) {
2040 hda_nid_t pin = pins[i];
2041 unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2042 if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
2043 struct snd_kcontrol_new *knew;
2044 char name[44];
2045 get_jack_mode_name(codec, pin, name, sizeof(name));
2046 knew = snd_hda_gen_add_kctl(spec, name,
2047 &out_jack_mode_enum);
2048 if (!knew)
2049 return -ENOMEM;
2050 knew->private_value = pin;
2051 }
2052 }
2053
2054 return 0;
2055}
2056
1962 2057
1963/* 2058/*
1964 * Parse input paths 2059 * Parse input paths
@@ -3298,6 +3393,21 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
3298 if (err < 0) 3393 if (err < 0)
3299 return err; 3394 return err;
3300 3395
3396 if (spec->add_out_jack_modes) {
3397 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3398 err = create_out_jack_modes(codec, cfg->line_outs,
3399 cfg->line_out_pins);
3400 if (err < 0)
3401 return err;
3402 }
3403 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
3404 err = create_out_jack_modes(codec, cfg->hp_outs,
3405 cfg->hp_pins);
3406 if (err < 0)
3407 return err;
3408 }
3409 }
3410
3301 dig_only: 3411 dig_only:
3302 parse_digital(codec); 3412 parse_digital(codec);
3303 3413
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 89683c7fe263..bfa2d973268b 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -191,6 +191,7 @@ struct hda_gen_spec {
191 unsigned int indep_hp:1; /* independent HP supported */ 191 unsigned int indep_hp:1; /* independent HP supported */
192 unsigned int indep_hp_enabled:1; /* independent HP enabled */ 192 unsigned int indep_hp_enabled:1; /* independent HP enabled */
193 unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ 193 unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
194 unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */
194 195
195 /* loopback mixing mode */ 196 /* loopback mixing mode */
196 bool aamix_mode; 197 bool aamix_mode;