0003-buttons.patch 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. From ac9ac2a05180af9e356f2f4d6840b132b1fb45f7 Mon Sep 17 00:00:00 2001
  2. From: qzed <qzed@users.noreply.github.com>
  3. Date: Mon, 24 Dec 2018 14:05:07 +0100
  4. Subject: [PATCH 3/8] buttons
  5. ---
  6. drivers/input/misc/soc_button_array.c | 67 +++++++++++++++++++++--
  7. drivers/platform/x86/surfacepro3_button.c | 9 +++
  8. 2 files changed, 70 insertions(+), 6 deletions(-)
  9. diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
  10. index 23520df7650f..d74f8c3dd54b 100644
  11. --- a/drivers/input/misc/soc_button_array.c
  12. +++ b/drivers/input/misc/soc_button_array.c
  13. @@ -29,12 +29,20 @@ struct soc_button_info {
  14. bool wakeup;
  15. };
  16. +struct soc_device_data {
  17. + /* Button info, may be NULL. */
  18. + struct soc_button_info *button_info;
  19. + /* Special device check function, may be NULL. */
  20. + int (*check)(struct device *);
  21. +};
  22. +
  23. /*
  24. * Some of the buttons like volume up/down are auto repeat, while others
  25. * are not. To support both, we register two platform devices, and put
  26. * buttons into them based on whether the key should be auto repeat.
  27. */
  28. -#define BUTTON_TYPES 2
  29. +#define BUTTON_TYPES 2
  30. +#define SURFACE_METHOD_DSM "_DSM"
  31. struct soc_button_data {
  32. struct platform_device *children[BUTTON_TYPES];
  33. @@ -310,6 +318,7 @@ static int soc_button_probe(struct platform_device *pdev)
  34. {
  35. struct device *dev = &pdev->dev;
  36. const struct acpi_device_id *id;
  37. + struct soc_device_data *device_data;
  38. struct soc_button_info *button_info;
  39. struct soc_button_data *priv;
  40. struct platform_device *pd;
  41. @@ -320,12 +329,20 @@ static int soc_button_probe(struct platform_device *pdev)
  42. if (!id)
  43. return -ENODEV;
  44. - if (!id->driver_data) {
  45. + device_data = (struct soc_device_data *)id->driver_data;
  46. + if (device_data && device_data->check) {
  47. + // device dependent check, required for MSHW0040
  48. + error = device_data->check(dev);
  49. + if (error != 0)
  50. + return error;
  51. + }
  52. +
  53. + if (device_data && device_data->button_info) {
  54. + button_info = (struct soc_button_info *)device_data->button_info;
  55. + } else {
  56. button_info = soc_button_get_button_info(dev);
  57. if (IS_ERR(button_info))
  58. return PTR_ERR(button_info);
  59. - } else {
  60. - button_info = (struct soc_button_info *)id->driver_data;
  61. }
  62. error = gpiod_count(dev, NULL);
  63. @@ -357,7 +374,7 @@ static int soc_button_probe(struct platform_device *pdev)
  64. if (!priv->children[0] && !priv->children[1])
  65. return -ENODEV;
  66. - if (!id->driver_data)
  67. + if (!device_data || !device_data->button_info)
  68. devm_kfree(dev, button_info);
  69. return 0;
  70. @@ -377,9 +394,47 @@ static struct soc_button_info soc_button_PNP0C40[] = {
  71. { }
  72. };
  73. +static struct soc_device_data soc_device_PNP0C40 = {
  74. + .button_info = soc_button_PNP0C40,
  75. + .check = NULL,
  76. +};
  77. +
  78. +/*
  79. + * Special device check for Surface Book 2 and Surface Pro (2017).
  80. + * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
  81. + * devices use MSHW0040 for power and volume buttons, however the way they
  82. + * have to be addressed differs. Make sure that we only load this drivers
  83. + * for the correct devices by checking if the _DSM method exists.
  84. + */
  85. +static int soc_device_check_MSHW0040(struct device *dev)
  86. +{
  87. + if (!acpi_has_method(ACPI_HANDLE(dev), SURFACE_METHOD_DSM))
  88. + return -ENODEV;
  89. +
  90. + return 0;
  91. +}
  92. +
  93. +/*
  94. + * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
  95. + * Extracted from DSDT.
  96. + */
  97. +static struct soc_button_info soc_button_MSHW0040[] = {
  98. + { "power", 0, EV_KEY, KEY_POWER, false, true },
  99. + { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
  100. + { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false },
  101. + { }
  102. +};
  103. +
  104. +static struct soc_device_data soc_device_MSHW0040 = {
  105. + .button_info = soc_button_MSHW0040,
  106. + .check = soc_device_check_MSHW0040,
  107. +};
  108. +
  109. static const struct acpi_device_id soc_button_acpi_match[] = {
  110. - { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
  111. + { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
  112. { "ACPI0011", 0 },
  113. + /* Microsoft Surface Book 2 and Surface Pro (2017) */
  114. + { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
  115. { }
  116. };
  117. diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c
  118. index 1b491690ce07..006c94eda7be 100644
  119. --- a/drivers/platform/x86/surfacepro3_button.c
  120. +++ b/drivers/platform/x86/surfacepro3_button.c
  121. @@ -22,6 +22,7 @@
  122. #define SURFACE_PRO3_BUTTON_HID "MSHW0028"
  123. #define SURFACE_PRO4_BUTTON_HID "MSHW0040"
  124. #define SURFACE_BUTTON_OBJ_NAME "VGBI"
  125. +#define SURFACE_METHOD_DSM "_DSM"
  126. #define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons"
  127. #define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8
  128. @@ -158,6 +159,14 @@ static int surface_button_add(struct acpi_device *device)
  129. strlen(SURFACE_BUTTON_OBJ_NAME)))
  130. return -ENODEV;
  131. + /*
  132. + * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
  133. + * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
  134. + * device by checking for the _DSM method.
  135. + */
  136. + if (acpi_has_method(device->handle, SURFACE_METHOD_DSM))
  137. + return -ENODEV;
  138. +
  139. button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
  140. if (!button)
  141. return -ENOMEM;
  142. --
  143. 2.20.1