drm_privacy_screen_x86.c (2487B)
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright (C) 2020 Red Hat, Inc. 4 * 5 * Authors: 6 * Hans de Goede <hdegoede@redhat.com> 7 */ 8 9#include <linux/acpi.h> 10#include <drm/drm_privacy_screen_machine.h> 11 12#ifdef CONFIG_X86 13static struct drm_privacy_screen_lookup arch_lookup; 14 15struct arch_init_data { 16 struct drm_privacy_screen_lookup lookup; 17 bool (*detect)(void); 18}; 19 20#if IS_ENABLED(CONFIG_THINKPAD_ACPI) 21static acpi_status __init acpi_set_handle(acpi_handle handle, u32 level, 22 void *context, void **return_value) 23{ 24 *(acpi_handle *)return_value = handle; 25 return AE_CTRL_TERMINATE; 26} 27 28static bool __init detect_thinkpad_privacy_screen(void) 29{ 30 union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; 31 struct acpi_object_list args = { .count = 1, .pointer = &obj, }; 32 acpi_handle ec_handle = NULL; 33 unsigned long long output; 34 acpi_status status; 35 36 if (acpi_disabled) 37 return false; 38 39 /* Get embedded-controller handle */ 40 status = acpi_get_devices("PNP0C09", acpi_set_handle, NULL, &ec_handle); 41 if (ACPI_FAILURE(status) || !ec_handle) 42 return false; 43 44 /* And call the privacy-screen get-status method */ 45 status = acpi_evaluate_integer(ec_handle, "HKEY.GSSS", &args, &output); 46 if (ACPI_FAILURE(status)) 47 return false; 48 49 return (output & 0x10000) ? true : false; 50} 51#endif 52 53#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN) 54static bool __init detect_chromeos_privacy_screen(void) 55{ 56 return acpi_dev_present("GOOG0010", NULL, -1); 57} 58#endif 59 60static const struct arch_init_data arch_init_data[] __initconst = { 61#if IS_ENABLED(CONFIG_THINKPAD_ACPI) 62 { 63 .lookup = { 64 .dev_id = NULL, 65 .con_id = NULL, 66 .provider = "privacy_screen-thinkpad_acpi", 67 }, 68 .detect = detect_thinkpad_privacy_screen, 69 }, 70#endif 71#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN) 72 { 73 .lookup = { 74 .dev_id = NULL, 75 .con_id = NULL, 76 .provider = "privacy_screen-GOOG0010:00", 77 }, 78 .detect = detect_chromeos_privacy_screen, 79 }, 80#endif 81}; 82 83void __init drm_privacy_screen_lookup_init(void) 84{ 85 int i; 86 87 for (i = 0; i < ARRAY_SIZE(arch_init_data); i++) { 88 if (!arch_init_data[i].detect()) 89 continue; 90 91 pr_info("Found '%s' privacy-screen provider\n", 92 arch_init_data[i].lookup.provider); 93 94 /* Make a copy because arch_init_data is __initconst */ 95 arch_lookup = arch_init_data[i].lookup; 96 drm_privacy_screen_lookup_add(&arch_lookup); 97 break; 98 } 99} 100 101void drm_privacy_screen_lookup_exit(void) 102{ 103 if (arch_lookup.provider) 104 drm_privacy_screen_lookup_remove(&arch_lookup); 105} 106#endif /* ifdef CONFIG_X86 */