diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 60 |
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 | ||
1275 | static unsigned int dell_m6_pin_configs[13] = { | 1276 | static 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 | |||
2058 | static 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 | |||
2068 | static 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 | ||
2057 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2086 | static 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 | ||
3206 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | 3263 | static 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; |