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 13 static struct drm_privacy_screen_lookup arch_lookup; 14 15 struct arch_init_data { 16 struct drm_privacy_screen_lookup lookup; 17 bool (*detect)(void); 18 }; 19 20 #if IS_ENABLED(CONFIG_THINKPAD_ACPI) 21 static 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 28 static 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 /* Get embedded-controller handle */ 37 status = acpi_get_devices("PNP0C09", acpi_set_handle, NULL, &ec_handle); 38 if (ACPI_FAILURE(status) || !ec_handle) 39 return false; 40 41 /* And call the privacy-screen get-status method */ 42 status = acpi_evaluate_integer(ec_handle, "HKEY.GSSS", &args, &output); 43 if (ACPI_FAILURE(status)) 44 return false; 45 46 return (output & 0x10000) ? true : false; 47 } 48 #endif 49 50 #if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN) 51 static bool __init detect_chromeos_privacy_screen(void) 52 { 53 return acpi_dev_present("GOOG0010", NULL, -1); 54 } 55 #endif 56 57 static const struct arch_init_data arch_init_data[] __initconst = { 58 #if IS_ENABLED(CONFIG_THINKPAD_ACPI) 59 { 60 .lookup = { 61 .dev_id = NULL, 62 .con_id = NULL, 63 .provider = "privacy_screen-thinkpad_acpi", 64 }, 65 .detect = detect_thinkpad_privacy_screen, 66 }, 67 #endif 68 #if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN) 69 { 70 .lookup = { 71 .dev_id = NULL, 72 .con_id = NULL, 73 .provider = "privacy_screen-GOOG0010:00", 74 }, 75 .detect = detect_chromeos_privacy_screen, 76 }, 77 #endif 78 }; 79 80 void __init drm_privacy_screen_lookup_init(void) 81 { 82 int i; 83 84 for (i = 0; i < ARRAY_SIZE(arch_init_data); i++) { 85 if (!arch_init_data[i].detect()) 86 continue; 87 88 pr_info("Found '%s' privacy-screen provider\n", 89 arch_init_data[i].lookup.provider); 90 91 /* Make a copy because arch_init_data is __initconst */ 92 arch_lookup = arch_init_data[i].lookup; 93 drm_privacy_screen_lookup_add(&arch_lookup); 94 break; 95 } 96 } 97 98 void drm_privacy_screen_lookup_exit(void) 99 { 100 if (arch_lookup.provider) 101 drm_privacy_screen_lookup_remove(&arch_lookup); 102 } 103 #endif /* ifdef CONFIG_X86 */ 104