Commit 29adc4b9e6a96571e83353cdcb69628871984935
Committed by
Takashi Iwai
1 parent
954df2a968
Exists in
master
and in
20 other branches
ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event
For less duplication of code between codecs, and to make it easier in the future to improve code for all codecs simultaneously. Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 3 changed files with 49 additions and 101 deletions Side-by-side Diff
sound/pci/hda/patch_conexant.c
... | ... | @@ -3402,7 +3402,7 @@ |
3402 | 3402 | do_automute(codec, cfg->line_outs, cfg->line_out_pins, on); |
3403 | 3403 | } |
3404 | 3404 | |
3405 | -static void cx_auto_hp_automute(struct hda_codec *codec) | |
3405 | +static void cx_auto_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
3406 | 3406 | { |
3407 | 3407 | struct conexant_spec *spec = codec->spec; |
3408 | 3408 | struct auto_pin_cfg *cfg = &spec->autocfg; |
... | ... | @@ -3413,7 +3413,7 @@ |
3413 | 3413 | cx_auto_update_speakers(codec); |
3414 | 3414 | } |
3415 | 3415 | |
3416 | -static void cx_auto_line_automute(struct hda_codec *codec) | |
3416 | +static void cx_auto_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
3417 | 3417 | { |
3418 | 3418 | struct conexant_spec *spec = codec->spec; |
3419 | 3419 | struct auto_pin_cfg *cfg = &spec->autocfg; |
... | ... | @@ -3664,7 +3664,7 @@ |
3664 | 3664 | } |
3665 | 3665 | |
3666 | 3666 | /* automatic switch internal and external mic */ |
3667 | -static void cx_auto_automic(struct hda_codec *codec) | |
3667 | +static void cx_auto_automic(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
3668 | 3668 | { |
3669 | 3669 | struct conexant_spec *spec = codec->spec; |
3670 | 3670 | |
... | ... | @@ -3675,22 +3675,6 @@ |
3675 | 3675 | select_automic(codec, spec->auto_mic_int, false); |
3676 | 3676 | } |
3677 | 3677 | |
3678 | -static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | |
3679 | -{ | |
3680 | - switch (snd_hda_jack_get_action(codec, res >> 26)) { | |
3681 | - case CONEXANT_HP_EVENT: | |
3682 | - cx_auto_hp_automute(codec); | |
3683 | - break; | |
3684 | - case CONEXANT_LINE_EVENT: | |
3685 | - cx_auto_line_automute(codec); | |
3686 | - break; | |
3687 | - case CONEXANT_MIC_EVENT: | |
3688 | - cx_auto_automic(codec); | |
3689 | - break; | |
3690 | - } | |
3691 | - snd_hda_jack_report_sync(codec); | |
3692 | -} | |
3693 | - | |
3694 | 3678 | /* check whether the pin config is suitable for auto-mic switching; |
3695 | 3679 | * auto-mic is enabled only when one int-mic and one ext- and/or |
3696 | 3680 | * one dock-mic exist |
3697 | 3681 | |
... | ... | @@ -3900,11 +3884,12 @@ |
3900 | 3884 | } |
3901 | 3885 | |
3902 | 3886 | static void enable_unsol_pins(struct hda_codec *codec, int num_pins, |
3903 | - hda_nid_t *pins, unsigned int action) | |
3887 | + hda_nid_t *pins, unsigned int action, | |
3888 | + hda_jack_callback cb) | |
3904 | 3889 | { |
3905 | 3890 | int i; |
3906 | 3891 | for (i = 0; i < num_pins; i++) |
3907 | - snd_hda_jack_detect_enable(codec, pins[i], action); | |
3892 | + snd_hda_jack_detect_enable_callback(codec, pins[i], action, cb); | |
3908 | 3893 | } |
3909 | 3894 | |
3910 | 3895 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) |
3911 | 3896 | |
... | ... | @@ -3992,13 +3977,14 @@ |
3992 | 3977 | } |
3993 | 3978 | if (spec->auto_mute) { |
3994 | 3979 | enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins, |
3995 | - CONEXANT_HP_EVENT); | |
3980 | + CONEXANT_HP_EVENT, cx_auto_hp_automute); | |
3996 | 3981 | spec->hp_present = detect_jacks(codec, cfg->hp_outs, |
3997 | 3982 | cfg->hp_pins); |
3998 | 3983 | if (spec->detect_line) { |
3999 | 3984 | enable_unsol_pins(codec, cfg->line_outs, |
4000 | 3985 | cfg->line_out_pins, |
4001 | - CONEXANT_LINE_EVENT); | |
3986 | + CONEXANT_LINE_EVENT, | |
3987 | + cx_auto_line_automute); | |
4002 | 3988 | spec->line_present = |
4003 | 3989 | detect_jacks(codec, cfg->line_outs, |
4004 | 3990 | cfg->line_out_pins); |
4005 | 3991 | |
4006 | 3992 | |
4007 | 3993 | |
4008 | 3994 | |
... | ... | @@ -4039,16 +4025,16 @@ |
4039 | 4025 | |
4040 | 4026 | if (spec->auto_mic) { |
4041 | 4027 | if (spec->auto_mic_ext >= 0) { |
4042 | - snd_hda_jack_detect_enable(codec, | |
4028 | + snd_hda_jack_detect_enable_callback(codec, | |
4043 | 4029 | cfg->inputs[spec->auto_mic_ext].pin, |
4044 | - CONEXANT_MIC_EVENT); | |
4030 | + CONEXANT_MIC_EVENT, cx_auto_automic); | |
4045 | 4031 | } |
4046 | 4032 | if (spec->auto_mic_dock >= 0) { |
4047 | - snd_hda_jack_detect_enable(codec, | |
4033 | + snd_hda_jack_detect_enable_callback(codec, | |
4048 | 4034 | cfg->inputs[spec->auto_mic_dock].pin, |
4049 | - CONEXANT_MIC_EVENT); | |
4035 | + CONEXANT_MIC_EVENT, cx_auto_automic); | |
4050 | 4036 | } |
4051 | - cx_auto_automic(codec); | |
4037 | + cx_auto_automic(codec, NULL); | |
4052 | 4038 | } else { |
4053 | 4039 | select_input_connection(codec, spec->imux_info[0].adc, |
4054 | 4040 | spec->imux_info[0].pin); |
... | ... | @@ -4406,7 +4392,7 @@ |
4406 | 4392 | .build_pcms = conexant_build_pcms, |
4407 | 4393 | .init = cx_auto_init, |
4408 | 4394 | .free = conexant_free, |
4409 | - .unsol_event = cx_auto_unsol_event, | |
4395 | + .unsol_event = snd_hda_jack_unsol_event, | |
4410 | 4396 | #ifdef CONFIG_PM |
4411 | 4397 | .suspend = conexant_suspend, |
4412 | 4398 | #endif |
sound/pci/hda/patch_realtek.c
... | ... | @@ -594,7 +594,7 @@ |
594 | 594 | } |
595 | 595 | |
596 | 596 | /* standard HP-automute helper */ |
597 | -static void alc_hp_automute(struct hda_codec *codec) | |
597 | +static void alc_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
598 | 598 | { |
599 | 599 | struct alc_spec *spec = codec->spec; |
600 | 600 | |
... | ... | @@ -607,7 +607,7 @@ |
607 | 607 | } |
608 | 608 | |
609 | 609 | /* standard line-out-automute helper */ |
610 | -static void alc_line_automute(struct hda_codec *codec) | |
610 | +static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
611 | 611 | { |
612 | 612 | struct alc_spec *spec = codec->spec; |
613 | 613 | |
... | ... | @@ -627,7 +627,7 @@ |
627 | 627 | snd_hda_get_conn_index(codec, mux, nid, 0) |
628 | 628 | |
629 | 629 | /* standard mic auto-switch helper */ |
630 | -static void alc_mic_automute(struct hda_codec *codec) | |
630 | +static void alc_mic_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
631 | 631 | { |
632 | 632 | struct alc_spec *spec = codec->spec; |
633 | 633 | hda_nid_t *pins = spec->imux_pins; |
634 | 634 | |
... | ... | @@ -648,25 +648,8 @@ |
648 | 648 | alc_mux_select(codec, 0, spec->int_mic_idx, false); |
649 | 649 | } |
650 | 650 | |
651 | -/* handle the specified unsol action (ALC_XXX_EVENT) */ | |
652 | -static void alc_exec_unsol_event(struct hda_codec *codec, int action) | |
653 | -{ | |
654 | - switch (action) { | |
655 | - case ALC_HP_EVENT: | |
656 | - alc_hp_automute(codec); | |
657 | - break; | |
658 | - case ALC_FRONT_EVENT: | |
659 | - alc_line_automute(codec); | |
660 | - break; | |
661 | - case ALC_MIC_EVENT: | |
662 | - alc_mic_automute(codec); | |
663 | - break; | |
664 | - } | |
665 | - snd_hda_jack_report_sync(codec); | |
666 | -} | |
667 | - | |
668 | 651 | /* update the master volume per volume-knob's unsol event */ |
669 | -static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | |
652 | +static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack) | |
670 | 653 | { |
671 | 654 | unsigned int val; |
672 | 655 | struct snd_kcontrol *kctl; |
... | ... | @@ -678,7 +661,7 @@ |
678 | 661 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); |
679 | 662 | if (!uctl) |
680 | 663 | return; |
681 | - val = snd_hda_codec_read(codec, nid, 0, | |
664 | + val = snd_hda_codec_read(codec, jack->nid, 0, | |
682 | 665 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); |
683 | 666 | val &= HDA_AMP_VOLMASK; |
684 | 667 | uctl->value.integer.value[0] = val; |
685 | 668 | |
686 | 669 | |
... | ... | @@ -687,37 +670,19 @@ |
687 | 670 | kfree(uctl); |
688 | 671 | } |
689 | 672 | |
690 | -/* unsolicited event for HP jack sensing */ | |
691 | -static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |
673 | +static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) | |
692 | 674 | { |
693 | - int action; | |
694 | - | |
695 | - if (codec->vendor_id == 0x10ec0880) | |
696 | - res >>= 28; | |
697 | - else | |
698 | - res >>= 26; | |
699 | - action = snd_hda_jack_get_action(codec, res); | |
700 | - if (action == ALC_DCVOL_EVENT) { | |
701 | - /* Execute the dc-vol event here as it requires the NID | |
702 | - * but we don't pass NID to alc_exec_unsol_event(). | |
703 | - * Once when we convert all static quirks to the auto-parser, | |
704 | - * this can be integerated into there. | |
705 | - */ | |
706 | - struct hda_jack_tbl *jack; | |
707 | - jack = snd_hda_jack_tbl_get_from_tag(codec, res); | |
708 | - if (jack) | |
709 | - alc_update_knob_master(codec, jack->nid); | |
710 | - return; | |
711 | - } | |
712 | - alc_exec_unsol_event(codec, action); | |
675 | + /* For some reason, the res given from ALC880 is broken. | |
676 | + Here we adjust it properly. */ | |
677 | + snd_hda_jack_unsol_event(codec, res >> 2); | |
713 | 678 | } |
714 | 679 | |
715 | 680 | /* call init functions of standard auto-mute helpers */ |
716 | 681 | static void alc_inithook(struct hda_codec *codec) |
717 | 682 | { |
718 | - alc_hp_automute(codec); | |
719 | - alc_line_automute(codec); | |
720 | - alc_mic_automute(codec); | |
683 | + alc_hp_automute(codec, NULL); | |
684 | + alc_line_automute(codec, NULL); | |
685 | + alc_mic_automute(codec, NULL); | |
721 | 686 | } |
722 | 687 | |
723 | 688 | /* additional initialization for ALC888 variants */ |
... | ... | @@ -999,7 +964,8 @@ |
999 | 964 | continue; |
1000 | 965 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", |
1001 | 966 | nid); |
1002 | - snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT); | |
967 | + snd_hda_jack_detect_enable_callback(codec, nid, ALC_HP_EVENT, | |
968 | + alc_hp_automute); | |
1003 | 969 | spec->detect_hp = 1; |
1004 | 970 | } |
1005 | 971 | |
1006 | 972 | |
... | ... | @@ -1011,10 +977,10 @@ |
1011 | 977 | continue; |
1012 | 978 | snd_printdd("realtek: Enable Line-Out " |
1013 | 979 | "auto-muting on NID 0x%x\n", nid); |
1014 | - snd_hda_jack_detect_enable(codec, nid, | |
1015 | - ALC_FRONT_EVENT); | |
980 | + snd_hda_jack_detect_enable_callback(codec, nid, ALC_FRONT_EVENT, | |
981 | + alc_line_automute); | |
1016 | 982 | spec->detect_lo = 1; |
1017 | - } | |
983 | + } | |
1018 | 984 | spec->automute_lo_possible = spec->detect_hp; |
1019 | 985 | } |
1020 | 986 | |
1021 | 987 | |
... | ... | @@ -1110,10 +1076,12 @@ |
1110 | 1076 | return false; /* no corresponding imux */ |
1111 | 1077 | } |
1112 | 1078 | |
1113 | - snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT); | |
1079 | + snd_hda_jack_detect_enable_callback(codec, spec->ext_mic_pin, | |
1080 | + ALC_MIC_EVENT, alc_mic_automute); | |
1114 | 1081 | if (spec->dock_mic_pin) |
1115 | - snd_hda_jack_detect_enable(codec, spec->dock_mic_pin, | |
1116 | - ALC_MIC_EVENT); | |
1082 | + snd_hda_jack_detect_enable_callback(codec, spec->dock_mic_pin, | |
1083 | + ALC_MIC_EVENT, | |
1084 | + alc_mic_automute); | |
1117 | 1085 | |
1118 | 1086 | spec->auto_mic_valid_imux = 1; |
1119 | 1087 | spec->auto_mic = 1; |
... | ... | @@ -2473,7 +2441,7 @@ |
2473 | 2441 | .build_pcms = alc_build_pcms, |
2474 | 2442 | .init = alc_init, |
2475 | 2443 | .free = alc_free, |
2476 | - .unsol_event = alc_unsol_event, | |
2444 | + .unsol_event = snd_hda_jack_unsol_event, | |
2477 | 2445 | #ifdef CONFIG_PM |
2478 | 2446 | .resume = alc_resume, |
2479 | 2447 | #endif |
... | ... | @@ -2484,6 +2452,7 @@ |
2484 | 2452 | .reboot_notify = alc_shutup, |
2485 | 2453 | }; |
2486 | 2454 | |
2455 | + | |
2487 | 2456 | /* replace the codec chip_name with the given string */ |
2488 | 2457 | static int alc_codec_rename(struct hda_codec *codec, const char *name) |
2489 | 2458 | { |
... | ... | @@ -4447,7 +4416,7 @@ |
4447 | 4416 | const struct alc_fixup *fix, int action) |
4448 | 4417 | { |
4449 | 4418 | if (action == ALC_FIXUP_ACT_PROBE) |
4450 | - snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); | |
4419 | + snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master); | |
4451 | 4420 | } |
4452 | 4421 | |
4453 | 4422 | static const struct alc_fixup alc880_fixups[] = { |
4454 | 4423 | |
... | ... | @@ -4812,7 +4781,9 @@ |
4812 | 4781 | } |
4813 | 4782 | |
4814 | 4783 | codec->patch_ops = alc_patch_ops; |
4784 | + codec->patch_ops.unsol_event = alc880_unsol_event; | |
4815 | 4785 | |
4786 | + | |
4816 | 4787 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4817 | 4788 | |
4818 | 4789 | return 0; |
... | ... | @@ -4866,7 +4837,8 @@ |
4866 | 4837 | spec->detect_hp = 1; |
4867 | 4838 | spec->automute_speaker = 1; |
4868 | 4839 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ |
4869 | - snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); | |
4840 | + snd_hda_jack_detect_enable_callback(codec, 0x0f, ALC_HP_EVENT, | |
4841 | + alc_hp_automute); | |
4870 | 4842 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); |
4871 | 4843 | } |
4872 | 4844 | } |
sound/pci/hda/patch_sigmatel.c
... | ... | @@ -4212,6 +4212,9 @@ |
4212 | 4212 | return 0; |
4213 | 4213 | } |
4214 | 4214 | |
4215 | +static void handle_unsol_event(struct hda_codec *codec, | |
4216 | + struct hda_jack_tbl *event); | |
4217 | + | |
4215 | 4218 | /* check if given nid is a valid pin and no other events are assigned |
4216 | 4219 | * to it. If OK, assign the event, set the unsol flag, and returns 1. |
4217 | 4220 | * Otherwise, returns zero. |
... | ... | @@ -4229,6 +4232,7 @@ |
4229 | 4232 | if (event->action && event->action != type) |
4230 | 4233 | return 0; |
4231 | 4234 | event->action = type; |
4235 | + event->callback = handle_unsol_event; | |
4232 | 4236 | snd_hda_jack_detect_enable(codec, nid, 0); |
4233 | 4237 | return 1; |
4234 | 4238 | } |
... | ... | @@ -4867,20 +4871,6 @@ |
4867 | 4871 | handle_unsol_event(codec, event); |
4868 | 4872 | } |
4869 | 4873 | |
4870 | -static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |
4871 | -{ | |
4872 | - struct hda_jack_tbl *event; | |
4873 | - int tag; | |
4874 | - | |
4875 | - tag = (res >> 26) & 0x7f; | |
4876 | - event = snd_hda_jack_tbl_get_from_tag(codec, tag); | |
4877 | - if (!event) | |
4878 | - return; | |
4879 | - event->jack_dirty = 1; | |
4880 | - handle_unsol_event(codec, event); | |
4881 | - snd_hda_jack_report_sync(codec); | |
4882 | -} | |
4883 | - | |
4884 | 4874 | static int hp_blike_system(u32 subsystem_id); |
4885 | 4875 | |
4886 | 4876 | static void set_hp_led_gpio(struct hda_codec *codec) |
... | ... | @@ -5131,7 +5121,7 @@ |
5131 | 5121 | .build_pcms = stac92xx_build_pcms, |
5132 | 5122 | .init = stac92xx_init, |
5133 | 5123 | .free = stac92xx_free, |
5134 | - .unsol_event = stac92xx_unsol_event, | |
5124 | + .unsol_event = snd_hda_jack_unsol_event, | |
5135 | 5125 | #ifdef CONFIG_PM |
5136 | 5126 | .suspend = stac92xx_suspend, |
5137 | 5127 | .resume = stac92xx_resume, |