aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_sigmatel.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e1d07ab5cd15..b3a15d616873 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -181,6 +181,7 @@ struct sigmatel_spec {
181 /* i/o switches */ 181 /* i/o switches */
182 unsigned int io_switch[2]; 182 unsigned int io_switch[2];
183 unsigned int clfe_swap; 183 unsigned int clfe_swap;
184 unsigned int hp_switch;
184 unsigned int aloopback; 185 unsigned int aloopback;
185 186
186 struct hda_pcm pcm_rec[2]; /* PCM information */ 187 struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -1274,7 +1275,7 @@ static unsigned int ref92hd73xx_pin_configs[13] = {
1274 1275
1275static unsigned int dell_m6_pin_configs[13] = { 1276static unsigned int dell_m6_pin_configs[13] = {
1276 0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110, 1277 0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
1277 0x03a11020, 0x03011050, 0x4f0000f0, 0x4f0000f0, 1278 0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
1278 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0, 1279 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
1279 0x4f0000f0, 1280 0x4f0000f0,
1280}; 1281};
@@ -2052,6 +2053,34 @@ static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int
2052 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 2053 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2053} 2054}
2054 2055
2056#define stac92xx_hp_switch_info snd_ctl_boolean_mono_info
2057
2058static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
2059 struct snd_ctl_elem_value *ucontrol)
2060{
2061 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2062 struct sigmatel_spec *spec = codec->spec;
2063
2064 ucontrol->value.integer.value[0] = spec->hp_switch;
2065 return 0;
2066}
2067
2068static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2069 struct snd_ctl_elem_value *ucontrol)
2070{
2071 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2072 struct sigmatel_spec *spec = codec->spec;
2073
2074 spec->hp_switch = ucontrol->value.integer.value[0];
2075
2076 /* check to be sure that the ports are upto date with
2077 * switch changes
2078 */
2079 codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
2080
2081 return 1;
2082}
2083
2055#define stac92xx_io_switch_info snd_ctl_boolean_mono_info 2084#define stac92xx_io_switch_info snd_ctl_boolean_mono_info
2056 2085
2057static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 2086static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -2123,6 +2152,15 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
2123 return 1; 2152 return 1;
2124} 2153}
2125 2154
2155#define STAC_CODEC_HP_SWITCH(xname) \
2156 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2157 .name = xname, \
2158 .index = 0, \
2159 .info = stac92xx_hp_switch_info, \
2160 .get = stac92xx_hp_switch_get, \
2161 .put = stac92xx_hp_switch_put, \
2162 }
2163
2126#define STAC_CODEC_IO_SWITCH(xname, xpval) \ 2164#define STAC_CODEC_IO_SWITCH(xname, xpval) \
2127 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2165 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2128 .name = xname, \ 2166 .name = xname, \
@@ -2147,6 +2185,7 @@ enum {
2147 STAC_CTL_WIDGET_VOL, 2185 STAC_CTL_WIDGET_VOL,
2148 STAC_CTL_WIDGET_MUTE, 2186 STAC_CTL_WIDGET_MUTE,
2149 STAC_CTL_WIDGET_MONO_MUX, 2187 STAC_CTL_WIDGET_MONO_MUX,
2188 STAC_CTL_WIDGET_HP_SWITCH,
2150 STAC_CTL_WIDGET_IO_SWITCH, 2189 STAC_CTL_WIDGET_IO_SWITCH,
2151 STAC_CTL_WIDGET_CLFE_SWITCH 2190 STAC_CTL_WIDGET_CLFE_SWITCH
2152}; 2191};
@@ -2155,6 +2194,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
2155 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2194 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2156 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2195 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2157 STAC_MONO_MUX, 2196 STAC_MONO_MUX,
2197 STAC_CODEC_HP_SWITCH(NULL),
2158 STAC_CODEC_IO_SWITCH(NULL, 0), 2198 STAC_CODEC_IO_SWITCH(NULL, 0),
2159 STAC_CODEC_CLFE_SWITCH(NULL, 0), 2199 STAC_CODEC_CLFE_SWITCH(NULL, 0),
2160}; 2200};
@@ -2419,6 +2459,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
2419 } 2459 }
2420 } 2460 }
2421 2461
2462 if (cfg->hp_outs > 1) {
2463 err = stac92xx_add_control(spec,
2464 STAC_CTL_WIDGET_HP_SWITCH,
2465 "Headphone as Line Out Switch", 0);
2466 if (err < 0)
2467 return err;
2468 }
2469
2422 if (spec->line_switch) { 2470 if (spec->line_switch) {
2423 nid = cfg->input_pins[AUTO_PIN_LINE]; 2471 nid = cfg->input_pins[AUTO_PIN_LINE];
2424 pincap = snd_hda_param_read(codec, nid, 2472 pincap = snd_hda_param_read(codec, nid,
@@ -3163,6 +3211,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3163{ 3211{
3164 struct sigmatel_spec *spec = codec->spec; 3212 struct sigmatel_spec *spec = codec->spec;
3165 struct auto_pin_cfg *cfg = &spec->autocfg; 3213 struct auto_pin_cfg *cfg = &spec->autocfg;
3214 int nid = cfg->hp_pins[cfg->hp_outs - 1];
3166 int i, presence; 3215 int i, presence;
3167 3216
3168 presence = 0; 3217 presence = 0;
@@ -3173,11 +3222,15 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3173 for (i = 0; i < cfg->hp_outs; i++) { 3222 for (i = 0; i < cfg->hp_outs; i++) {
3174 if (presence) 3223 if (presence)
3175 break; 3224 break;
3225 if (spec->hp_switch && cfg->hp_pins[i] == nid)
3226 break;
3176 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); 3227 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
3177 } 3228 }
3178 3229
3179 if (presence) { 3230 if (presence) {
3180 /* disable lineouts, enable hp */ 3231 /* disable lineouts, enable hp */
3232 if (spec->hp_switch)
3233 stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
3181 for (i = 0; i < cfg->line_outs; i++) 3234 for (i = 0; i < cfg->line_outs; i++)
3182 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 3235 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
3183 AC_PINCTL_OUT_EN); 3236 AC_PINCTL_OUT_EN);
@@ -3190,6 +3243,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3190 ~spec->eapd_mask); 3243 ~spec->eapd_mask);
3191 } else { 3244 } else {
3192 /* enable lineouts, disable hp */ 3245 /* enable lineouts, disable hp */
3246 if (spec->hp_switch)
3247 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
3193 for (i = 0; i < cfg->line_outs; i++) 3248 for (i = 0; i < cfg->line_outs; i++)
3194 stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 3249 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
3195 AC_PINCTL_OUT_EN); 3250 AC_PINCTL_OUT_EN);
@@ -3201,6 +3256,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3201 spec->gpio_dir, spec->gpio_data | 3256 spec->gpio_dir, spec->gpio_data |
3202 spec->eapd_mask); 3257 spec->eapd_mask);
3203 } 3258 }
3259 if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
3260 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
3204} 3261}
3205 3262
3206static void stac92xx_pin_sense(struct hda_codec *codec, int idx) 3263static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
@@ -3459,6 +3516,7 @@ again:
3459 3516
3460 switch (spec->multiout.num_dacs) { 3517 switch (spec->multiout.num_dacs) {
3461 case 0x3: /* 6 Channel */ 3518 case 0x3: /* 6 Channel */
3519 spec->multiout.hp_nid = 0x17;
3462 spec->mixer = stac92hd73xx_6ch_mixer; 3520 spec->mixer = stac92hd73xx_6ch_mixer;
3463 spec->init = stac92hd73xx_6ch_core_init; 3521 spec->init = stac92hd73xx_6ch_core_init;
3464 break; 3522 break;