aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2014-10-07 04:18:42 -0400
committerTakashi Iwai <tiwai@suse.de>2014-10-07 06:01:48 -0400
commit9d36a7dc4df6ef77cfc02ba78a10bc8577c2663f (patch)
treef30d38a2bc9a12372222ebe711e27fabb399516b /sound/pci/hda/patch_realtek.c
parenta33cc48d28b4ff58e2627e2613f15c63754dc376 (diff)
ALSA: hda - Make the inv dmic handling for Realtek use generic parser
From what I can see, the generic parser is now good enough to handle Realtek's inverted dmic handling, so let's remove the special handling and use the generic parser instead. Signed-off-by: David Henningsson <david.henningsson@canonical.com> 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.c158
1 files changed, 8 insertions, 150 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 82ea50ec978f..69d1236365e0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -90,11 +90,6 @@ struct alc_spec {
90 struct alc_customize_define cdefine; 90 struct alc_customize_define cdefine;
91 unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ 91 unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
92 92
93 /* inverted dmic fix */
94 unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */
95 unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
96 hda_nid_t inv_dmic_pin;
97
98 /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ 93 /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
99 int mute_led_polarity; 94 int mute_led_polarity;
100 hda_nid_t mute_led_nid; 95 hda_nid_t mute_led_nid;
@@ -625,147 +620,12 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
625/* 620/*
626 */ 621 */
627 622
628static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx) 623static void alc_fixup_inv_dmic(struct hda_codec *codec,
629{ 624 const struct hda_fixup *fix, int action)
630 struct hda_gen_spec *spec = codec->spec;
631 if (spec->dyn_adc_switch)
632 adc_idx = spec->dyn_adc_idx[imux_idx];
633 return spec->adc_nids[adc_idx];
634}
635
636static void alc_inv_dmic_sync_adc(struct hda_codec *codec, int adc_idx)
637{
638 struct alc_spec *spec = codec->spec;
639 struct hda_input_mux *imux = &spec->gen.input_mux;
640 struct nid_path *path;
641 hda_nid_t nid;
642 int i, dir, parm;
643 unsigned int val;
644
645 for (i = 0; i < imux->num_items; i++) {
646 if (spec->gen.imux_pins[i] == spec->inv_dmic_pin)
647 break;
648 }
649 if (i >= imux->num_items)
650 return;
651
652 path = snd_hda_get_nid_path(codec, spec->inv_dmic_pin,
653 get_adc_nid(codec, adc_idx, i));
654 val = path->ctls[NID_PATH_MUTE_CTL];
655 if (!val)
656 return;
657 nid = get_amp_nid_(val);
658 dir = get_amp_direction_(val);
659 parm = AC_AMP_SET_RIGHT |
660 (dir == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT);
661
662 /* flush all cached amps at first */
663 snd_hda_codec_flush_cache(codec);
664
665 /* we care only right channel */
666 val = snd_hda_codec_amp_read(codec, nid, 1, dir, 0);
667 if (val & 0x80) /* if already muted, we don't need to touch */
668 return;
669 val |= 0x80;
670 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
671 parm | val);
672}
673
674/*
675 * Inverted digital-mic handling
676 *
677 * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch"
678 * gives the additional mute only to the right channel of the digital mic
679 * capture stream. This is a workaround for avoiding the almost silence
680 * by summing the stereo stream from some (known to be ForteMedia)
681 * digital mic unit.
682 *
683 * The logic is to call alc_inv_dmic_sync() after each action (possibly)
684 * modifying ADC amp. When the mute flag is set, it mutes the R-channel
685 * without caching so that the cache can still keep the original value.
686 * The cached value is then restored when the flag is set off or any other
687 * than d-mic is used as the current input source.
688 */
689static void alc_inv_dmic_sync(struct hda_codec *codec, bool force)
690{
691 struct alc_spec *spec = codec->spec;
692 int src, nums;
693
694 if (!spec->inv_dmic_fixup)
695 return;
696 if (!spec->inv_dmic_muted && !force)
697 return;
698 nums = spec->gen.dyn_adc_switch ? 1 : spec->gen.num_adc_nids;
699 for (src = 0; src < nums; src++) {
700 bool dmic_fixup = false;
701
702 if (spec->inv_dmic_muted &&
703 spec->gen.imux_pins[spec->gen.cur_mux[src]] == spec->inv_dmic_pin)
704 dmic_fixup = true;
705 if (!dmic_fixup && !force)
706 continue;
707 alc_inv_dmic_sync_adc(codec, src);
708 }
709}
710
711static void alc_inv_dmic_hook(struct hda_codec *codec,
712 struct snd_kcontrol *kcontrol,
713 struct snd_ctl_elem_value *ucontrol)
714{
715 alc_inv_dmic_sync(codec, false);
716}
717
718static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol,
719 struct snd_ctl_elem_value *ucontrol)
720{
721 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
722 struct alc_spec *spec = codec->spec;
723
724 ucontrol->value.integer.value[0] = !spec->inv_dmic_muted;
725 return 0;
726}
727
728static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol,
729 struct snd_ctl_elem_value *ucontrol)
730{
731 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
732 struct alc_spec *spec = codec->spec;
733 unsigned int val = !ucontrol->value.integer.value[0];
734
735 if (val == spec->inv_dmic_muted)
736 return 0;
737 spec->inv_dmic_muted = val;
738 alc_inv_dmic_sync(codec, true);
739 return 0;
740}
741
742static const struct snd_kcontrol_new alc_inv_dmic_sw = {
743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
744 .name = "Inverted Internal Mic Capture Switch",
745 .info = snd_ctl_boolean_mono_info,
746 .get = alc_inv_dmic_sw_get,
747 .put = alc_inv_dmic_sw_put,
748};
749
750static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid)
751{ 625{
752 struct alc_spec *spec = codec->spec; 626 struct alc_spec *spec = codec->spec;
753 627
754 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &alc_inv_dmic_sw)) 628 spec->gen.inv_dmic_split = 1;
755 return -ENOMEM;
756 spec->inv_dmic_fixup = 1;
757 spec->inv_dmic_muted = 0;
758 spec->inv_dmic_pin = nid;
759 spec->gen.cap_sync_hook = alc_inv_dmic_hook;
760 return 0;
761}
762
763/* typically the digital mic is put at node 0x12 */
764static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec,
765 const struct hda_fixup *fix, int action)
766{
767 if (action == HDA_FIXUP_ACT_PROBE)
768 alc_add_inv_dmic_mixer(codec, 0x12);
769} 629}
770 630
771 631
@@ -874,7 +734,6 @@ static int alc_resume(struct hda_codec *codec)
874 codec->patch_ops.init(codec); 734 codec->patch_ops.init(codec);
875 snd_hda_codec_resume_amp(codec); 735 snd_hda_codec_resume_amp(codec);
876 snd_hda_codec_resume_cache(codec); 736 snd_hda_codec_resume_cache(codec);
877 alc_inv_dmic_sync(codec, true);
878 hda_call_check_power_status(codec, 0x01); 737 hda_call_check_power_status(codec, 0x01);
879 return 0; 738 return 0;
880} 739}
@@ -2217,7 +2076,7 @@ static const struct hda_fixup alc882_fixups[] = {
2217 }, 2076 },
2218 [ALC882_FIXUP_INV_DMIC] = { 2077 [ALC882_FIXUP_INV_DMIC] = {
2219 .type = HDA_FIXUP_FUNC, 2078 .type = HDA_FIXUP_FUNC,
2220 .v.func = alc_fixup_inv_dmic_0x12, 2079 .v.func = alc_fixup_inv_dmic,
2221 }, 2080 },
2222 [ALC882_FIXUP_NO_PRIMARY_HP] = { 2081 [ALC882_FIXUP_NO_PRIMARY_HP] = {
2223 .type = HDA_FIXUP_FUNC, 2082 .type = HDA_FIXUP_FUNC,
@@ -2468,7 +2327,7 @@ static const struct hda_fixup alc262_fixups[] = {
2468 }, 2327 },
2469 [ALC262_FIXUP_INV_DMIC] = { 2328 [ALC262_FIXUP_INV_DMIC] = {
2470 .type = HDA_FIXUP_FUNC, 2329 .type = HDA_FIXUP_FUNC,
2471 .v.func = alc_fixup_inv_dmic_0x12, 2330 .v.func = alc_fixup_inv_dmic,
2472 }, 2331 },
2473 [ALC262_FIXUP_INTEL_BAYLEYBAY] = { 2332 [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
2474 .type = HDA_FIXUP_FUNC, 2333 .type = HDA_FIXUP_FUNC,
@@ -2581,7 +2440,7 @@ enum {
2581static const struct hda_fixup alc268_fixups[] = { 2440static const struct hda_fixup alc268_fixups[] = {
2582 [ALC268_FIXUP_INV_DMIC] = { 2441 [ALC268_FIXUP_INV_DMIC] = {
2583 .type = HDA_FIXUP_FUNC, 2442 .type = HDA_FIXUP_FUNC,
2584 .v.func = alc_fixup_inv_dmic_0x12, 2443 .v.func = alc_fixup_inv_dmic,
2585 }, 2444 },
2586 [ALC268_FIXUP_HP_EAPD] = { 2445 [ALC268_FIXUP_HP_EAPD] = {
2587 .type = HDA_FIXUP_VERBS, 2446 .type = HDA_FIXUP_VERBS,
@@ -3167,7 +3026,6 @@ static int alc269_resume(struct hda_codec *codec)
3167 3026
3168 snd_hda_codec_resume_amp(codec); 3027 snd_hda_codec_resume_amp(codec);
3169 snd_hda_codec_resume_cache(codec); 3028 snd_hda_codec_resume_cache(codec);
3170 alc_inv_dmic_sync(codec, true);
3171 hda_call_check_power_status(codec, 0x01); 3029 hda_call_check_power_status(codec, 0x01);
3172 3030
3173 /* on some machine, the BIOS will clear the codec gpio data when enter 3031 /* on some machine, the BIOS will clear the codec gpio data when enter
@@ -4520,7 +4378,7 @@ static const struct hda_fixup alc269_fixups[] = {
4520 }, 4378 },
4521 [ALC269_FIXUP_INV_DMIC] = { 4379 [ALC269_FIXUP_INV_DMIC] = {
4522 .type = HDA_FIXUP_FUNC, 4380 .type = HDA_FIXUP_FUNC,
4523 .v.func = alc_fixup_inv_dmic_0x12, 4381 .v.func = alc_fixup_inv_dmic,
4524 }, 4382 },
4525 [ALC269_FIXUP_NO_SHUTUP] = { 4383 [ALC269_FIXUP_NO_SHUTUP] = {
4526 .type = HDA_FIXUP_FUNC, 4384 .type = HDA_FIXUP_FUNC,
@@ -5980,7 +5838,7 @@ static const struct hda_fixup alc662_fixups[] = {
5980 }, 5838 },
5981 [ALC662_FIXUP_INV_DMIC] = { 5839 [ALC662_FIXUP_INV_DMIC] = {
5982 .type = HDA_FIXUP_FUNC, 5840 .type = HDA_FIXUP_FUNC,
5983 .v.func = alc_fixup_inv_dmic_0x12, 5841 .v.func = alc_fixup_inv_dmic,
5984 }, 5842 },
5985 [ALC668_FIXUP_DELL_XPS13] = { 5843 [ALC668_FIXUP_DELL_XPS13] = {
5986 .type = HDA_FIXUP_FUNC, 5844 .type = HDA_FIXUP_FUNC,