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

Merge branch 'linux-next' of git://cavan.codon.org.uk/platform-drivers-x86

Pull x86 platform driver updates from Matthew Garrett:
"Nothing overly dramatic here - improved support for the Classmate,
some random small fixes and a rework of backlight management to deal
with some of the more awkward cases."

* 'linux-next' of git://cavan.codon.org.uk/platform-drivers-x86:
thinkpad_acpi: Free hotkey_keycode_map after unregistering tpacpi_inputdev
thinkpad_acpi: Fix a memory leak during module exit
thinkpad_acpi: Flush the workqueue before freeing tpacpi_leds
dell-laptop: Add 6 machines to touchpad led quirk
ACER: Fix Smatch double-free issue
ACER: Fix up sparse warning
asus-nb-wmi: add some video toggle keys
asus-nb-wmi: add wapf quirk for ASUS machines
classmate-laptop: Fix extra keys hardware id.
classmate-laptop: Add support for Classmate V4 accelerometer.
asus-wmi: enable resume on lid open
asus-wmi: control backlight power through WMI, not ACPI
samsung-laptop: support R40/R41
acpi/video_detect: blacklist samsung x360
samsung-laptop: X360 ACPI backlight device is broken
drivers-platform-x86: use acpi_video_dmi_promote_vendor()
acpi: add a way to promote/demote vendor backlight drivers
ACER: Add support for accelerometer sensor
asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID.

+864 -34
+7
Documentation/ABI/testing/sysfs-platform-asus-wmi
··· 29 29 Contact: "Corentin Chary" <corentincj@iksaif.net> 30 30 Description: 31 31 Control the card touchpad. 1 means on, 0 means off. 32 + 33 + What: /sys/devices/platform/<platform>/lid_resume 34 + Date: May 2012 35 + KernelVersion: 3.5 36 + Contact: "AceLan Kao" <acelan.kao@canonical.com> 37 + Description: 38 + Resume on lid open. 1 means on, 0 means off.
+58 -2
drivers/acpi/video_detect.c
··· 132 132 return AE_OK; 133 133 } 134 134 135 + /* Force to use vendor driver when the ACPI device is known to be 136 + * buggy */ 137 + static int video_detect_force_vendor(const struct dmi_system_id *d) 138 + { 139 + acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; 140 + return 0; 141 + } 142 + 143 + static struct dmi_system_id video_detect_dmi_table[] = { 144 + /* On Samsung X360, the BIOS will set a flag (VDRV) if generic 145 + * ACPI backlight device is used. This flag will definitively break 146 + * the backlight interface (even the vendor interface) untill next 147 + * reboot. It's why we should prevent video.ko from being used here 148 + * and we can't rely on a later call to acpi_video_unregister(). 149 + */ 150 + { 151 + .callback = video_detect_force_vendor, 152 + .ident = "X360", 153 + .matches = { 154 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 155 + DMI_MATCH(DMI_PRODUCT_NAME, "X360"), 156 + DMI_MATCH(DMI_BOARD_NAME, "X360"), 157 + }, 158 + }, 159 + { }, 160 + }; 161 + 135 162 /* 136 163 * Returns the video capabilities of a specific ACPI graphics device 137 164 * ··· 191 164 * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; 192 165 *} 193 166 */ 167 + 168 + dmi_check_system(video_detect_dmi_table); 194 169 } else { 195 170 status = acpi_bus_get_device(graphics_handle, &tmp_dev); 196 171 if (ACPI_FAILURE(status)) { ··· 211 182 } 212 183 EXPORT_SYMBOL(acpi_video_get_capabilities); 213 184 214 - /* Returns true if video.ko can do backlight switching */ 215 - int acpi_video_backlight_support(void) 185 + static void acpi_video_caps_check(void) 216 186 { 217 187 /* 218 188 * We must check whether the ACPI graphics device is physically plugged ··· 219 191 */ 220 192 if (!acpi_video_caps_checked) 221 193 acpi_video_get_capabilities(NULL); 194 + } 195 + 196 + /* Promote the vendor interface instead of the generic video module. 197 + * This function allow DMI blacklists to be implemented by externals 198 + * platform drivers instead of putting a big blacklist in video_detect.c 199 + * After calling this function you will probably want to call 200 + * acpi_video_unregister() to make sure the video module is not loaded 201 + */ 202 + void acpi_video_dmi_promote_vendor(void) 203 + { 204 + acpi_video_caps_check(); 205 + acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; 206 + } 207 + EXPORT_SYMBOL(acpi_video_dmi_promote_vendor); 208 + 209 + /* To be called when a driver who previously promoted the vendor 210 + * interface */ 211 + void acpi_video_dmi_demote_vendor(void) 212 + { 213 + acpi_video_caps_check(); 214 + acpi_video_support &= ~ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; 215 + } 216 + EXPORT_SYMBOL(acpi_video_dmi_demote_vendor); 217 + 218 + /* Returns true if video.ko can do backlight switching */ 219 + int acpi_video_backlight_support(void) 220 + { 221 + acpi_video_caps_check(); 222 222 223 223 /* First check for boot param -> highest prio */ 224 224 if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR)
+146 -7
drivers/platform/x86/acer-wmi.c
··· 95 95 96 96 enum acer_wmi_event_ids { 97 97 WMID_HOTKEY_EVENT = 0x1, 98 + WMID_ACCEL_EVENT = 0x5, 98 99 }; 99 100 100 101 static const struct key_entry acer_wmi_keymap[] = { ··· 131 130 }; 132 131 133 132 static struct input_dev *acer_wmi_input_dev; 133 + static struct input_dev *acer_wmi_accel_dev; 134 134 135 135 struct event_return_value { 136 136 u8 function; ··· 202 200 #define ACER_CAP_BLUETOOTH (1<<2) 203 201 #define ACER_CAP_BRIGHTNESS (1<<3) 204 202 #define ACER_CAP_THREEG (1<<4) 203 + #define ACER_CAP_ACCEL (1<<5) 205 204 #define ACER_CAP_ANY (0xFFFFFFFF) 206 205 207 206 /* ··· 1402 1399 } 1403 1400 1404 1401 /* 1402 + * Accelerometer device 1403 + */ 1404 + static acpi_handle gsensor_handle; 1405 + 1406 + static int acer_gsensor_init(void) 1407 + { 1408 + acpi_status status; 1409 + struct acpi_buffer output; 1410 + union acpi_object out_obj; 1411 + 1412 + output.length = sizeof(out_obj); 1413 + output.pointer = &out_obj; 1414 + status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output); 1415 + if (ACPI_FAILURE(status)) 1416 + return -1; 1417 + 1418 + return 0; 1419 + } 1420 + 1421 + static int acer_gsensor_open(struct input_dev *input) 1422 + { 1423 + return acer_gsensor_init(); 1424 + } 1425 + 1426 + static int acer_gsensor_event(void) 1427 + { 1428 + acpi_status status; 1429 + struct acpi_buffer output; 1430 + union acpi_object out_obj[5]; 1431 + 1432 + if (!has_cap(ACER_CAP_ACCEL)) 1433 + return -1; 1434 + 1435 + output.length = sizeof(out_obj); 1436 + output.pointer = out_obj; 1437 + 1438 + status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output); 1439 + if (ACPI_FAILURE(status)) 1440 + return -1; 1441 + 1442 + if (out_obj->package.count != 4) 1443 + return -1; 1444 + 1445 + input_report_abs(acer_wmi_accel_dev, ABS_X, 1446 + (s16)out_obj->package.elements[0].integer.value); 1447 + input_report_abs(acer_wmi_accel_dev, ABS_Y, 1448 + (s16)out_obj->package.elements[1].integer.value); 1449 + input_report_abs(acer_wmi_accel_dev, ABS_Z, 1450 + (s16)out_obj->package.elements[2].integer.value); 1451 + input_sync(acer_wmi_accel_dev); 1452 + return 0; 1453 + } 1454 + 1455 + /* 1405 1456 * Rfkill devices 1406 1457 */ 1407 1458 static void acer_rfkill_update(struct work_struct *ignored); ··· 1730 1673 1, true); 1731 1674 } 1732 1675 break; 1676 + case WMID_ACCEL_EVENT: 1677 + acer_gsensor_event(); 1678 + break; 1733 1679 default: 1734 1680 pr_warn("Unknown function number - %d - %d\n", 1735 1681 return_value.function, return_value.key_num); ··· 1816 1756 return_value.ec_return_value); 1817 1757 1818 1758 return status; 1759 + } 1760 + 1761 + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, 1762 + void *ctx, void **retval) 1763 + { 1764 + *(acpi_handle *)retval = ah; 1765 + return AE_OK; 1766 + } 1767 + 1768 + static int __init acer_wmi_get_handle(const char *name, const char *prop, 1769 + acpi_handle *ah) 1770 + { 1771 + acpi_status status; 1772 + acpi_handle handle; 1773 + 1774 + BUG_ON(!name || !ah); 1775 + 1776 + handle = NULL; 1777 + status = acpi_get_devices(prop, acer_wmi_get_handle_cb, 1778 + (void *)name, &handle); 1779 + 1780 + if (ACPI_SUCCESS(status)) { 1781 + *ah = handle; 1782 + return 0; 1783 + } else { 1784 + return -ENODEV; 1785 + } 1786 + } 1787 + 1788 + static int __init acer_wmi_accel_setup(void) 1789 + { 1790 + int err; 1791 + 1792 + err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); 1793 + if (err) 1794 + return err; 1795 + 1796 + interface->capability |= ACER_CAP_ACCEL; 1797 + 1798 + acer_wmi_accel_dev = input_allocate_device(); 1799 + if (!acer_wmi_accel_dev) 1800 + return -ENOMEM; 1801 + 1802 + acer_wmi_accel_dev->open = acer_gsensor_open; 1803 + 1804 + acer_wmi_accel_dev->name = "Acer BMA150 accelerometer"; 1805 + acer_wmi_accel_dev->phys = "wmi/input1"; 1806 + acer_wmi_accel_dev->id.bustype = BUS_HOST; 1807 + acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS); 1808 + input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0); 1809 + input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0); 1810 + input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0); 1811 + 1812 + err = input_register_device(acer_wmi_accel_dev); 1813 + if (err) 1814 + goto err_free_dev; 1815 + 1816 + return 0; 1817 + 1818 + err_free_dev: 1819 + input_free_device(acer_wmi_accel_dev); 1820 + return err; 1821 + } 1822 + 1823 + static void acer_wmi_accel_destroy(void) 1824 + { 1825 + input_unregister_device(acer_wmi_accel_dev); 1819 1826 } 1820 1827 1821 1828 static int __init acer_wmi_input_setup(void) ··· 2039 1912 if (has_cap(ACER_CAP_BRIGHTNESS)) 2040 1913 set_u32(data->brightness, ACER_CAP_BRIGHTNESS); 2041 1914 1915 + if (has_cap(ACER_CAP_ACCEL)) 1916 + acer_gsensor_init(); 1917 + 2042 1918 return 0; 2043 1919 } 2044 1920 ··· 2190 2060 2191 2061 set_quirks(); 2192 2062 2063 + if (dmi_check_system(video_vendor_dmi_table)) 2064 + acpi_video_dmi_promote_vendor(); 2193 2065 if (acpi_video_backlight_support()) { 2194 - if (dmi_check_system(video_vendor_dmi_table)) { 2195 - acpi_video_unregister(); 2196 - } else { 2197 - interface->capability &= ~ACER_CAP_BRIGHTNESS; 2198 - pr_info("Brightness must be controlled by " 2199 - "acpi video driver\n"); 2200 - } 2066 + interface->capability &= ~ACER_CAP_BRIGHTNESS; 2067 + pr_info("Brightness must be controlled by acpi video driver\n"); 2068 + } else { 2069 + #ifdef CONFIG_ACPI_VIDEO 2070 + pr_info("Disabling ACPI video driver\n"); 2071 + acpi_video_unregister(); 2072 + #endif 2201 2073 } 2202 2074 2203 2075 if (wmi_has_guid(WMID_GUID3)) { ··· 2221 2089 if (err) 2222 2090 return err; 2223 2091 } 2092 + 2093 + acer_wmi_accel_setup(); 2224 2094 2225 2095 err = platform_driver_register(&acer_platform_driver); 2226 2096 if (err) { ··· 2267 2133 error_platform_register: 2268 2134 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 2269 2135 acer_wmi_input_destroy(); 2136 + if (has_cap(ACER_CAP_ACCEL)) 2137 + acer_wmi_accel_destroy(); 2270 2138 2271 2139 return err; 2272 2140 } ··· 2277 2141 { 2278 2142 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 2279 2143 acer_wmi_input_destroy(); 2144 + 2145 + if (has_cap(ACER_CAP_ACCEL)) 2146 + acer_wmi_accel_destroy(); 2280 2147 2281 2148 remove_sysfs(acer_platform_device); 2282 2149 remove_debugfs();
+6
drivers/platform/x86/apple-gmux.c
··· 193 193 * backlight control and supports more levels than other options. 194 194 * Disable the other backlight choices. 195 195 */ 196 + acpi_video_dmi_promote_vendor(); 197 + #ifdef CONFIG_ACPI_VIDEO 196 198 acpi_video_unregister(); 199 + #endif 197 200 apple_bl_unregister(); 198 201 199 202 return 0; ··· 216 213 release_region(gmux_data->iostart, gmux_data->iolen); 217 214 kfree(gmux_data); 218 215 216 + acpi_video_dmi_demote_vendor(); 217 + #ifdef CONFIG_ACPI_VIDEO 219 218 acpi_video_register(); 219 + #endif 220 220 apple_bl_register(); 221 221 } 222 222
+105 -3
drivers/platform/x86/asus-nb-wmi.c
··· 26 26 #include <linux/input.h> 27 27 #include <linux/input/sparse-keymap.h> 28 28 #include <linux/fb.h> 29 + #include <linux/dmi.h> 29 30 30 31 #include "asus-wmi.h" 31 32 ··· 49 48 * 1 | Hardware | Software 50 49 * 4 | Software | Software 51 50 */ 52 - static uint wapf; 51 + static int wapf = -1; 53 52 module_param(wapf, uint, 0444); 54 53 MODULE_PARM_DESC(wapf, "WAPF value"); 55 54 55 + static struct quirk_entry *quirks; 56 + 56 57 static struct quirk_entry quirk_asus_unknown = { 58 + .wapf = 0, 59 + }; 60 + 61 + static struct quirk_entry quirk_asus_x401u = { 62 + .wapf = 4, 63 + }; 64 + 65 + static int dmi_matched(const struct dmi_system_id *dmi) 66 + { 67 + quirks = dmi->driver_data; 68 + return 1; 69 + } 70 + 71 + static struct dmi_system_id asus_quirks[] = { 72 + { 73 + .callback = dmi_matched, 74 + .ident = "ASUSTeK COMPUTER INC. X401U", 75 + .matches = { 76 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 77 + DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), 78 + }, 79 + .driver_data = &quirk_asus_x401u, 80 + }, 81 + { 82 + .callback = dmi_matched, 83 + .ident = "ASUSTeK COMPUTER INC. X401A1", 84 + .matches = { 85 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 86 + DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), 87 + }, 88 + .driver_data = &quirk_asus_x401u, 89 + }, 90 + { 91 + .callback = dmi_matched, 92 + .ident = "ASUSTeK COMPUTER INC. X501U", 93 + .matches = { 94 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 95 + DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), 96 + }, 97 + .driver_data = &quirk_asus_x401u, 98 + }, 99 + { 100 + .callback = dmi_matched, 101 + .ident = "ASUSTeK COMPUTER INC. X501A1", 102 + .matches = { 103 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 104 + DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), 105 + }, 106 + .driver_data = &quirk_asus_x401u, 107 + }, 108 + { 109 + .callback = dmi_matched, 110 + .ident = "ASUSTeK COMPUTER INC. X55A", 111 + .matches = { 112 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 113 + DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), 114 + }, 115 + .driver_data = &quirk_asus_x401u, 116 + }, 117 + { 118 + .callback = dmi_matched, 119 + .ident = "ASUSTeK COMPUTER INC. X55C", 120 + .matches = { 121 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 122 + DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), 123 + }, 124 + .driver_data = &quirk_asus_x401u, 125 + }, 126 + { 127 + .callback = dmi_matched, 128 + .ident = "ASUSTeK COMPUTER INC. X55U", 129 + .matches = { 130 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 131 + DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), 132 + }, 133 + .driver_data = &quirk_asus_x401u, 134 + }, 135 + { 136 + .callback = dmi_matched, 137 + .ident = "ASUSTeK COMPUTER INC. X55VD", 138 + .matches = { 139 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 140 + DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), 141 + }, 142 + .driver_data = &quirk_asus_x401u, 143 + }, 144 + {}, 57 145 }; 58 146 59 147 static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) 60 148 { 61 - driver->quirks = &quirk_asus_unknown; 62 - driver->quirks->wapf = wapf; 149 + quirks = &quirk_asus_unknown; 150 + dmi_check_system(asus_quirks); 151 + 152 + driver->quirks = quirks; 63 153 driver->panel_power = FB_BLANK_UNBLANK; 154 + 155 + /* overwrite the wapf setting if the wapf paramater is specified */ 156 + if (wapf != -1) 157 + quirks->wapf = wapf; 158 + else 159 + wapf = quirks->wapf; 64 160 } 65 161 66 162 static const struct key_entry asus_nb_wmi_keymap[] = { ··· 192 94 { KE_KEY, 0x8A, { KEY_PROG1 } }, 193 95 { KE_KEY, 0x95, { KEY_MEDIA } }, 194 96 { KE_KEY, 0x99, { KEY_PHONE } }, 97 + { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ 98 + { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ 99 + { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ 100 + { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ 195 101 { KE_KEY, 0xb5, { KEY_CALC } }, 196 102 { KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, 197 103 { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+17 -6
drivers/platform/x86/asus-wmi.c
··· 47 47 #include <linux/thermal.h> 48 48 #include <acpi/acpi_bus.h> 49 49 #include <acpi/acpi_drivers.h> 50 + #ifdef CONFIG_ACPI_VIDEO 51 + #include <acpi/video.h> 52 + #endif 50 53 51 54 #include "asus-wmi.h" 52 55 ··· 138 135 139 136 /* Power */ 140 137 #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 138 + 139 + /* Deep S3 / Resume on LID open */ 140 + #define ASUS_WMI_DEVID_LID_RESUME 0x00120031 141 141 142 142 /* DSTS masks */ 143 143 #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 ··· 1371 1365 ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD); 1372 1366 ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA); 1373 1367 ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER); 1368 + ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME); 1374 1369 1375 1370 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 1376 1371 const char *buf, size_t count) ··· 1397 1390 &dev_attr_camera.attr, 1398 1391 &dev_attr_cardr.attr, 1399 1392 &dev_attr_touchpad.attr, 1393 + &dev_attr_lid_resume.attr, 1400 1394 NULL 1401 1395 }; 1402 1396 ··· 1416 1408 devid = ASUS_WMI_DEVID_CARDREADER; 1417 1409 else if (attr == &dev_attr_touchpad.attr) 1418 1410 devid = ASUS_WMI_DEVID_TOUCHPAD; 1411 + else if (attr == &dev_attr_lid_resume.attr) 1412 + devid = ASUS_WMI_DEVID_LID_RESUME; 1419 1413 1420 1414 if (devid != -1) 1421 1415 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); ··· 1477 1467 */ 1478 1468 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) 1479 1469 asus->dsts_id = ASUS_WMI_METHODID_DSTS; 1480 - else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) 1470 + else 1481 1471 asus->dsts_id = ASUS_WMI_METHODID_DSTS2; 1482 - 1483 - if (!asus->dsts_id) { 1484 - pr_err("Can't find DSTS"); 1485 - return -ENODEV; 1486 - } 1487 1472 1488 1473 /* CWAP allow to define the behavior of the Fn+F2 key, 1489 1474 * this method doesn't seems to be present on Eee PCs */ ··· 1686 1681 if (err) 1687 1682 goto fail_rfkill; 1688 1683 1684 + if (asus->driver->quirks->wmi_backlight_power) 1685 + acpi_video_dmi_promote_vendor(); 1689 1686 if (!acpi_video_backlight_support()) { 1687 + #ifdef CONFIG_ACPI_VIDEO 1688 + pr_info("Disabling ACPI video driver\n"); 1689 + acpi_video_unregister(); 1690 + #endif 1690 1691 err = asus_wmi_backlight_init(asus); 1691 1692 if (err && err != -ENODEV) 1692 1693 goto fail_backlight;
+1
drivers/platform/x86/asus-wmi.h
··· 39 39 bool hotplug_wireless; 40 40 bool scalar_panel_brightness; 41 41 bool store_backlight_power; 42 + bool wmi_backlight_power; 42 43 int wapf; 43 44 }; 44 45
+402 -3
drivers/platform/x86/classmate-laptop.c
··· 31 31 32 32 struct cmpc_accel { 33 33 int sensitivity; 34 + int g_select; 35 + int inputdev_state; 34 36 }; 35 37 36 - #define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 38 + #define CMPC_ACCEL_DEV_STATE_CLOSED 0 39 + #define CMPC_ACCEL_DEV_STATE_OPEN 1 37 40 41 + #define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 42 + #define CMPC_ACCEL_G_SELECT_DEFAULT 0 38 43 39 44 #define CMPC_ACCEL_HID "ACCE0000" 45 + #define CMPC_ACCEL_HID_V4 "ACCE0001" 40 46 #define CMPC_TABLET_HID "TBLT0000" 41 47 #define CMPC_IPML_HID "IPML200" 42 - #define CMPC_KEYS_HID "FnBT0000" 48 + #define CMPC_KEYS_HID "FNBT0000" 43 49 44 50 /* 45 51 * Generic input device code. ··· 82 76 } 83 77 84 78 /* 85 - * Accelerometer code. 79 + * Accelerometer code for Classmate V4 80 + */ 81 + static acpi_status cmpc_start_accel_v4(acpi_handle handle) 82 + { 83 + union acpi_object param[4]; 84 + struct acpi_object_list input; 85 + acpi_status status; 86 + 87 + param[0].type = ACPI_TYPE_INTEGER; 88 + param[0].integer.value = 0x3; 89 + param[1].type = ACPI_TYPE_INTEGER; 90 + param[1].integer.value = 0; 91 + param[2].type = ACPI_TYPE_INTEGER; 92 + param[2].integer.value = 0; 93 + param[3].type = ACPI_TYPE_INTEGER; 94 + param[3].integer.value = 0; 95 + input.count = 4; 96 + input.pointer = param; 97 + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); 98 + return status; 99 + } 100 + 101 + static acpi_status cmpc_stop_accel_v4(acpi_handle handle) 102 + { 103 + union acpi_object param[4]; 104 + struct acpi_object_list input; 105 + acpi_status status; 106 + 107 + param[0].type = ACPI_TYPE_INTEGER; 108 + param[0].integer.value = 0x4; 109 + param[1].type = ACPI_TYPE_INTEGER; 110 + param[1].integer.value = 0; 111 + param[2].type = ACPI_TYPE_INTEGER; 112 + param[2].integer.value = 0; 113 + param[3].type = ACPI_TYPE_INTEGER; 114 + param[3].integer.value = 0; 115 + input.count = 4; 116 + input.pointer = param; 117 + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); 118 + return status; 119 + } 120 + 121 + static acpi_status cmpc_accel_set_sensitivity_v4(acpi_handle handle, int val) 122 + { 123 + union acpi_object param[4]; 124 + struct acpi_object_list input; 125 + 126 + param[0].type = ACPI_TYPE_INTEGER; 127 + param[0].integer.value = 0x02; 128 + param[1].type = ACPI_TYPE_INTEGER; 129 + param[1].integer.value = val; 130 + param[2].type = ACPI_TYPE_INTEGER; 131 + param[2].integer.value = 0; 132 + param[3].type = ACPI_TYPE_INTEGER; 133 + param[3].integer.value = 0; 134 + input.count = 4; 135 + input.pointer = param; 136 + return acpi_evaluate_object(handle, "ACMD", &input, NULL); 137 + } 138 + 139 + static acpi_status cmpc_accel_set_g_select_v4(acpi_handle handle, int val) 140 + { 141 + union acpi_object param[4]; 142 + struct acpi_object_list input; 143 + 144 + param[0].type = ACPI_TYPE_INTEGER; 145 + param[0].integer.value = 0x05; 146 + param[1].type = ACPI_TYPE_INTEGER; 147 + param[1].integer.value = val; 148 + param[2].type = ACPI_TYPE_INTEGER; 149 + param[2].integer.value = 0; 150 + param[3].type = ACPI_TYPE_INTEGER; 151 + param[3].integer.value = 0; 152 + input.count = 4; 153 + input.pointer = param; 154 + return acpi_evaluate_object(handle, "ACMD", &input, NULL); 155 + } 156 + 157 + static acpi_status cmpc_get_accel_v4(acpi_handle handle, 158 + int16_t *x, 159 + int16_t *y, 160 + int16_t *z) 161 + { 162 + union acpi_object param[4]; 163 + struct acpi_object_list input; 164 + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 165 + int16_t *locs; 166 + acpi_status status; 167 + 168 + param[0].type = ACPI_TYPE_INTEGER; 169 + param[0].integer.value = 0x01; 170 + param[1].type = ACPI_TYPE_INTEGER; 171 + param[1].integer.value = 0; 172 + param[2].type = ACPI_TYPE_INTEGER; 173 + param[2].integer.value = 0; 174 + param[3].type = ACPI_TYPE_INTEGER; 175 + param[3].integer.value = 0; 176 + input.count = 4; 177 + input.pointer = param; 178 + status = acpi_evaluate_object(handle, "ACMD", &input, &output); 179 + if (ACPI_SUCCESS(status)) { 180 + union acpi_object *obj; 181 + obj = output.pointer; 182 + locs = (int16_t *) obj->buffer.pointer; 183 + *x = locs[0]; 184 + *y = locs[1]; 185 + *z = locs[2]; 186 + kfree(output.pointer); 187 + } 188 + return status; 189 + } 190 + 191 + static void cmpc_accel_handler_v4(struct acpi_device *dev, u32 event) 192 + { 193 + if (event == 0x81) { 194 + int16_t x, y, z; 195 + acpi_status status; 196 + 197 + status = cmpc_get_accel_v4(dev->handle, &x, &y, &z); 198 + if (ACPI_SUCCESS(status)) { 199 + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); 200 + 201 + input_report_abs(inputdev, ABS_X, x); 202 + input_report_abs(inputdev, ABS_Y, y); 203 + input_report_abs(inputdev, ABS_Z, z); 204 + input_sync(inputdev); 205 + } 206 + } 207 + } 208 + 209 + static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev, 210 + struct device_attribute *attr, 211 + char *buf) 212 + { 213 + struct acpi_device *acpi; 214 + struct input_dev *inputdev; 215 + struct cmpc_accel *accel; 216 + 217 + acpi = to_acpi_device(dev); 218 + inputdev = dev_get_drvdata(&acpi->dev); 219 + accel = dev_get_drvdata(&inputdev->dev); 220 + 221 + return sprintf(buf, "%d\n", accel->sensitivity); 222 + } 223 + 224 + static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, 225 + struct device_attribute *attr, 226 + const char *buf, size_t count) 227 + { 228 + struct acpi_device *acpi; 229 + struct input_dev *inputdev; 230 + struct cmpc_accel *accel; 231 + unsigned long sensitivity; 232 + int r; 233 + 234 + acpi = to_acpi_device(dev); 235 + inputdev = dev_get_drvdata(&acpi->dev); 236 + accel = dev_get_drvdata(&inputdev->dev); 237 + 238 + r = kstrtoul(buf, 0, &sensitivity); 239 + if (r) 240 + return r; 241 + 242 + /* sensitivity must be between 1 and 127 */ 243 + if (sensitivity < 1 || sensitivity > 127) 244 + return -EINVAL; 245 + 246 + accel->sensitivity = sensitivity; 247 + cmpc_accel_set_sensitivity_v4(acpi->handle, sensitivity); 248 + 249 + return strnlen(buf, count); 250 + } 251 + 252 + static struct device_attribute cmpc_accel_sensitivity_attr_v4 = { 253 + .attr = { .name = "sensitivity", .mode = 0660 }, 254 + .show = cmpc_accel_sensitivity_show_v4, 255 + .store = cmpc_accel_sensitivity_store_v4 256 + }; 257 + 258 + static ssize_t cmpc_accel_g_select_show_v4(struct device *dev, 259 + struct device_attribute *attr, 260 + char *buf) 261 + { 262 + struct acpi_device *acpi; 263 + struct input_dev *inputdev; 264 + struct cmpc_accel *accel; 265 + 266 + acpi = to_acpi_device(dev); 267 + inputdev = dev_get_drvdata(&acpi->dev); 268 + accel = dev_get_drvdata(&inputdev->dev); 269 + 270 + return sprintf(buf, "%d\n", accel->g_select); 271 + } 272 + 273 + static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, 274 + struct device_attribute *attr, 275 + const char *buf, size_t count) 276 + { 277 + struct acpi_device *acpi; 278 + struct input_dev *inputdev; 279 + struct cmpc_accel *accel; 280 + unsigned long g_select; 281 + int r; 282 + 283 + acpi = to_acpi_device(dev); 284 + inputdev = dev_get_drvdata(&acpi->dev); 285 + accel = dev_get_drvdata(&inputdev->dev); 286 + 287 + r = kstrtoul(buf, 0, &g_select); 288 + if (r) 289 + return r; 290 + 291 + /* 0 means 1.5g, 1 means 6g, everything else is wrong */ 292 + if (g_select != 0 && g_select != 1) 293 + return -EINVAL; 294 + 295 + accel->g_select = g_select; 296 + cmpc_accel_set_g_select_v4(acpi->handle, g_select); 297 + 298 + return strnlen(buf, count); 299 + } 300 + 301 + static struct device_attribute cmpc_accel_g_select_attr_v4 = { 302 + .attr = { .name = "g_select", .mode = 0660 }, 303 + .show = cmpc_accel_g_select_show_v4, 304 + .store = cmpc_accel_g_select_store_v4 305 + }; 306 + 307 + static int cmpc_accel_open_v4(struct input_dev *input) 308 + { 309 + struct acpi_device *acpi; 310 + struct cmpc_accel *accel; 311 + 312 + acpi = to_acpi_device(input->dev.parent); 313 + accel = dev_get_drvdata(&input->dev); 314 + 315 + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); 316 + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); 317 + 318 + if (ACPI_SUCCESS(cmpc_start_accel_v4(acpi->handle))) { 319 + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_OPEN; 320 + return 0; 321 + } 322 + return -EIO; 323 + } 324 + 325 + static void cmpc_accel_close_v4(struct input_dev *input) 326 + { 327 + struct acpi_device *acpi; 328 + struct cmpc_accel *accel; 329 + 330 + acpi = to_acpi_device(input->dev.parent); 331 + accel = dev_get_drvdata(&input->dev); 332 + 333 + cmpc_stop_accel_v4(acpi->handle); 334 + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; 335 + } 336 + 337 + static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) 338 + { 339 + set_bit(EV_ABS, inputdev->evbit); 340 + input_set_abs_params(inputdev, ABS_X, -255, 255, 16, 0); 341 + input_set_abs_params(inputdev, ABS_Y, -255, 255, 16, 0); 342 + input_set_abs_params(inputdev, ABS_Z, -255, 255, 16, 0); 343 + inputdev->open = cmpc_accel_open_v4; 344 + inputdev->close = cmpc_accel_close_v4; 345 + } 346 + 347 + static int cmpc_accel_suspend_v4(struct device *dev) 348 + { 349 + struct input_dev *inputdev; 350 + struct cmpc_accel *accel; 351 + 352 + inputdev = dev_get_drvdata(dev); 353 + accel = dev_get_drvdata(&inputdev->dev); 354 + 355 + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) 356 + return cmpc_stop_accel_v4(to_acpi_device(dev)->handle); 357 + 358 + return 0; 359 + } 360 + 361 + static int cmpc_accel_resume_v4(struct device *dev) 362 + { 363 + struct input_dev *inputdev; 364 + struct cmpc_accel *accel; 365 + 366 + inputdev = dev_get_drvdata(dev); 367 + accel = dev_get_drvdata(&inputdev->dev); 368 + 369 + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) { 370 + cmpc_accel_set_sensitivity_v4(to_acpi_device(dev)->handle, 371 + accel->sensitivity); 372 + cmpc_accel_set_g_select_v4(to_acpi_device(dev)->handle, 373 + accel->g_select); 374 + 375 + if (ACPI_FAILURE(cmpc_start_accel_v4(to_acpi_device(dev)->handle))) 376 + return -EIO; 377 + } 378 + 379 + return 0; 380 + } 381 + 382 + static int cmpc_accel_add_v4(struct acpi_device *acpi) 383 + { 384 + int error; 385 + struct input_dev *inputdev; 386 + struct cmpc_accel *accel; 387 + 388 + accel = kmalloc(sizeof(*accel), GFP_KERNEL); 389 + if (!accel) 390 + return -ENOMEM; 391 + 392 + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; 393 + 394 + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; 395 + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); 396 + 397 + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); 398 + if (error) 399 + goto failed_sensitivity; 400 + 401 + accel->g_select = CMPC_ACCEL_G_SELECT_DEFAULT; 402 + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); 403 + 404 + error = device_create_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); 405 + if (error) 406 + goto failed_g_select; 407 + 408 + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel_v4", 409 + cmpc_accel_idev_init_v4); 410 + if (error) 411 + goto failed_input; 412 + 413 + inputdev = dev_get_drvdata(&acpi->dev); 414 + dev_set_drvdata(&inputdev->dev, accel); 415 + 416 + return 0; 417 + 418 + failed_input: 419 + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); 420 + failed_g_select: 421 + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); 422 + failed_sensitivity: 423 + kfree(accel); 424 + return error; 425 + } 426 + 427 + static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) 428 + { 429 + struct input_dev *inputdev; 430 + struct cmpc_accel *accel; 431 + 432 + inputdev = dev_get_drvdata(&acpi->dev); 433 + accel = dev_get_drvdata(&inputdev->dev); 434 + 435 + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); 436 + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); 437 + return cmpc_remove_acpi_notify_device(acpi); 438 + } 439 + 440 + static SIMPLE_DEV_PM_OPS(cmpc_accel_pm, cmpc_accel_suspend_v4, 441 + cmpc_accel_resume_v4); 442 + 443 + static const struct acpi_device_id cmpc_accel_device_ids_v4[] = { 444 + {CMPC_ACCEL_HID_V4, 0}, 445 + {"", 0} 446 + }; 447 + 448 + static struct acpi_driver cmpc_accel_acpi_driver_v4 = { 449 + .owner = THIS_MODULE, 450 + .name = "cmpc_accel_v4", 451 + .class = "cmpc_accel_v4", 452 + .ids = cmpc_accel_device_ids_v4, 453 + .ops = { 454 + .add = cmpc_accel_add_v4, 455 + .remove = cmpc_accel_remove_v4, 456 + .notify = cmpc_accel_handler_v4, 457 + }, 458 + .drv.pm = &cmpc_accel_pm, 459 + }; 460 + 461 + 462 + /* 463 + * Accelerometer code for Classmate versions prior to V4 86 464 */ 87 465 static acpi_status cmpc_start_accel(acpi_handle handle) 88 466 { ··· 1116 726 if (r) 1117 727 goto failed_accel; 1118 728 729 + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver_v4); 730 + if (r) 731 + goto failed_accel_v4; 732 + 1119 733 return r; 734 + 735 + failed_accel_v4: 736 + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); 1120 737 1121 738 failed_accel: 1122 739 acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); ··· 1140 743 1141 744 static void cmpc_exit(void) 1142 745 { 746 + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v4); 1143 747 acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); 1144 748 acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); 1145 749 acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver); ··· 1152 754 1153 755 static const struct acpi_device_id cmpc_device_ids[] = { 1154 756 {CMPC_ACCEL_HID, 0}, 757 + {CMPC_ACCEL_HID_V4, 0}, 1155 758 {CMPC_TABLET_HID, 0}, 1156 759 {CMPC_IPML_HID, 0}, 1157 760 {CMPC_KEYS_HID, 0},
+54
drivers/platform/x86/dell-laptop.c
··· 206 206 }, 207 207 .driver_data = &quirk_dell_vostro_v130, 208 208 }, 209 + { 210 + .callback = dmi_matched, 211 + .ident = "Dell Inspiron 5420", 212 + .matches = { 213 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 214 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), 215 + }, 216 + .driver_data = &quirk_dell_vostro_v130, 217 + }, 218 + { 219 + .callback = dmi_matched, 220 + .ident = "Dell Inspiron 5520", 221 + .matches = { 222 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 223 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), 224 + }, 225 + .driver_data = &quirk_dell_vostro_v130, 226 + }, 227 + { 228 + .callback = dmi_matched, 229 + .ident = "Dell Inspiron 5720", 230 + .matches = { 231 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 232 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), 233 + }, 234 + .driver_data = &quirk_dell_vostro_v130, 235 + }, 236 + { 237 + .callback = dmi_matched, 238 + .ident = "Dell Inspiron 7420", 239 + .matches = { 240 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 241 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), 242 + }, 243 + .driver_data = &quirk_dell_vostro_v130, 244 + }, 245 + { 246 + .callback = dmi_matched, 247 + .ident = "Dell Inspiron 7520", 248 + .matches = { 249 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 250 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), 251 + }, 252 + .driver_data = &quirk_dell_vostro_v130, 253 + }, 254 + { 255 + .callback = dmi_matched, 256 + .ident = "Dell Inspiron 7720", 257 + .matches = { 258 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 259 + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), 260 + }, 261 + .driver_data = &quirk_dell_vostro_v130, 262 + }, 209 263 { } 210 264 }; 211 265
+24 -1
drivers/platform/x86/eeepc-wmi.c
··· 79 79 { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */ 80 80 { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */ 81 81 { KE_KEY, 0xe8, { KEY_SCREENLOCK } }, 82 - { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } }, 82 + { KE_KEY, 0xe9, { KEY_DISPLAYTOGGLE } }, 83 83 { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } }, 84 84 { KE_KEY, 0xec, { KEY_CAMERA_UP } }, 85 85 { KE_KEY, 0xed, { KEY_CAMERA_DOWN } }, ··· 105 105 static struct quirk_entry quirk_asus_et2012_type3 = { 106 106 .scalar_panel_brightness = true, 107 107 .store_backlight_power = true, 108 + }; 109 + 110 + static struct quirk_entry quirk_asus_x101ch = { 111 + /* We need this when ACPI function doesn't do this well */ 112 + .wmi_backlight_power = true, 108 113 }; 109 114 110 115 static struct quirk_entry *quirks; ··· 161 156 DMI_MATCH(DMI_PRODUCT_NAME, "ET2012"), 162 157 }, 163 158 .driver_data = &quirk_asus_unknown, 159 + }, 160 + { 161 + .callback = dmi_matched, 162 + .ident = "ASUSTeK Computer INC. X101CH", 163 + .matches = { 164 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 165 + DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"), 166 + }, 167 + .driver_data = &quirk_asus_x101ch, 168 + }, 169 + { 170 + .callback = dmi_matched, 171 + .ident = "ASUSTeK Computer INC. 1015CX", 172 + .matches = { 173 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 174 + DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"), 175 + }, 176 + .driver_data = &quirk_asus_x101ch, 164 177 }, 165 178 {}, 166 179 };
+31 -10
drivers/platform/x86/samsung-laptop.c
··· 26 26 #include <linux/seq_file.h> 27 27 #include <linux/debugfs.h> 28 28 #include <linux/ctype.h> 29 - #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) 29 + #ifdef CONFIG_ACPI_VIDEO 30 30 #include <acpi/video.h> 31 31 #endif 32 32 ··· 1465 1465 DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ 1466 1466 }, 1467 1467 }, 1468 + /* DMI ids for laptops with bad Chassis Type */ 1469 + { 1470 + .ident = "R40/R41", 1471 + .matches = { 1472 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1473 + DMI_MATCH(DMI_PRODUCT_NAME, "R40/R41"), 1474 + DMI_MATCH(DMI_BOARD_NAME, "R40/R41"), 1475 + }, 1476 + }, 1468 1477 /* Specific DMI ids for laptop with quirks */ 1469 1478 { 1470 1479 .callback = samsung_dmi_matched, ··· 1515 1506 }, 1516 1507 .driver_data = &samsung_broken_acpi_video, 1517 1508 }, 1509 + { 1510 + .callback = samsung_dmi_matched, 1511 + .ident = "X360", 1512 + .matches = { 1513 + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 1514 + DMI_MATCH(DMI_PRODUCT_NAME, "X360"), 1515 + DMI_MATCH(DMI_BOARD_NAME, "X360"), 1516 + }, 1517 + .driver_data = &samsung_broken_acpi_video, 1518 + }, 1518 1519 { }, 1519 1520 }; 1520 1521 MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); ··· 1549 1530 samsung->quirks = quirks; 1550 1531 1551 1532 1552 - #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) 1533 + #ifdef CONFIG_ACPI 1534 + if (samsung->quirks->broken_acpi_video) 1535 + acpi_video_dmi_promote_vendor(); 1536 + 1553 1537 /* Don't handle backlight here if the acpi video already handle it */ 1554 1538 if (acpi_video_backlight_support()) { 1555 - if (samsung->quirks->broken_acpi_video) { 1556 - pr_info("Disabling ACPI video driver\n"); 1557 - acpi_video_unregister(); 1558 - } else { 1559 - samsung->handle_backlight = false; 1560 - } 1539 + samsung->handle_backlight = false; 1540 + } else if (samsung->quirks->broken_acpi_video) { 1541 + pr_info("Disabling ACPI video driver\n"); 1542 + #ifdef CONFIG_ACPI_VIDEO 1543 + acpi_video_unregister(); 1544 + #endif 1561 1545 } 1562 1546 #endif 1563 1547 ··· 1574 1552 1575 1553 #ifdef CONFIG_ACPI 1576 1554 /* Only log that if we are really on a sabi platform */ 1577 - if (acpi_video_backlight_support() && 1578 - !samsung->quirks->broken_acpi_video) 1555 + if (acpi_video_backlight_support()) 1579 1556 pr_info("Backlight controlled by ACPI video driver\n"); 1580 1557 #endif 1581 1558
+3 -2
drivers/platform/x86/thinkpad_acpi.c
··· 3015 3015 if (hotkey_dev_attributes) 3016 3016 delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); 3017 3017 3018 - kfree(hotkey_keycode_map); 3019 - 3020 3018 dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY, 3021 3019 "restoring original HKEY status and mask\n"); 3022 3020 /* yes, there is a bitwise or below, we want the ··· 5215 5217 led_classdev_unregister(&tpacpi_leds[i].led_classdev); 5216 5218 } 5217 5219 5220 + flush_workqueue(tpacpi_wq); 5218 5221 kfree(tpacpi_leds); 5219 5222 } 5220 5223 ··· 8935 8936 input_unregister_device(tpacpi_inputdev); 8936 8937 else 8937 8938 input_free_device(tpacpi_inputdev); 8939 + kfree(hotkey_keycode_map); 8938 8940 } 8939 8941 8940 8942 if (tpacpi_hwmon) ··· 8969 8969 kfree(thinkpad_id.bios_version_str); 8970 8970 kfree(thinkpad_id.ec_version_str); 8971 8971 kfree(thinkpad_id.model_str); 8972 + kfree(thinkpad_id.nummodel_str); 8972 8973 } 8973 8974 8974 8975
+10
include/linux/acpi.h
··· 190 190 191 191 extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle); 192 192 extern long acpi_is_video_device(struct acpi_device *device); 193 + extern void acpi_video_dmi_promote_vendor(void); 194 + extern void acpi_video_dmi_demote_vendor(void); 193 195 extern int acpi_video_backlight_support(void); 194 196 extern int acpi_video_display_switch_support(void); 195 197 ··· 205 203 static inline long acpi_is_video_device(struct acpi_device *device) 206 204 { 207 205 return 0; 206 + } 207 + 208 + static inline void acpi_video_dmi_promote_vendor(void) 209 + { 210 + } 211 + 212 + static inline void acpi_video_dmi_demote_vendor(void) 213 + { 208 214 } 209 215 210 216 static inline int acpi_video_backlight_support(void)