diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-01-08 05:44:21 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-01-08 10:16:51 -0500 |
commit | b317b032d2dcb5e518cc9630cc6f1c7c24afedfc (patch) | |
tree | 91c4725440de1d3fad2b8d0cf6c52ef3d863700f /sound/pci | |
parent | 43a8e50a46a4e1dd1451e4a4ffa1f7695fb7d287 (diff) |
ALSA: hda - Split Thinkpad ACPI-related code
Both patch_realtek.c and patch_conexant.c contain the fairy same code
snippet for supporting Thinkpad ACPI LED controls. Split them into
thinkpad_helper.c and include it from both places. Although this
isn't the best approach from the code size POV, the probability for
coexistence of both Realtek and Conexant codecs on a single machine is
pretty low, thus it'll end up with less memory footprint than
splitting to yet another module.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 100 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 93 | ||||
-rw-r--r-- | sound/pci/hda/thinkpad_helper.c | 99 |
3 files changed, 105 insertions, 187 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6df4c35b48c5..4e0ec146553d 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3240,102 +3240,8 @@ enum { | |||
3240 | CXT_FIXUP_THINKPAD_ACPI, | 3240 | CXT_FIXUP_THINKPAD_ACPI, |
3241 | }; | 3241 | }; |
3242 | 3242 | ||
3243 | #if IS_ENABLED(CONFIG_THINKPAD_ACPI) | 3243 | /* for hda_fixup_thinkpad_acpi() */ |
3244 | 3244 | #include "thinkpad_helper.c" | |
3245 | #include <linux/thinkpad_acpi.h> | ||
3246 | #include <linux/acpi.h> | ||
3247 | |||
3248 | static int (*led_set_func)(int, bool); | ||
3249 | |||
3250 | static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context, | ||
3251 | void **rv) | ||
3252 | { | ||
3253 | bool *found = context; | ||
3254 | *found = true; | ||
3255 | return AE_OK; | ||
3256 | } | ||
3257 | |||
3258 | static bool is_thinkpad(struct hda_codec *codec) | ||
3259 | { | ||
3260 | bool found = false; | ||
3261 | if (codec->subsystem_id >> 16 != 0x17aa) | ||
3262 | return false; | ||
3263 | if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found) | ||
3264 | return true; | ||
3265 | found = false; | ||
3266 | return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found; | ||
3267 | } | ||
3268 | |||
3269 | static void update_tpacpi_mute_led(void *private_data, int enabled) | ||
3270 | { | ||
3271 | struct hda_codec *codec = private_data; | ||
3272 | struct conexant_spec *spec = codec->spec; | ||
3273 | |||
3274 | if (spec->dynamic_eapd) | ||
3275 | cx_auto_vmaster_hook(private_data, enabled); | ||
3276 | |||
3277 | if (led_set_func) | ||
3278 | led_set_func(TPACPI_LED_MUTE, !enabled); | ||
3279 | } | ||
3280 | |||
3281 | static void update_tpacpi_micmute_led(struct hda_codec *codec, | ||
3282 | struct snd_ctl_elem_value *ucontrol) | ||
3283 | { | ||
3284 | if (!ucontrol || !led_set_func) | ||
3285 | return; | ||
3286 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
3287 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
3288 | bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]; | ||
3289 | led_set_func(TPACPI_LED_MICMUTE, !val); | ||
3290 | } | ||
3291 | } | ||
3292 | |||
3293 | static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3294 | const struct hda_fixup *fix, int action) | ||
3295 | { | ||
3296 | struct conexant_spec *spec = codec->spec; | ||
3297 | |||
3298 | bool removefunc = false; | ||
3299 | |||
3300 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
3301 | if (!is_thinkpad(codec)) | ||
3302 | return; | ||
3303 | if (!led_set_func) | ||
3304 | led_set_func = symbol_request(tpacpi_led_set); | ||
3305 | if (!led_set_func) { | ||
3306 | snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); | ||
3307 | return; | ||
3308 | } | ||
3309 | |||
3310 | removefunc = true; | ||
3311 | if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { | ||
3312 | spec->gen.vmaster_mute.hook = update_tpacpi_mute_led; | ||
3313 | removefunc = false; | ||
3314 | } | ||
3315 | if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { | ||
3316 | if (spec->gen.num_adc_nids > 1) | ||
3317 | snd_printdd("Skipping micmute LED control due to several ADCs"); | ||
3318 | else { | ||
3319 | spec->gen.cap_sync_hook = update_tpacpi_micmute_led; | ||
3320 | removefunc = false; | ||
3321 | } | ||
3322 | } | ||
3323 | } | ||
3324 | |||
3325 | if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
3326 | symbol_put(tpacpi_led_set); | ||
3327 | led_set_func = NULL; | ||
3328 | } | ||
3329 | } | ||
3330 | |||
3331 | #else | ||
3332 | |||
3333 | static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3334 | const struct hda_fixup *fix, int action) | ||
3335 | { | ||
3336 | } | ||
3337 | |||
3338 | #endif | ||
3339 | 3245 | ||
3340 | static void cxt_fixup_stereo_dmic(struct hda_codec *codec, | 3246 | static void cxt_fixup_stereo_dmic(struct hda_codec *codec, |
3341 | const struct hda_fixup *fix, int action) | 3247 | const struct hda_fixup *fix, int action) |
@@ -3492,7 +3398,7 @@ static const struct hda_fixup cxt_fixups[] = { | |||
3492 | }, | 3398 | }, |
3493 | [CXT_FIXUP_THINKPAD_ACPI] = { | 3399 | [CXT_FIXUP_THINKPAD_ACPI] = { |
3494 | .type = HDA_FIXUP_FUNC, | 3400 | .type = HDA_FIXUP_FUNC, |
3495 | .v.func = cxt_fixup_thinkpad_acpi, | 3401 | .v.func = hda_fixup_thinkpad_acpi, |
3496 | }, | 3402 | }, |
3497 | }; | 3403 | }; |
3498 | 3404 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 74b496b0d179..d35cf3dc6711 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -3781,95 +3781,8 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec, | |||
3781 | } | 3781 | } |
3782 | } | 3782 | } |
3783 | 3783 | ||
3784 | #if IS_ENABLED(CONFIG_THINKPAD_ACPI) | 3784 | /* for hda_fixup_thinkpad_acpi() */ |
3785 | 3785 | #include "thinkpad_helper.c" | |
3786 | #include <linux/thinkpad_acpi.h> | ||
3787 | #include <linux/acpi.h> | ||
3788 | |||
3789 | static int (*led_set_func)(int, bool); | ||
3790 | |||
3791 | static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context, | ||
3792 | void **rv) | ||
3793 | { | ||
3794 | bool *found = context; | ||
3795 | *found = true; | ||
3796 | return AE_OK; | ||
3797 | } | ||
3798 | |||
3799 | static bool is_thinkpad(struct hda_codec *codec) | ||
3800 | { | ||
3801 | bool found = false; | ||
3802 | if (codec->subsystem_id >> 16 != 0x17aa) | ||
3803 | return false; | ||
3804 | if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found) | ||
3805 | return true; | ||
3806 | found = false; | ||
3807 | return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found; | ||
3808 | } | ||
3809 | |||
3810 | static void update_tpacpi_mute_led(void *private_data, int enabled) | ||
3811 | { | ||
3812 | if (led_set_func) | ||
3813 | led_set_func(TPACPI_LED_MUTE, !enabled); | ||
3814 | } | ||
3815 | |||
3816 | static void update_tpacpi_micmute_led(struct hda_codec *codec, | ||
3817 | struct snd_ctl_elem_value *ucontrol) | ||
3818 | { | ||
3819 | if (!ucontrol || !led_set_func) | ||
3820 | return; | ||
3821 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
3822 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
3823 | bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]; | ||
3824 | led_set_func(TPACPI_LED_MICMUTE, !val); | ||
3825 | } | ||
3826 | } | ||
3827 | |||
3828 | static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3829 | const struct hda_fixup *fix, int action) | ||
3830 | { | ||
3831 | struct alc_spec *spec = codec->spec; | ||
3832 | bool removefunc = false; | ||
3833 | |||
3834 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
3835 | if (!is_thinkpad(codec)) | ||
3836 | return; | ||
3837 | if (!led_set_func) | ||
3838 | led_set_func = symbol_request(tpacpi_led_set); | ||
3839 | if (!led_set_func) { | ||
3840 | snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); | ||
3841 | return; | ||
3842 | } | ||
3843 | |||
3844 | removefunc = true; | ||
3845 | if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { | ||
3846 | spec->gen.vmaster_mute.hook = update_tpacpi_mute_led; | ||
3847 | removefunc = false; | ||
3848 | } | ||
3849 | if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { | ||
3850 | if (spec->gen.num_adc_nids > 1) | ||
3851 | snd_printdd("Skipping micmute LED control due to several ADCs"); | ||
3852 | else { | ||
3853 | spec->gen.cap_sync_hook = update_tpacpi_micmute_led; | ||
3854 | removefunc = false; | ||
3855 | } | ||
3856 | } | ||
3857 | } | ||
3858 | |||
3859 | if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
3860 | symbol_put(tpacpi_led_set); | ||
3861 | led_set_func = NULL; | ||
3862 | } | ||
3863 | } | ||
3864 | |||
3865 | #else | ||
3866 | |||
3867 | static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3868 | const struct hda_fixup *fix, int action) | ||
3869 | { | ||
3870 | } | ||
3871 | |||
3872 | #endif | ||
3873 | 3786 | ||
3874 | enum { | 3787 | enum { |
3875 | ALC269_FIXUP_SONY_VAIO, | 3788 | ALC269_FIXUP_SONY_VAIO, |
@@ -4273,7 +4186,7 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4273 | }, | 4186 | }, |
4274 | [ALC269_FIXUP_THINKPAD_ACPI] = { | 4187 | [ALC269_FIXUP_THINKPAD_ACPI] = { |
4275 | .type = HDA_FIXUP_FUNC, | 4188 | .type = HDA_FIXUP_FUNC, |
4276 | .v.func = alc_fixup_thinkpad_acpi, | 4189 | .v.func = hda_fixup_thinkpad_acpi, |
4277 | }, | 4190 | }, |
4278 | [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = { | 4191 | [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = { |
4279 | .type = HDA_FIXUP_PINS, | 4192 | .type = HDA_FIXUP_PINS, |
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c new file mode 100644 index 000000000000..8492b8a3ce47 --- /dev/null +++ b/sound/pci/hda/thinkpad_helper.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* Helper functions for Thinkpad LED control; | ||
2 | * to be included from codec driver | ||
3 | */ | ||
4 | |||
5 | #if IS_ENABLED(CONFIG_THINKPAD_ACPI) | ||
6 | |||
7 | #include <linux/acpi.h> | ||
8 | #include <linux/thinkpad_acpi.h> | ||
9 | |||
10 | static int (*led_set_func)(int, bool); | ||
11 | |||
12 | static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context, | ||
13 | void **rv) | ||
14 | { | ||
15 | bool *found = context; | ||
16 | *found = true; | ||
17 | return AE_OK; | ||
18 | } | ||
19 | |||
20 | static bool is_thinkpad(struct hda_codec *codec) | ||
21 | { | ||
22 | bool found = false; | ||
23 | if (codec->subsystem_id >> 16 != 0x17aa) | ||
24 | return false; | ||
25 | if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found) | ||
26 | return true; | ||
27 | found = false; | ||
28 | return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found; | ||
29 | } | ||
30 | |||
31 | static void update_tpacpi_mute_led(void *private_data, int enabled) | ||
32 | { | ||
33 | struct hda_codec *codec = private_data; | ||
34 | struct hda_gen_spec *spec = codec->spec; | ||
35 | |||
36 | if (spec->vmaster_mute.hook) | ||
37 | spec->vmaster_mute.hook(private_data, enabled); | ||
38 | |||
39 | if (led_set_func) | ||
40 | led_set_func(TPACPI_LED_MUTE, !enabled); | ||
41 | } | ||
42 | |||
43 | static void update_tpacpi_micmute_led(struct hda_codec *codec, | ||
44 | struct snd_ctl_elem_value *ucontrol) | ||
45 | { | ||
46 | if (!ucontrol || !led_set_func) | ||
47 | return; | ||
48 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
49 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
50 | bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]; | ||
51 | led_set_func(TPACPI_LED_MICMUTE, !val); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
56 | const struct hda_fixup *fix, int action) | ||
57 | { | ||
58 | struct hda_gen_spec *spec = codec->spec; | ||
59 | bool removefunc = false; | ||
60 | |||
61 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
62 | if (!is_thinkpad(codec)) | ||
63 | return; | ||
64 | if (!led_set_func) | ||
65 | led_set_func = symbol_request(tpacpi_led_set); | ||
66 | if (!led_set_func) { | ||
67 | snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | removefunc = true; | ||
72 | if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { | ||
73 | spec->vmaster_mute.hook = update_tpacpi_mute_led; | ||
74 | removefunc = false; | ||
75 | } | ||
76 | if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { | ||
77 | if (spec->num_adc_nids > 1) | ||
78 | snd_printdd("Skipping micmute LED control due to several ADCs"); | ||
79 | else { | ||
80 | spec->cap_sync_hook = update_tpacpi_micmute_led; | ||
81 | removefunc = false; | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
87 | symbol_put(tpacpi_led_set); | ||
88 | led_set_func = NULL; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #else /* CONFIG_THINKPAD_ACPI */ | ||
93 | |||
94 | static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
95 | const struct hda_fixup *fix, int action) | ||
96 | { | ||
97 | } | ||
98 | |||
99 | #endif /* CONFIG_THINKPAD_ACPI */ | ||