0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/acpi.h>
0015 #include <drm/drm_privacy_screen_driver.h>
0016
0017
0018
0019
0020
0021 #define PRIV_SCRN_DSM_REVID 1
0022 #define PRIV_SCRN_DSM_FN_GET_STATUS 1
0023 #define PRIV_SCRN_DSM_FN_ENABLE 2
0024 #define PRIV_SCRN_DSM_FN_DISABLE 3
0025
0026 static const guid_t chromeos_privacy_screen_dsm_guid =
0027 GUID_INIT(0xc7033113, 0x8720, 0x4ceb,
0028 0x90, 0x90, 0x9d, 0x52, 0xb3, 0xe5, 0x2d, 0x73);
0029
0030 static void
0031 chromeos_privacy_screen_get_hw_state(struct drm_privacy_screen
0032 *drm_privacy_screen)
0033 {
0034 union acpi_object *obj;
0035 acpi_handle handle;
0036 struct device *privacy_screen =
0037 drm_privacy_screen_get_drvdata(drm_privacy_screen);
0038
0039 handle = acpi_device_handle(to_acpi_device(privacy_screen));
0040 obj = acpi_evaluate_dsm(handle, &chromeos_privacy_screen_dsm_guid,
0041 PRIV_SCRN_DSM_REVID,
0042 PRIV_SCRN_DSM_FN_GET_STATUS, NULL);
0043 if (!obj) {
0044 dev_err(privacy_screen,
0045 "_DSM failed to get privacy-screen state\n");
0046 return;
0047 }
0048
0049 if (obj->type != ACPI_TYPE_INTEGER)
0050 dev_err(privacy_screen,
0051 "Bad _DSM to get privacy-screen state\n");
0052 else if (obj->integer.value == 1)
0053 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
0054 PRIVACY_SCREEN_ENABLED;
0055 else
0056 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
0057 PRIVACY_SCREEN_DISABLED;
0058
0059 ACPI_FREE(obj);
0060 }
0061
0062 static int
0063 chromeos_privacy_screen_set_sw_state(struct drm_privacy_screen
0064 *drm_privacy_screen,
0065 enum drm_privacy_screen_status state)
0066 {
0067 union acpi_object *obj = NULL;
0068 acpi_handle handle;
0069 struct device *privacy_screen =
0070 drm_privacy_screen_get_drvdata(drm_privacy_screen);
0071
0072 handle = acpi_device_handle(to_acpi_device(privacy_screen));
0073
0074 if (state == PRIVACY_SCREEN_DISABLED) {
0075 obj = acpi_evaluate_dsm(handle,
0076 &chromeos_privacy_screen_dsm_guid,
0077 PRIV_SCRN_DSM_REVID,
0078 PRIV_SCRN_DSM_FN_DISABLE, NULL);
0079 } else if (state == PRIVACY_SCREEN_ENABLED) {
0080 obj = acpi_evaluate_dsm(handle,
0081 &chromeos_privacy_screen_dsm_guid,
0082 PRIV_SCRN_DSM_REVID,
0083 PRIV_SCRN_DSM_FN_ENABLE, NULL);
0084 } else {
0085 dev_err(privacy_screen,
0086 "Bad attempt to set privacy-screen status to %u\n",
0087 state);
0088 return -EINVAL;
0089 }
0090
0091 if (!obj) {
0092 dev_err(privacy_screen,
0093 "_DSM failed to set privacy-screen state\n");
0094 return -EIO;
0095 }
0096
0097 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = state;
0098 ACPI_FREE(obj);
0099 return 0;
0100 }
0101
0102 static const struct drm_privacy_screen_ops chromeos_privacy_screen_ops = {
0103 .get_hw_state = chromeos_privacy_screen_get_hw_state,
0104 .set_sw_state = chromeos_privacy_screen_set_sw_state,
0105 };
0106
0107 static int chromeos_privacy_screen_add(struct acpi_device *adev)
0108 {
0109 struct drm_privacy_screen *drm_privacy_screen =
0110 drm_privacy_screen_register(&adev->dev,
0111 &chromeos_privacy_screen_ops,
0112 &adev->dev);
0113
0114 if (IS_ERR(drm_privacy_screen)) {
0115 dev_err(&adev->dev, "Error registering privacy-screen\n");
0116 return PTR_ERR(drm_privacy_screen);
0117 }
0118
0119 adev->driver_data = drm_privacy_screen;
0120 dev_info(&adev->dev, "registered privacy-screen '%s'\n",
0121 dev_name(&drm_privacy_screen->dev));
0122
0123 return 0;
0124 }
0125
0126 static int chromeos_privacy_screen_remove(struct acpi_device *adev)
0127 {
0128 struct drm_privacy_screen *drm_privacy_screen = acpi_driver_data(adev);
0129
0130 drm_privacy_screen_unregister(drm_privacy_screen);
0131 return 0;
0132 }
0133
0134 static const struct acpi_device_id chromeos_privacy_screen_device_ids[] = {
0135 {"GOOG0010", 0},
0136 {}
0137 };
0138 MODULE_DEVICE_TABLE(acpi, chromeos_privacy_screen_device_ids);
0139
0140 static struct acpi_driver chromeos_privacy_screen_driver = {
0141 .name = "chromeos_privacy_screen_driver",
0142 .class = "ChromeOS",
0143 .ids = chromeos_privacy_screen_device_ids,
0144 .ops = {
0145 .add = chromeos_privacy_screen_add,
0146 .remove = chromeos_privacy_screen_remove,
0147 },
0148 };
0149
0150 module_acpi_driver(chromeos_privacy_screen_driver);
0151 MODULE_LICENSE("GPL v2");
0152 MODULE_DESCRIPTION("ChromeOS ACPI Privacy Screen driver");
0153 MODULE_AUTHOR("Rajat Jain <rajatja@google.com>");