aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c100
1 files changed, 3 insertions, 97 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 3fbf2883e06e..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 <acpi/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