Commit 29adc4b9e6a96571e83353cdcb69628871984935

Authored by David Henningsson
Committed by Takashi Iwai
1 parent 954df2a968

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,