aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-11-07 11:13:39 -0500
committerTakashi Iwai <tiwai@suse.de>2011-11-08 02:59:36 -0500
commit24de183ed0369d73af89e6752fcc1ecbde59053d (patch)
tree328eeda01abff20d263ad841533af7f6ba133015 /sound/pci/hda/patch_realtek.c
parent82e14a4754599952f5504c1f696bbc77bdfd6009 (diff)
ALSA: hda/realtek - Add the support of shared HP/Mic
A machine like Q1-ultra which has only a single HP but no mic-jack, we can re-task the headhpone as an external mic jack. This was done formerly in ALC262 model=ultra quirk, and now the auto-parser supports this mode. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 1f3d1686db1a..ef040ec6580d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -183,6 +183,7 @@ struct alc_spec {
183 unsigned int single_input_src:1; 183 unsigned int single_input_src:1;
184 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ 184 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
185 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ 185 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
186 unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
186 187
187 /* auto-mute control */ 188 /* auto-mute control */
188 int automute_mode; 189 int automute_mode;
@@ -277,6 +278,8 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
277 return false; 278 return false;
278} 279}
279 280
281static void call_update_outputs(struct hda_codec *codec);
282
280/* select the given imux item; either unmute exclusively or select the route */ 283/* select the given imux item; either unmute exclusively or select the route */
281static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, 284static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
282 unsigned int idx, bool force) 285 unsigned int idx, bool force)
@@ -298,6 +301,19 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
298 return 0; 301 return 0;
299 spec->cur_mux[adc_idx] = idx; 302 spec->cur_mux[adc_idx] = idx;
300 303
304 /* for shared I/O, change the pin-control accordingly */
305 if (spec->shared_mic_hp) {
306 /* NOTE: this assumes that there are only two inputs, the
307 * first is the real internal mic and the second is HP jack.
308 */
309 snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0,
310 AC_VERB_SET_PIN_WIDGET_CONTROL,
311 spec->cur_mux[adc_idx] ?
312 PIN_VREF80 : PIN_HP);
313 spec->automute_speaker = !spec->cur_mux[adc_idx];
314 call_update_outputs(codec);
315 }
316
301 if (spec->dyn_adc_switch) { 317 if (spec->dyn_adc_switch) {
302 alc_dyn_adc_pcm_resetup(codec, idx); 318 alc_dyn_adc_pcm_resetup(codec, idx);
303 adc_idx = spec->dyn_adc_idx[idx]; 319 adc_idx = spec->dyn_adc_idx[idx];
@@ -547,7 +563,8 @@ static void update_outputs(struct hda_codec *codec)
547 * in general, HP pins/amps control should be enabled in all cases, 563 * in general, HP pins/amps control should be enabled in all cases,
548 * but currently set only for master_mute, just to be safe 564 * but currently set only for master_mute, just to be safe
549 */ 565 */
550 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), 566 if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
567 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
551 spec->autocfg.hp_pins, spec->master_mute, true); 568 spec->autocfg.hp_pins, spec->master_mute, true);
552 569
553 if (!spec->automute_speaker) 570 if (!spec->automute_speaker)
@@ -1115,6 +1132,9 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1115 hda_nid_t fixed, ext, dock; 1132 hda_nid_t fixed, ext, dock;
1116 int i; 1133 int i;
1117 1134
1135 if (spec->shared_mic_hp)
1136 return; /* no auto-mic for the shared I/O */
1137
1118 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1; 1138 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1119 1139
1120 fixed = ext = dock = 0; 1140 fixed = ext = dock = 0;
@@ -2667,6 +2687,9 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
2667 int max_nums = ARRAY_SIZE(spec->private_adc_nids); 2687 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2668 int i, nums = 0; 2688 int i, nums = 0;
2669 2689
2690 if (spec->shared_mic_hp)
2691 max_nums = 1; /* no multi streams with the shared HP/mic */
2692
2670 nid = codec->start_nid; 2693 nid = codec->start_nid;
2671 for (i = 0; i < codec->num_nodes; i++, nid++) { 2694 for (i = 0; i < codec->num_nodes; i++, nid++) {
2672 hda_nid_t src; 2695 hda_nid_t src;
@@ -2729,6 +2752,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
2729 continue; 2752 continue;
2730 2753
2731 label = hda_get_autocfg_input_label(codec, cfg, i); 2754 label = hda_get_autocfg_input_label(codec, cfg, i);
2755 if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2756 label = "Headphone Mic";
2732 if (prev_label && !strcmp(label, prev_label)) 2757 if (prev_label && !strcmp(label, prev_label))
2733 type_idx++; 2758 type_idx++;
2734 else 2759 else
@@ -2764,6 +2789,39 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
2764 return 0; 2789 return 0;
2765} 2790}
2766 2791
2792/* create a shared input with the headphone out */
2793static int alc_auto_create_shared_input(struct hda_codec *codec)
2794{
2795 struct alc_spec *spec = codec->spec;
2796 struct auto_pin_cfg *cfg = &spec->autocfg;
2797 unsigned int defcfg;
2798 hda_nid_t nid;
2799
2800 /* only one internal input pin? */
2801 if (cfg->num_inputs != 1)
2802 return 0;
2803 defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2804 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2805 return 0;
2806
2807 if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2808 nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2809 else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2810 nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2811 else
2812 return 0; /* both not available */
2813
2814 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2815 return 0; /* no input */
2816
2817 cfg->inputs[1].pin = nid;
2818 cfg->inputs[1].type = AUTO_PIN_MIC;
2819 cfg->num_inputs = 2;
2820 spec->shared_mic_hp = 1;
2821 snd_printdd("realtek: Enable shared I/O jack on NID 0x%x\n", nid);
2822 return 0;
2823}
2824
2767static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid, 2825static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2768 unsigned int pin_type) 2826 unsigned int pin_type)
2769{ 2827{
@@ -3654,6 +3712,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
3654 char boost_label[32]; 3712 char boost_label[32];
3655 3713
3656 label = hda_get_autocfg_input_label(codec, cfg, i); 3714 label = hda_get_autocfg_input_label(codec, cfg, i);
3715 if (spec->shared_mic_hp && !strcmp(label, "Misc"))
3716 label = "Headphone Mic";
3657 if (prev_label && !strcmp(label, prev_label)) 3717 if (prev_label && !strcmp(label, prev_label))
3658 type_idx++; 3718 type_idx++;
3659 else 3719 else
@@ -3859,6 +3919,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
3859 err = alc_auto_create_speaker_out(codec); 3919 err = alc_auto_create_speaker_out(codec);
3860 if (err < 0) 3920 if (err < 0)
3861 return err; 3921 return err;
3922 err = alc_auto_create_shared_input(codec);
3923 if (err < 0)
3924 return err;
3862 err = alc_auto_create_input_ctls(codec); 3925 err = alc_auto_create_input_ctls(codec);
3863 if (err < 0) 3926 if (err < 0)
3864 return err; 3927 return err;