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 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) 54 static bool __init detect_chromeos_privacy_screen(void) 55 { 56 return acpi_dev_present("GOOG0010", NULL, -1); 57 } 58 #endif 59 60 static 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 83 void __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 101 void 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 */ 107