aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-10 10:57:58 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-12 02:44:38 -0500
commit978e77e78cff7a85a31ad552ffd8afee319e8721 (patch)
treec95b0e607f72f3549817fd992999e8251adfe96a
parenta365fed9806e182cb4e1b7bb1855759489d95858 (diff)
ALSA: hda - Add output jack mode enum controls
Add the enum controls for changing the headphone amp bits of output jacks, such as "Headphone Jack Mode". This feature isn't enabled as default, so far, unless spec->add_out_jack_modes flag is set. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-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;