aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-01-08 05:44:21 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-08 10:16:51 -0500
commitb317b032d2dcb5e518cc9630cc6f1c7c24afedfc (patch)
tree91c4725440de1d3fad2b8d0cf6c52ef3d863700f /sound/pci
parent43a8e50a46a4e1dd1451e4a4ffa1f7695fb7d287 (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.c100
-rw-r--r--sound/pci/hda/patch_realtek.c93
-rw-r--r--sound/pci/hda/thinkpad_helper.c99
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
3248static int (*led_set_func)(int, bool);
3249
3250static 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
3258static 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
3269static 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
3281static 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
3293static 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
3333static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
3334 const struct hda_fixup *fix, int action)
3335{
3336}
3337
3338#endif
3339 3245
3340static void cxt_fixup_stereo_dmic(struct hda_codec *codec, 3246static 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
3789static int (*led_set_func)(int, bool);
3790
3791static 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
3799static 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
3810static 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
3816static 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
3828static 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
3867static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
3868 const struct hda_fixup *fix, int action)
3869{
3870}
3871
3872#endif
3873 3786
3874enum { 3787enum {
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
10static int (*led_set_func)(int, bool);
11
12static 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
20static 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
31static 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
43static 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
55static 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
94static 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 */