aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-02-19 11:12:42 -0500
committerTakashi Iwai <tiwai@suse.de>2013-03-07 12:29:52 -0500
commit967303dabc22335e83c6ee4a9e0684a7c05da976 (patch)
treef94d11ae35522d65fb437812ca6190a31775bcfd
parent2dad9402192250d4061332b6a9be71ebf8493c49 (diff)
ALSA: hda - Add the generic Headphone Mic feature
This patch improves the generic parser code to allow to set up the headphone jack as a mic input. User can enable this feature by giving hp_mic hint string. The former shared hp/mic feature for the single built-in mic is still retained. This detection can be disabled now via hp_mic_detect hint string, too. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt3
-rw-r--r--sound/pci/hda/hda_generic.c143
-rw-r--r--sound/pci/hda/hda_generic.h6
3 files changed, 97 insertions, 55 deletions
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index d4faa63ff352..77e176a35ce1 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -466,6 +466,9 @@ The generic parser supports the following hints:
466- add_in_jack_modes (bool): add "xxx Jack Mode" enum controls to each 466- add_in_jack_modes (bool): add "xxx Jack Mode" enum controls to each
467 input jack for allowing to change the mic bias vref 467 input jack for allowing to change the mic bias vref
468- power_down_unused (bool): power down the unused widgets 468- power_down_unused (bool): power down the unused widgets
469- add_hp_mic (bool): add the headphone to capture source if possible
470- hp_mic_detect (bool): enable/disable the hp/mic shared input for a
471 single built-in mic case; default true
469- mixer_nid (int): specifies the widget NID of the analog-loopback 472- mixer_nid (int): specifies the widget NID of the analog-loopback
470 mixer 473 mixer
471 474
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 78897d05d80f..73de215da03f 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -159,6 +159,12 @@ static void parse_user_hints(struct hda_codec *codec)
159 val = snd_hda_get_bool_hint(codec, "power_down_unused"); 159 val = snd_hda_get_bool_hint(codec, "power_down_unused");
160 if (val >= 0) 160 if (val >= 0)
161 spec->power_down_unused = !!val; 161 spec->power_down_unused = !!val;
162 val = snd_hda_get_bool_hint(codec, "add_hp_mic");
163 if (val >= 0)
164 spec->hp_mic = !!val;
165 val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
166 if (val >= 0)
167 spec->suppress_hp_mic_detect = !val;
162 168
163 if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) 169 if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
164 spec->mixer_nid = val; 170 spec->mixer_nid = val;
@@ -2194,63 +2200,97 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
2194static void call_update_outputs(struct hda_codec *codec); 2200static void call_update_outputs(struct hda_codec *codec);
2195 2201
2196/* for shared I/O, change the pin-control accordingly */ 2202/* for shared I/O, change the pin-control accordingly */
2197static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) 2203static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2198{ 2204{
2199 struct hda_gen_spec *spec = codec->spec; 2205 struct hda_gen_spec *spec = codec->spec;
2206 bool as_mic;
2200 unsigned int val; 2207 unsigned int val;
2201 hda_nid_t pin = spec->autocfg.inputs[1].pin; 2208 hda_nid_t pin;
2202 /* NOTE: this assumes that there are only two inputs, the
2203 * first is the real internal mic and the second is HP/mic jack.
2204 */
2205 2209
2206 val = snd_hda_get_default_vref(codec, pin); 2210 pin = spec->hp_mic_pin;
2211 as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2207 2212
2208 /* This pin does not have vref caps - let's enable vref on pin 0x18 2213 if (!force) {
2209 instead, as suggested by Realtek */ 2214 val = snd_hda_codec_get_pin_target(codec, pin);
2215 if (as_mic) {
2216 if (val & PIN_IN)
2217 return;
2218 } else {
2219 if (val & PIN_OUT)
2220 return;
2221 }
2222 }
2223
2224 val = snd_hda_get_default_vref(codec, pin);
2225 /* if the HP pin doesn't support VREF and the codec driver gives an
2226 * alternative pin, set up the VREF on that pin instead
2227 */
2210 if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) { 2228 if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2211 const hda_nid_t vref_pin = spec->shared_mic_vref_pin; 2229 const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2212 unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); 2230 unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2213 if (vref_val != AC_PINCTL_VREF_HIZ) 2231 if (vref_val != AC_PINCTL_VREF_HIZ)
2214 snd_hda_set_pin_ctl_cache(codec, vref_pin, 2232 snd_hda_set_pin_ctl_cache(codec, vref_pin,
2215 PIN_IN | (set_as_mic ? vref_val : 0)); 2233 PIN_IN | (as_mic ? vref_val : 0));
2216 } 2234 }
2217 2235
2218 val = set_as_mic ? val | PIN_IN : PIN_HP; 2236 if (as_mic)
2237 val |= PIN_IN;
2238 else
2239 val = PIN_HP;
2219 set_pin_target(codec, pin, val, true); 2240 set_pin_target(codec, pin, val, true);
2220 2241
2221 spec->automute_speaker = !set_as_mic; 2242 /* update HP auto-mute state too */
2222 call_update_outputs(codec); 2243 if (spec->hp_automute_hook)
2244 spec->hp_automute_hook(codec, NULL);
2245 else
2246 snd_hda_gen_hp_automute(codec, NULL);
2223} 2247}
2224 2248
2225/* create a shared input with the headphone out */ 2249/* create a shared input with the headphone out */
2226static int create_shared_input(struct hda_codec *codec) 2250static int create_hp_mic(struct hda_codec *codec)
2227{ 2251{
2228 struct hda_gen_spec *spec = codec->spec; 2252 struct hda_gen_spec *spec = codec->spec;
2229 struct auto_pin_cfg *cfg = &spec->autocfg; 2253 struct auto_pin_cfg *cfg = &spec->autocfg;
2230 unsigned int defcfg; 2254 unsigned int defcfg;
2231 hda_nid_t nid; 2255 hda_nid_t nid;
2232 2256
2233 /* only one internal input pin? */ 2257 if (!spec->hp_mic) {
2234 if (cfg->num_inputs != 1) 2258 if (spec->suppress_hp_mic_detect)
2235 return 0; 2259 return 0;
2236 defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin); 2260 /* automatic detection: only if no input or a single internal
2237 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT) 2261 * input pin is found, try to detect the shared hp/mic
2262 */
2263 if (cfg->num_inputs > 1)
2264 return 0;
2265 else if (cfg->num_inputs == 1) {
2266 defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2267 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2268 return 0;
2269 }
2270 }
2271
2272 spec->hp_mic = 0; /* clear once */
2273 if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2238 return 0; 2274 return 0;
2239 2275
2240 if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 2276 nid = 0;
2241 nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */ 2277 if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2242 else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT) 2278 nid = cfg->line_out_pins[0];
2243 nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */ 2279 else if (cfg->hp_outs > 0)
2244 else 2280 nid = cfg->hp_pins[0];
2245 return 0; /* both not available */ 2281 if (!nid)
2282 return 0;
2246 2283
2247 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN)) 2284 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2248 return 0; /* no input */ 2285 return 0; /* no input */
2249 2286
2250 cfg->inputs[1].pin = nid; 2287 cfg->inputs[cfg->num_inputs].pin = nid;
2251 cfg->inputs[1].type = AUTO_PIN_MIC; 2288 cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2252 cfg->num_inputs = 2; 2289 cfg->num_inputs++;
2253 spec->shared_mic_hp = 1; 2290 spec->hp_mic = 1;
2291 spec->hp_mic_pin = nid;
2292 /* we can't handle auto-mic together with HP-mic */
2293 spec->suppress_auto_mic = 1;
2254 snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid); 2294 snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2255 return 0; 2295 return 0;
2256} 2296}
@@ -2602,7 +2642,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
2602 unsigned int ok_bits; 2642 unsigned int ok_bits;
2603 int i, n, nums; 2643 int i, n, nums;
2604 2644
2605 again:
2606 nums = 0; 2645 nums = 0;
2607 ok_bits = 0; 2646 ok_bits = 0;
2608 for (n = 0; n < spec->num_adc_nids; n++) { 2647 for (n = 0; n < spec->num_adc_nids; n++) {
@@ -2617,12 +2656,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
2617 } 2656 }
2618 2657
2619 if (!ok_bits) { 2658 if (!ok_bits) {
2620 if (spec->shared_mic_hp) {
2621 spec->shared_mic_hp = 0;
2622 imux->num_items = 1;
2623 goto again;
2624 }
2625
2626 /* check whether ADC-switch is possible */ 2659 /* check whether ADC-switch is possible */
2627 for (i = 0; i < imux->num_items; i++) { 2660 for (i = 0; i < imux->num_items; i++) {
2628 for (n = 0; n < spec->num_adc_nids; n++) { 2661 for (n = 0; n < spec->num_adc_nids; n++) {
@@ -2655,7 +2688,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
2655 spec->num_adc_nids = nums; 2688 spec->num_adc_nids = nums;
2656 } 2689 }
2657 2690
2658 if (imux->num_items == 1 || spec->shared_mic_hp) { 2691 if (imux->num_items == 1 ||
2692 (imux->num_items == 2 && spec->hp_mic)) {
2659 snd_printdd("hda-codec: reducing to a single ADC\n"); 2693 snd_printdd("hda-codec: reducing to a single ADC\n");
2660 spec->num_adc_nids = 1; /* reduce to a single ADC */ 2694 spec->num_adc_nids = 1; /* reduce to a single ADC */
2661 } 2695 }
@@ -2692,6 +2726,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
2692 snd_hda_get_path_idx(codec, path); 2726 snd_hda_get_path_idx(codec, path);
2693 2727
2694 if (!imux_added) { 2728 if (!imux_added) {
2729 if (spec->hp_mic_pin == pin)
2730 spec->hp_mic_mux_idx = imux->num_items;
2695 spec->imux_pins[imux->num_items] = pin; 2731 spec->imux_pins[imux->num_items] = pin;
2696 snd_hda_add_imux_item(imux, label, cfg_idx, NULL); 2732 snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
2697 imux_added = true; 2733 imux_added = true;
@@ -3416,8 +3452,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3416 3452
3417 spec->cur_mux[adc_idx] = idx; 3453 spec->cur_mux[adc_idx] = idx;
3418 3454
3419 if (spec->shared_mic_hp) 3455 if (spec->hp_mic)
3420 update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); 3456 update_hp_mic(codec, adc_idx, false);
3421 3457
3422 if (spec->dyn_adc_switch) 3458 if (spec->dyn_adc_switch)
3423 dyn_adc_pcm_resetup(codec, idx); 3459 dyn_adc_pcm_resetup(codec, idx);
@@ -3465,18 +3501,21 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3465 3501
3466 for (i = 0; i < num_pins; i++) { 3502 for (i = 0; i < num_pins; i++) {
3467 hda_nid_t nid = pins[i]; 3503 hda_nid_t nid = pins[i];
3468 unsigned int val; 3504 unsigned int val, oldval;
3469 if (!nid) 3505 if (!nid)
3470 break; 3506 break;
3507 oldval = snd_hda_codec_get_pin_target(codec, nid);
3508 if (oldval & PIN_IN)
3509 continue; /* no mute for inputs */
3471 /* don't reset VREF value in case it's controlling 3510 /* don't reset VREF value in case it's controlling
3472 * the amp (see alc861_fixup_asus_amp_vref_0f()) 3511 * the amp (see alc861_fixup_asus_amp_vref_0f())
3473 */ 3512 */
3474 if (spec->keep_vref_in_automute) 3513 if (spec->keep_vref_in_automute)
3475 val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP; 3514 val = oldval & ~PIN_HP;
3476 else 3515 else
3477 val = 0; 3516 val = 0;
3478 if (!mute) 3517 if (!mute)
3479 val |= snd_hda_codec_get_pin_target(codec, nid); 3518 val |= oldval;
3480 /* here we call update_pin_ctl() so that the pinctl is changed 3519 /* here we call update_pin_ctl() so that the pinctl is changed
3481 * without changing the pinctl target value; 3520 * without changing the pinctl target value;
3482 * the original target value will be still referred at the 3521 * the original target value will be still referred at the
@@ -3497,8 +3536,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
3497 * in general, HP pins/amps control should be enabled in all cases, 3536 * in general, HP pins/amps control should be enabled in all cases,
3498 * but currently set only for master_mute, just to be safe 3537 * but currently set only for master_mute, just to be safe
3499 */ 3538 */
3500 if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */ 3539 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3501 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3502 spec->autocfg.hp_pins, spec->master_mute); 3540 spec->autocfg.hp_pins, spec->master_mute);
3503 3541
3504 if (!spec->automute_speaker) 3542 if (!spec->automute_speaker)
@@ -3978,7 +4016,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
3978 err = create_loopback_mixing_ctl(codec); 4016 err = create_loopback_mixing_ctl(codec);
3979 if (err < 0) 4017 if (err < 0)
3980 return err; 4018 return err;
3981 err = create_shared_input(codec); 4019 err = create_hp_mic(codec);
3982 if (err < 0) 4020 if (err < 0)
3983 return err; 4021 return err;
3984 err = create_input_ctls(codec); 4022 err = create_input_ctls(codec);
@@ -4004,11 +4042,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
4004 if (err < 0) 4042 if (err < 0)
4005 return err; 4043 return err;
4006 4044
4007 if (!spec->shared_mic_hp) { 4045 err = check_auto_mic_availability(codec);
4008 err = check_auto_mic_availability(codec); 4046 if (err < 0)
4009 if (err < 0) 4047 return err;
4010 return err;
4011 }
4012 4048
4013 err = create_capture_mixers(codec); 4049 err = create_capture_mixers(codec);
4014 if (err < 0) 4050 if (err < 0)
@@ -4115,9 +4151,9 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
4115 4151
4116 free_kctls(spec); /* no longer needed */ 4152 free_kctls(spec); /* no longer needed */
4117 4153
4118 if (spec->shared_mic_hp) { 4154 if (spec->hp_mic_pin) {
4119 int err; 4155 int err;
4120 int nid = spec->autocfg.inputs[1].pin; 4156 int nid = spec->hp_mic_pin;
4121 err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0); 4157 err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
4122 if (err < 0) 4158 if (err < 0)
4123 return err; 4159 return err;
@@ -4780,11 +4816,10 @@ static void init_input_src(struct hda_codec *codec)
4780 snd_hda_activate_path(codec, path, active, false); 4816 snd_hda_activate_path(codec, path, active, false);
4781 } 4817 }
4782 } 4818 }
4819 if (spec->hp_mic)
4820 update_hp_mic(codec, c, true);
4783 } 4821 }
4784 4822
4785 if (spec->shared_mic_hp)
4786 update_shared_mic_hp(codec, spec->cur_mux[0]);
4787
4788 if (spec->cap_sync_hook) 4823 if (spec->cap_sync_hook)
4789 spec->cap_sync_hook(codec, NULL); 4824 spec->cap_sync_hook(codec, NULL);
4790} 4825}
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 009b57be96d3..7ee5b57946c9 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -145,7 +145,10 @@ struct hda_gen_spec {
145 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 145 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
146 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; 146 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
147 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; 147 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
148 /* shared hp/mic */
148 hda_nid_t shared_mic_vref_pin; 149 hda_nid_t shared_mic_vref_pin;
150 hda_nid_t hp_mic_pin;
151 int hp_mic_mux_idx;
149 152
150 /* DAC/ADC lists */ 153 /* DAC/ADC lists */
151 int num_all_dacs; 154 int num_all_dacs;
@@ -200,7 +203,8 @@ struct hda_gen_spec {
200 203
201 /* other parse behavior flags */ 204 /* other parse behavior flags */
202 unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ 205 unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
203 unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ 206 unsigned int hp_mic:1; /* Allow HP as a mic-in */
207 unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
204 unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ 208 unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
205 unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ 209 unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
206 unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */ 210 unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */