Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 147 lines 4.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2 3/* 4 * ChromeOS Privacy Screen support 5 * 6 * Copyright (C) 2022 Google LLC 7 * 8 * This is the Chromeos privacy screen provider, present on certain chromebooks, 9 * represented by a GOOG0010 device in the ACPI. This ACPI device, if present, 10 * will cause the i915 drm driver to probe defer until this driver registers 11 * the privacy-screen. 12 */ 13 14#include <linux/acpi.h> 15#include <linux/platform_device.h> 16#include <drm/drm_privacy_screen_driver.h> 17 18/* 19 * The DSM (Device Specific Method) constants below are the agreed API with 20 * the firmware team, on how to control privacy screen using ACPI methods. 21 */ 22#define PRIV_SCRN_DSM_REVID 1 /* DSM version */ 23#define PRIV_SCRN_DSM_FN_GET_STATUS 1 /* Get privacy screen status */ 24#define PRIV_SCRN_DSM_FN_ENABLE 2 /* Enable privacy screen */ 25#define PRIV_SCRN_DSM_FN_DISABLE 3 /* Disable privacy screen */ 26 27static const guid_t chromeos_privacy_screen_dsm_guid = 28 GUID_INIT(0xc7033113, 0x8720, 0x4ceb, 29 0x90, 0x90, 0x9d, 0x52, 0xb3, 0xe5, 0x2d, 0x73); 30 31static void 32chromeos_privacy_screen_get_hw_state(struct drm_privacy_screen 33 *drm_privacy_screen) 34{ 35 union acpi_object *obj; 36 struct device *privacy_screen = 37 drm_privacy_screen_get_drvdata(drm_privacy_screen); 38 acpi_handle handle = ACPI_HANDLE(privacy_screen); 39 40 obj = acpi_evaluate_dsm(handle, &chromeos_privacy_screen_dsm_guid, 41 PRIV_SCRN_DSM_REVID, 42 PRIV_SCRN_DSM_FN_GET_STATUS, NULL); 43 if (!obj) { 44 dev_err(privacy_screen, 45 "_DSM failed to get privacy-screen state\n"); 46 return; 47 } 48 49 if (obj->type != ACPI_TYPE_INTEGER) 50 dev_err(privacy_screen, 51 "Bad _DSM to get privacy-screen state\n"); 52 else if (obj->integer.value == 1) 53 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = 54 PRIVACY_SCREEN_ENABLED; 55 else 56 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = 57 PRIVACY_SCREEN_DISABLED; 58 59 ACPI_FREE(obj); 60} 61 62static int 63chromeos_privacy_screen_set_sw_state(struct drm_privacy_screen 64 *drm_privacy_screen, 65 enum drm_privacy_screen_status state) 66{ 67 union acpi_object *obj = NULL; 68 struct device *privacy_screen = 69 drm_privacy_screen_get_drvdata(drm_privacy_screen); 70 acpi_handle handle = ACPI_HANDLE(privacy_screen); 71 72 if (state == PRIVACY_SCREEN_DISABLED) { 73 obj = acpi_evaluate_dsm(handle, 74 &chromeos_privacy_screen_dsm_guid, 75 PRIV_SCRN_DSM_REVID, 76 PRIV_SCRN_DSM_FN_DISABLE, NULL); 77 } else if (state == PRIVACY_SCREEN_ENABLED) { 78 obj = acpi_evaluate_dsm(handle, 79 &chromeos_privacy_screen_dsm_guid, 80 PRIV_SCRN_DSM_REVID, 81 PRIV_SCRN_DSM_FN_ENABLE, NULL); 82 } else { 83 dev_err(privacy_screen, 84 "Bad attempt to set privacy-screen status to %u\n", 85 state); 86 return -EINVAL; 87 } 88 89 if (!obj) { 90 dev_err(privacy_screen, 91 "_DSM failed to set privacy-screen state\n"); 92 return -EIO; 93 } 94 95 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = state; 96 ACPI_FREE(obj); 97 return 0; 98} 99 100static const struct drm_privacy_screen_ops chromeos_privacy_screen_ops = { 101 .get_hw_state = chromeos_privacy_screen_get_hw_state, 102 .set_sw_state = chromeos_privacy_screen_set_sw_state, 103}; 104 105static int chromeos_privacy_screen_probe(struct platform_device *pdev) 106{ 107 struct drm_privacy_screen *drm_privacy_screen = 108 drm_privacy_screen_register(&pdev->dev, 109 &chromeos_privacy_screen_ops, 110 &pdev->dev); 111 112 if (IS_ERR(drm_privacy_screen)) { 113 dev_err(&pdev->dev, "Error registering privacy-screen\n"); 114 return PTR_ERR(drm_privacy_screen); 115 } 116 117 platform_set_drvdata(pdev, drm_privacy_screen); 118 dev_info(&pdev->dev, "registered privacy-screen '%s'\n", 119 dev_name(&drm_privacy_screen->dev)); 120 121 return 0; 122} 123 124static void chromeos_privacy_screen_remove(struct platform_device *pdev) 125{ 126 drm_privacy_screen_unregister(platform_get_drvdata(pdev)); 127} 128 129static const struct acpi_device_id chromeos_privacy_screen_device_ids[] = { 130 {"GOOG0010", 0}, /* Google's electronic privacy screen for eDP-1 */ 131 {} 132}; 133MODULE_DEVICE_TABLE(acpi, chromeos_privacy_screen_device_ids); 134 135static struct platform_driver chromeos_privacy_screen_driver = { 136 .probe = chromeos_privacy_screen_probe, 137 .remove = chromeos_privacy_screen_remove, 138 .driver = { 139 .name = "chromeos_privacy_screen_driver", 140 .acpi_match_table = chromeos_privacy_screen_device_ids, 141 }, 142}; 143 144module_platform_driver(chromeos_privacy_screen_driver); 145MODULE_LICENSE("GPL v2"); 146MODULE_DESCRIPTION("ChromeOS ACPI Privacy Screen driver"); 147MODULE_AUTHOR("Rajat Jain <rajatja@google.com>");