diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-12-18 11:24:25 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-12 02:30:43 -0500 |
commit | 81fede89eda16a597c2d814113b74677754b0058 (patch) | |
tree | 41c63269cf1d70a1f2af1bf5d088dcfd76585c30 | |
parent | 9bf387b6121bc446f275b0de8196d4dea8a3c876 (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>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 35 |
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 | ||
2555 | static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs); | ||
2556 | |||
2553 | static int add_single_cap_ctl(struct hda_codec *codec, const char *label, | 2557 | static 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; |