platform/x86: surfacepro3_button: Fix device check

Do not use the surfacepro3_button driver on newer Microsoft Surface
models, only use it on the Surface Pro 3 and 4. Newer models (5th, 6th
and possibly future generations) use the same device as the Surface Pro
4 to represent their volume and power buttons (MSHW0040), but their
actual implementation is significantly different. This patch ensures
that the surfacepro3_button driver is only used on the Pro 3 and 4
models, allowing a different driver to bind on other models.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Acked-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
Maximilian Luz 2019-07-28 12:55:48 +03:00 committed by Dmitry Torokhov
parent 3b51c44bd6
commit 64dd243d73

View File

@ -20,6 +20,12 @@
#define SURFACE_BUTTON_OBJ_NAME "VGBI" #define SURFACE_BUTTON_OBJ_NAME "VGBI"
#define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons" #define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons"
#define MSHW0040_DSM_REVISION 0x01
#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision
static const guid_t MSHW0040_DSM_UUID =
GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
0x49, 0x80, 0x35);
#define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8 #define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8
#define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6
@ -142,6 +148,44 @@ static int surface_button_resume(struct device *dev)
} }
#endif #endif
/*
* Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
* ID (MSHW0040) for the power/volume buttons. Make sure this is the right
* device by checking for the _DSM method and OEM Platform Revision.
*
* Returns true if the driver should bind to this device, i.e. the device is
* either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
*/
static bool surface_button_check_MSHW0040(struct acpi_device *dev)
{
acpi_handle handle = dev->handle;
union acpi_object *result;
u64 oem_platform_rev = 0; // valid revisions are nonzero
// get OEM platform revision
result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
MSHW0040_DSM_REVISION,
MSHW0040_DSM_GET_OMPR,
NULL, ACPI_TYPE_INTEGER);
/*
* If evaluating the _DSM fails, the method is not present. This means
* that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
* should use this driver. We use revision 0 indicating it is
* unavailable.
*/
if (result) {
oem_platform_rev = result->integer.value;
ACPI_FREE(result);
}
dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
return oem_platform_rev == 0;
}
static int surface_button_add(struct acpi_device *device) static int surface_button_add(struct acpi_device *device)
{ {
struct surface_button *button; struct surface_button *button;
@ -154,6 +198,9 @@ static int surface_button_add(struct acpi_device *device)
strlen(SURFACE_BUTTON_OBJ_NAME))) strlen(SURFACE_BUTTON_OBJ_NAME)))
return -ENODEV; return -ENODEV;
if (!surface_button_check_MSHW0040(device))
return -ENODEV;
button = kzalloc(sizeof(struct surface_button), GFP_KERNEL); button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
if (!button) if (!button)
return -ENOMEM; return -ENOMEM;