aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-12-18 11:24:25 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-12 02:30:43 -0500
commit81fede89eda16a597c2d814113b74677754b0058 (patch)
tree41c63269cf1d70a1f2af1bf5d088dcfd76585c30 /sound/pci/hda/patch_realtek.c
parent9bf387b6121bc446f275b0de8196d4dea8a3c876 (diff)
ALSA: hda/realtek - Add conexant-style inverted dmic handling
To make the parser more generic, a few codes to handle the inverted stereo dmic in a way Conexant parser does is added in this patch. The caller should set spec->inv_dmic_split flag appropriately. 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.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6fb39221aac4..fbdcbded3417 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -184,6 +184,7 @@ struct alc_spec {
184 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ 184 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
185 hda_nid_t inv_dmic_pin; 185 hda_nid_t inv_dmic_pin;
186 hda_nid_t shared_mic_vref_pin; 186 hda_nid_t shared_mic_vref_pin;
187 int inv_dmic_split_idx; /* used internally for inv_dmic_split */
187 188
188 /* DAC list */ 189 /* DAC list */
189 int num_all_dacs; 190 int num_all_dacs;
@@ -222,6 +223,7 @@ struct alc_spec {
222 unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ 223 unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
223 unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ 224 unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
224 unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ 225 unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
226 unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
225 227
226 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ 228 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
227 229
@@ -2550,6 +2552,8 @@ static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2550 return 0; 2552 return 0;
2551} 2553}
2552 2554
2555static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs);
2556
2553static int add_single_cap_ctl(struct hda_codec *codec, const char *label, 2557static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2554 int idx, bool is_switch, unsigned int ctl) 2558 int idx, bool is_switch, unsigned int ctl)
2555{ 2559{
@@ -2557,17 +2561,37 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2557 char tmpname[44]; 2561 char tmpname[44];
2558 int type = is_switch ? ALC_CTL_WIDGET_MUTE : ALC_CTL_WIDGET_VOL; 2562 int type = is_switch ? ALC_CTL_WIDGET_MUTE : ALC_CTL_WIDGET_VOL;
2559 const char *sfx = is_switch ? "Switch" : "Volume"; 2563 const char *sfx = is_switch ? "Switch" : "Volume";
2564 unsigned int chs;
2565 int err;
2560 2566
2561 if (!ctl) 2567 if (!ctl)
2562 return 0; 2568 return 0;
2563 2569
2570 if (idx == spec->inv_dmic_split_idx)
2571 chs = 1;
2572 else
2573 chs = 3;
2574
2564 if (label) 2575 if (label)
2565 snprintf(tmpname, sizeof(tmpname), 2576 snprintf(tmpname, sizeof(tmpname),
2566 "%s Capture %s", label, sfx); 2577 "%s Capture %s", label, sfx);
2567 else 2578 else
2568 snprintf(tmpname, sizeof(tmpname), 2579 snprintf(tmpname, sizeof(tmpname),
2569 "Capture %s", sfx); 2580 "Capture %s", sfx);
2570 return add_control(spec, type, tmpname, idx, ctl); 2581 err = add_control(spec, type, tmpname, idx,
2582 amp_val_replace_channels(ctl, chs));
2583 if (err < 0 || chs == 3)
2584 return err;
2585
2586 /* Make independent right kcontrol */
2587 if (label)
2588 snprintf(tmpname, sizeof(tmpname),
2589 "Inverted %s Capture %s", label, sfx);
2590 else
2591 snprintf(tmpname, sizeof(tmpname),
2592 "Inverted Capture %s", sfx);
2593 return add_control(spec, type, tmpname, idx,
2594 amp_val_replace_channels(ctl, 2));
2571} 2595}
2572 2596
2573/* create single (and simple) capture volume and switch controls */ 2597/* create single (and simple) capture volume and switch controls */
@@ -2730,6 +2754,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
2730 if (num_adcs < 0) 2754 if (num_adcs < 0)
2731 return 0; 2755 return 0;
2732 2756
2757 spec->inv_dmic_split_idx = -1;
2733 for (i = 0; i < cfg->num_inputs; i++) { 2758 for (i = 0; i < cfg->num_inputs; i++) {
2734 hda_nid_t pin; 2759 hda_nid_t pin;
2735 const char *label; 2760 const char *label;
@@ -2783,6 +2808,14 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
2783 imux_added = true; 2808 imux_added = true;
2784 } 2809 }
2785 } 2810 }
2811
2812 if (spec->inv_dmic_split) {
2813 if (cfg->inputs[i].type == AUTO_PIN_MIC) {
2814 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
2815 if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
2816 spec->inv_dmic_split_idx = i;
2817 }
2818 }
2786 } 2819 }
2787 2820
2788 return 0; 2821 return 0;