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

Merge tag 'platform-drivers-x86-v4.12-1' of git://git.infradead.org/linux-platform-drivers-x86

Pull x86 platform-drivers update from Darren Hart:
"This represents a significantly larger and more complex set of changes
than those of prior merge windows.

In particular, we had several changes with dependencies on other
subsystems which we felt were best managed through merges of immutable
branches, including one each from input, i2c, and leds. Two patches
for the watchdog subsystem are included after discussion with Wim and
Guenter following a collision in linux-next (this should be resolved
and you should only see these two appear in this pull request). These
are called out in the "External" section below.

Summary of changes:
- significant further cleanup of fujitsu-laptop and hp-wmi
- new model support for ideapad, asus, silead, and xiaomi
- new hotkeys for thinkpad and models using intel-vbtn
- dell keyboard backlight improvements
- build and dependency improvements
- intel * ipc fixes, cleanups, and api updates
- single isolated fixes noted below

External:
- watchdog: iTCO_wdt: Add PMC specific noreboot update api
- watchdog: iTCO_wdt: cleanup set/unset no_reboot_bit functions
- Merge branch 'ib/4.10-sparse-keymap-managed'
- Merge branch 'i2c/for-INT33FE'
- Merge branch 'linux-leds/dell-laptop-changes-for-4.12'

platform/x86:
- Add Intel Cherry Trail ACPI INT33FE device driver
- remove sparse_keymap_free() calls
- Make SILEAD_DMI depend on TOUCHSCREEN_SILEAD

asus-wmi:
- try to set als by default
- fix cpufv sysfs file permission

acer-wmi:
- setup accelerometer when ACPI device was found

ideapad-laptop:
- Add IdeaPad V310-15ISK to no_hw_rfkill
- Add IdeaPad 310-15IKB to no_hw_rfkill

intel_pmc_ipc:
- use gcr mem base for S0ix counter read
- Fix iTCO_wdt GCS memory mapping failure
- Add pmc gcr read/write/update api's
- fix gcr offset

dell-laptop:
- Add keyboard backlight timeout AC settings
- Handle return error form dell_get_intensity.
- Protect kbd_state against races
- Refactor kbd_led_triggers_store()

hp-wireless:
- reuse module_acpi_driver
- add Xiaomi's hardware id to the supported list

intel-vbtn:
- add volume up and down

INT33FE:
- add i2c dependency

hp-wmi:
- Cleanup exit paths
- Do not shadow errors in sysfs show functions
- Use DEVICE_ATTR_(RO|RW) helper macros
- Refactor dock and tablet state fetchers
- Cleanup wireless get_(hw|sw)state functions
- Refactor redundant HPWMI_READ functions
- Standardize enum usage for constants
- Cleanup local variable declarations
- Do not shadow error values
- Fix detection for dock and tablet mode
- Fix error value for hp_wmi_tablet_state

fujitsu-laptop:
- simplify error handling in acpi_fujitsu_laptop_add()
- do not log LED registration failures
- switch to managed LED class devices
- reorganize LED-related code
- refactor LED registration
- select LEDS_CLASS
- remove redundant fields from struct fujitsu_bl
- account for backlight power when determining brightness
- do not log set_lcd_level() failures in bl_update_status()
- ignore errors when setting backlight power
- make disable_brightness_adjust a boolean
- clean up use_alt_lcd_levels handling
- sync brightness in set_lcd_level()
- simplify set_lcd_level()
- merge set_lcd_level_alt() into set_lcd_level()
- switch to a managed backlight device
- only handle backlight when appropriate
- update debug message logged by call_fext_func()
- rename call_fext_func() arguments
- simplify call_fext_func()
- clean up local variables in call_fext_func()
- remove keycode fields from struct fujitsu_bl
- model-dependent sparse keymap overrides
- use a sparse keymap for hotkey event generation
- switch to a managed hotkey input device
- refactor hotkey input device setup
- use a sparse keymap for brightness key events
- switch to a managed backlight input device
- refactor backlight input device setup
- remove pf_device field from struct fujitsu_bl
- only register platform device if FUJ02E3 is present
- add and remove platform device in separate functions
- simplify platform device attribute definitions
- remove backlight-related attributes from the platform device
- cleanup error labels in fujitsu_init()
- only register backlight device if FUJ02B1 is present
- sync backlight power status in acpi_fujitsu_laptop_add()
- register backlight device in a separate function
- simplify brightness key event generation logic
- decrease indentation in acpi_fujitsu_bl_notify()

intel-hid:
- Add missing ->thaw callback
- do not set parents of input devices explicitly
- remove redundant set_bit() call
- use devm_input_allocate_device() for HID events input device
- make intel_hid_set_enable() take a boolean argument
- simplify enabling/disabling HID events

silead_dmi:
- Add touchscreen info for Surftab Wintron 7.0
- Abort early if DMI does not match
- Do not treat all devices as i2c_clients
- Add entry for Insyde 7W tablets
- Constify properties arrays

intel_scu_ipc:
- Introduce intel_scu_ipc_raw_command()
- Introduce SCU_DEVICE() macro
- Remove redundant subarch check
- Rearrange init sequence
- Platform data is mandatory

asus-nb-wmi:
- Add wapf4 quirk for the X302UA

dell-*:
- Call new led hw_changed API on kbd brightness change
- Add a generic dell-laptop notifier chain

eeepc-laptop:
- Skip unknown key messages 0x50 0x51

thinkpad_acpi:
- add mapping for new hotkeys
- guard generic hotkey case"

* tag 'platform-drivers-x86-v4.12-1' of git://git.infradead.org/linux-platform-drivers-x86: (108 commits)
platform/x86: Make SILEAD_DMI depend on TOUCHSCREEN_SILEAD
platform/x86: asus-wmi: try to set als by default
platform/x86: asus-wmi: fix cpufv sysfs file permission
platform/x86: acer-wmi: setup accelerometer when ACPI device was found
platform/x86: ideapad-laptop: Add IdeaPad V310-15ISK to no_hw_rfkill
platform/x86: intel_pmc_ipc: use gcr mem base for S0ix counter read
platform/x86: intel_pmc_ipc: Fix iTCO_wdt GCS memory mapping failure
watchdog: iTCO_wdt: Add PMC specific noreboot update api
watchdog: iTCO_wdt: cleanup set/unset no_reboot_bit functions
platform/x86: intel_pmc_ipc: Add pmc gcr read/write/update api's
platform/x86: intel_pmc_ipc: fix gcr offset
platform/x86: dell-laptop: Add keyboard backlight timeout AC settings
platform/x86: dell-laptop: Handle return error form dell_get_intensity.
platform/x86: hp-wireless: reuse module_acpi_driver
platform/x86: intel-vbtn: add volume up and down
platform/x86: INT33FE: add i2c dependency
platform/x86: hp-wmi: Cleanup exit paths
platform/x86: hp-wmi: Do not shadow errors in sysfs show functions
platform/x86: hp-wmi: Use DEVICE_ATTR_(RO|RW) helper macros
platform/x86: hp-wmi: Refactor dock and tablet state fetchers
...

+1629 -1305
+23
arch/x86/include/asm/intel_pmc_ipc.h
··· 23 23 #define IPC_ERR_EMSECURITY 6 24 24 #define IPC_ERR_UNSIGNEDKERNEL 7 25 25 26 + /* GCR reg offsets from gcr base*/ 27 + #define PMC_GCR_PMC_CFG_REG 0x08 28 + #define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78 29 + #define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80 30 + 26 31 #if IS_ENABLED(CONFIG_INTEL_PMC_IPC) 27 32 28 33 int intel_pmc_ipc_simple_command(int cmd, int sub); ··· 36 31 int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 37 32 u32 *out, u32 outlen); 38 33 int intel_pmc_s0ix_counter_read(u64 *data); 34 + int intel_pmc_gcr_read(u32 offset, u32 *data); 35 + int intel_pmc_gcr_write(u32 offset, u32 data); 36 + int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val); 39 37 40 38 #else 41 39 ··· 60 52 } 61 53 62 54 static inline int intel_pmc_s0ix_counter_read(u64 *data) 55 + { 56 + return -EINVAL; 57 + } 58 + 59 + static inline int intel_pmc_gcr_read(u32 offset, u32 *data) 60 + { 61 + return -EINVAL; 62 + } 63 + 64 + static inline int intel_pmc_gcr_write(u32 offset, u32 data) 65 + { 66 + return -EINVAL; 67 + } 68 + 69 + static inline int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) 63 70 { 64 71 return -EINVAL; 65 72 }
+7 -1
arch/x86/include/asm/intel_scu_ipc.h
··· 3 3 4 4 #include <linux/notifier.h> 5 5 6 + #define IPCMSG_INDIRECT_READ 0x02 7 + #define IPCMSG_INDIRECT_WRITE 0x05 8 + 6 9 #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ 7 10 8 11 #define IPCMSG_WARM_RESET 0xF0 ··· 48 45 /* Issue commands to the SCU with or without data */ 49 46 int intel_scu_ipc_simple_command(int cmd, int sub); 50 47 int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 51 - u32 *out, int outlen); 48 + u32 *out, int outlen); 49 + int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen, 50 + u32 *out, int outlen, u32 dptr, u32 sptr); 51 + 52 52 /* I2C control api */ 53 53 int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data); 54 54
+16 -2
drivers/platform/x86/Kconfig
··· 182 182 depends on INPUT 183 183 depends on BACKLIGHT_CLASS_DEVICE 184 184 depends on ACPI_VIDEO || ACPI_VIDEO = n 185 - depends on LEDS_CLASS || LEDS_CLASS=n 185 + select INPUT_SPARSEKMAP 186 + select LEDS_CLASS 186 187 ---help--- 187 188 This is a driver for laptops built by Fujitsu: 188 189 ··· 781 780 keys as input device, backlight device, tablet and accelerometer 782 781 devices. 783 782 783 + config INTEL_CHT_INT33FE 784 + tristate "Intel Cherry Trail ACPI INT33FE Driver" 785 + depends on X86 && ACPI && I2C 786 + ---help--- 787 + This driver add support for the INT33FE ACPI device found on 788 + some Intel Cherry Trail devices. 789 + 790 + The INT33FE ACPI device has a CRS table with I2cSerialBusV2 791 + resources for 3 devices: Maxim MAX17047 Fuel Gauge Controller, 792 + FUSB302 USB Type-C Controller and PI3USB30532 USB switch. 793 + This driver instantiates i2c-clients for these, so that standard 794 + i2c drivers for these chips can bind to the them. 795 + 784 796 config INTEL_HID_EVENT 785 797 tristate "INTEL HID Event" 786 798 depends on ACPI ··· 1101 1087 1102 1088 config SILEAD_DMI 1103 1089 bool "Tablets with Silead touchscreens" 1104 - depends on ACPI && DMI && I2C=y && INPUT 1090 + depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD 1105 1091 ---help--- 1106 1092 Certain ACPI based tablets with Silead touchscreens do not have 1107 1093 enough data in ACPI tables for the touchscreen driver to handle
+1
drivers/platform/x86/Makefile
··· 45 45 obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 46 46 obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o 47 47 obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o 48 + obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o 48 49 obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o 49 50 obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o 50 51 obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
+5 -9
drivers/platform/x86/acer-wmi.c
··· 1896 1896 if (!strcmp(ctx, "SENR")) { 1897 1897 if (acpi_bus_get_device(ah, &dev)) 1898 1898 return AE_OK; 1899 - if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) 1899 + if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) 1900 1900 return AE_OK; 1901 1901 } else 1902 1902 return AE_OK; ··· 1917 1917 handle = NULL; 1918 1918 status = acpi_get_devices(prop, acer_wmi_get_handle_cb, 1919 1919 (void *)name, &handle); 1920 - 1921 - if (ACPI_SUCCESS(status)) { 1920 + if (ACPI_SUCCESS(status) && handle) { 1922 1921 *ah = handle; 1923 1922 return 0; 1924 1923 } else { ··· 1986 1987 acer_wmi_notify, NULL); 1987 1988 if (ACPI_FAILURE(status)) { 1988 1989 err = -EIO; 1989 - goto err_free_keymap; 1990 + goto err_free_dev; 1990 1991 } 1991 1992 1992 1993 err = input_register_device(acer_wmi_input_dev); ··· 1997 1998 1998 1999 err_uninstall_notifier: 1999 2000 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 2000 - err_free_keymap: 2001 - sparse_keymap_free(acer_wmi_input_dev); 2002 2001 err_free_dev: 2003 2002 input_free_device(acer_wmi_input_dev); 2004 2003 return err; ··· 2005 2008 static void acer_wmi_input_destroy(void) 2006 2009 { 2007 2010 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 2008 - sparse_keymap_free(acer_wmi_input_dev); 2009 2011 input_unregister_device(acer_wmi_input_dev); 2010 2012 } 2011 2013 ··· 2286 2290 if (err) 2287 2291 return err; 2288 2292 err = acer_wmi_accel_setup(); 2289 - if (err) 2290 - return err; 2293 + if (err && err != -ENODEV) 2294 + pr_warn("Cannot enable accelerometer\n"); 2291 2295 } 2292 2296 2293 2297 err = platform_driver_register(&acer_platform_driver);
+2 -6
drivers/platform/x86/asus-laptop.c
··· 1516 1516 error = input_register_device(input); 1517 1517 if (error) { 1518 1518 pr_warn("Unable to register input device\n"); 1519 - goto err_free_keymap; 1519 + goto err_free_dev; 1520 1520 } 1521 1521 1522 1522 asus->inputdev = input; 1523 1523 return 0; 1524 1524 1525 - err_free_keymap: 1526 - sparse_keymap_free(input); 1527 1525 err_free_dev: 1528 1526 input_free_device(input); 1529 1527 return error; ··· 1529 1531 1530 1532 static void asus_input_exit(struct asus_laptop *asus) 1531 1533 { 1532 - if (asus->inputdev) { 1533 - sparse_keymap_free(asus->inputdev); 1534 + if (asus->inputdev) 1534 1535 input_unregister_device(asus->inputdev); 1535 - } 1536 1536 asus->inputdev = NULL; 1537 1537 } 1538 1538
+22
drivers/platform/x86/asus-nb-wmi.c
··· 111 111 .xusb2pr = 0x01D9, 112 112 }; 113 113 114 + static struct quirk_entry quirk_asus_ux330uak = { 115 + .wmi_force_als_set = true, 116 + }; 117 + 114 118 static int dmi_matched(const struct dmi_system_id *dmi) 115 119 { 116 120 pr_info("Identified laptop model '%s'\n", dmi->ident); ··· 144 140 * machines need quirk_asus_x55u / wmi_backlight_power but 145 141 * here acpi-video seems to work fine for backlight control. 146 142 */ 143 + .driver_data = &quirk_asus_wapf4, 144 + }, 145 + { 146 + .callback = dmi_matched, 147 + .ident = "ASUSTeK COMPUTER INC. X302UA", 148 + .matches = { 149 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 150 + DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"), 151 + }, 147 152 .driver_data = &quirk_asus_wapf4, 148 153 }, 149 154 { ··· 379 366 DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), 380 367 }, 381 368 .driver_data = &quirk_asus_ux303ub, 369 + }, 370 + { 371 + .callback = dmi_matched, 372 + .ident = "ASUSTeK COMPUTER INC. UX330UAK", 373 + .matches = { 374 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 375 + DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"), 376 + }, 377 + .driver_data = &quirk_asus_ux330uak, 382 378 }, 383 379 { 384 380 .callback = dmi_matched,
+16 -8
drivers/platform/x86/asus-wmi.c
··· 269 269 270 270 err = input_register_device(asus->inputdev); 271 271 if (err) 272 - goto err_free_keymap; 272 + goto err_free_dev; 273 273 274 274 return 0; 275 275 276 - err_free_keymap: 277 - sparse_keymap_free(asus->inputdev); 278 276 err_free_dev: 279 277 input_free_device(asus->inputdev); 280 278 return err; ··· 280 282 281 283 static void asus_wmi_input_exit(struct asus_wmi *asus) 282 284 { 283 - if (asus->inputdev) { 284 - sparse_keymap_free(asus->inputdev); 285 + if (asus->inputdev) 285 286 input_unregister_device(asus->inputdev); 286 - } 287 287 288 288 asus->inputdev = NULL; 289 289 } ··· 1105 1109 } 1106 1110 1107 1111 /* 1112 + * Some devices dont support or have borcken get_als method 1113 + * but still support set method. 1114 + */ 1115 + static void asus_wmi_set_als(void) 1116 + { 1117 + asus_wmi_set_devstate(ASUS_WMI_DEVID_ALS_ENABLE, 1, NULL); 1118 + } 1119 + 1120 + /* 1108 1121 * Hwmon device 1109 1122 */ 1110 1123 static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, ··· 1766 1761 ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME); 1767 1762 ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE); 1768 1763 1769 - static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 1764 + static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr, 1770 1765 const char *buf, size_t count) 1771 1766 { 1772 1767 int value, rv; ··· 1783 1778 return count; 1784 1779 } 1785 1780 1786 - static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 1781 + static DEVICE_ATTR_WO(cpufv); 1787 1782 1788 1783 static struct attribute *platform_attributes[] = { 1789 1784 &dev_attr_cpufv.attr, ··· 2121 2116 if (err) 2122 2117 goto fail_rfkill; 2123 2118 } 2119 + 2120 + if (asus->driver->quirks->wmi_force_als_set) 2121 + asus_wmi_set_als(); 2124 2122 2125 2123 /* Some Asus desktop boards export an acpi-video backlight interface, 2126 2124 stop this from showing up */
+1
drivers/platform/x86/asus-wmi.h
··· 44 44 bool store_backlight_power; 45 45 bool wmi_backlight_power; 46 46 bool wmi_backlight_native; 47 + bool wmi_force_als_set; 47 48 int wapf; 48 49 /* 49 50 * For machines with AMD graphic chips, it will send out WMI event
+189 -65
drivers/platform/x86/dell-laptop.c
··· 45 45 #define KBD_LED_AUTO_100_TOKEN 0x02F6 46 46 #define GLOBAL_MIC_MUTE_ENABLE 0x0364 47 47 #define GLOBAL_MIC_MUTE_DISABLE 0x0365 48 + #define KBD_LED_AC_TOKEN 0x0451 48 49 49 50 struct quirk_entry { 50 51 u8 touchpad_led; ··· 1028 1027 * bit 2 Pointing stick 1029 1028 * bit 3 Any mouse 1030 1029 * bits 4-7 Reserved for future use 1031 - * cbRES2, byte3 Current Timeout 1030 + * cbRES2, byte3 Current Timeout on battery 1032 1031 * bits 7:6 Timeout units indicator: 1033 1032 * 00b Seconds 1034 1033 * 01b Minutes ··· 1040 1039 * cbRES3, byte0 Current setting of ALS value that turns the light on or off. 1041 1040 * cbRES3, byte1 Current ALS reading 1042 1041 * cbRES3, byte2 Current keyboard light level. 1042 + * cbRES3, byte3 Current timeout on AC Power 1043 + * bits 7:6 Timeout units indicator: 1044 + * 00b Seconds 1045 + * 01b Minutes 1046 + * 10b Hours 1047 + * 11b Days 1048 + * Bits 5:0 Timeout value (0-63) in sec/min/hr/day 1049 + * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte2 1050 + * are set upon return from the upon return from the [Get Feature information] call. 1043 1051 * 1044 1052 * cbArg1 0x2 = Set New State 1045 1053 * cbRES1 Standard return codes (0, -1, -2) ··· 1071 1061 * bit 2 Pointing stick 1072 1062 * bit 3 Any mouse 1073 1063 * bits 4-7 Reserved for future use 1074 - * cbArg2, byte3 Desired Timeout 1064 + * cbArg2, byte3 Desired Timeout on battery 1075 1065 * bits 7:6 Timeout units indicator: 1076 1066 * 00b Seconds 1077 1067 * 01b Minutes ··· 1080 1070 * bits 5:0 Timeout value (0-63) in sec/min/hr/day 1081 1071 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off. 1082 1072 * cbArg3, byte2 Desired keyboard light level. 1073 + * cbArg3, byte3 Desired Timeout on AC power 1074 + * bits 7:6 Timeout units indicator: 1075 + * 00b Seconds 1076 + * 01b Minutes 1077 + * 10b Hours 1078 + * 11b Days 1079 + * bits 5:0 Timeout value (0-63) in sec/min/hr/day 1083 1080 */ 1084 1081 1085 1082 ··· 1132 1115 u8 triggers; 1133 1116 u8 timeout_value; 1134 1117 u8 timeout_unit; 1118 + u8 timeout_value_ac; 1119 + u8 timeout_unit_ac; 1135 1120 u8 als_setting; 1136 1121 u8 als_value; 1137 1122 u8 level; ··· 1153 1134 static struct kbd_info kbd_info; 1154 1135 static bool kbd_als_supported; 1155 1136 static bool kbd_triggers_supported; 1137 + static bool kbd_timeout_ac_supported; 1156 1138 1157 1139 static u8 kbd_mode_levels[16]; 1158 1140 static int kbd_mode_levels_count; ··· 1162 1142 static u8 kbd_previous_mode_bit; 1163 1143 1164 1144 static bool kbd_led_present; 1145 + static DEFINE_MUTEX(kbd_led_mutex); 1165 1146 1166 1147 /* 1167 1148 * NOTE: there are three ways to set the keyboard backlight level. ··· 1293 1272 state->als_setting = buffer->output[2] & 0xFF; 1294 1273 state->als_value = (buffer->output[2] >> 8) & 0xFF; 1295 1274 state->level = (buffer->output[2] >> 16) & 0xFF; 1275 + state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F; 1276 + state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3; 1296 1277 1297 1278 out: 1298 1279 dell_smbios_release_buffer(); ··· 1314 1291 buffer->input[1] |= (state->timeout_unit & 0x3) << 30; 1315 1292 buffer->input[2] = state->als_setting & 0xFF; 1316 1293 buffer->input[2] |= (state->level & 0xFF) << 16; 1294 + buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24; 1295 + buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30; 1317 1296 dell_smbios_send_request(4, 11); 1318 1297 ret = buffer->output[0]; 1319 1298 dell_smbios_release_buffer(); ··· 1421 1396 ret = kbd_get_info(&kbd_info); 1422 1397 if (ret) 1423 1398 return ret; 1399 + 1400 + /* NOTE: Old models without KBD_LED_AC_TOKEN token supports only one 1401 + * timeout value which is shared for both battery and AC power 1402 + * settings. So do not try to set AC values on old models. 1403 + */ 1404 + if (dell_smbios_find_token(KBD_LED_AC_TOKEN)) 1405 + kbd_timeout_ac_supported = true; 1424 1406 1425 1407 kbd_get_state(&state); 1426 1408 ··· 1603 1571 } 1604 1572 } 1605 1573 1574 + mutex_lock(&kbd_led_mutex); 1575 + 1606 1576 ret = kbd_get_state(&state); 1607 1577 if (ret) 1608 - return ret; 1578 + goto out; 1609 1579 1610 1580 new_state = state; 1611 - new_state.timeout_value = value; 1612 - new_state.timeout_unit = unit; 1581 + 1582 + if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) { 1583 + new_state.timeout_value_ac = value; 1584 + new_state.timeout_unit_ac = unit; 1585 + } else { 1586 + new_state.timeout_value = value; 1587 + new_state.timeout_unit = unit; 1588 + } 1613 1589 1614 1590 ret = kbd_set_state_safe(&new_state, &state); 1615 1591 if (ret) 1616 - return ret; 1592 + goto out; 1617 1593 1618 - return count; 1594 + ret = count; 1595 + out: 1596 + mutex_unlock(&kbd_led_mutex); 1597 + return ret; 1619 1598 } 1620 1599 1621 1600 static ssize_t kbd_led_timeout_show(struct device *dev, 1622 1601 struct device_attribute *attr, char *buf) 1623 1602 { 1624 1603 struct kbd_state state; 1604 + int value; 1625 1605 int ret; 1626 1606 int len; 1607 + u8 unit; 1627 1608 1628 1609 ret = kbd_get_state(&state); 1629 1610 if (ret) 1630 1611 return ret; 1631 1612 1632 - len = sprintf(buf, "%d", state.timeout_value); 1613 + if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) { 1614 + value = state.timeout_value_ac; 1615 + unit = state.timeout_unit_ac; 1616 + } else { 1617 + value = state.timeout_value; 1618 + unit = state.timeout_unit; 1619 + } 1633 1620 1634 - switch (state.timeout_unit) { 1621 + len = sprintf(buf, "%d", value); 1622 + 1623 + switch (unit) { 1635 1624 case KBD_TIMEOUT_SECONDS: 1636 1625 return len + sprintf(buf+len, "s\n"); 1637 1626 case KBD_TIMEOUT_MINUTES: ··· 1696 1643 if (trigger[0] != '+' && trigger[0] != '-') 1697 1644 return -EINVAL; 1698 1645 1646 + mutex_lock(&kbd_led_mutex); 1647 + 1699 1648 ret = kbd_get_state(&state); 1700 1649 if (ret) 1701 - return ret; 1650 + goto out; 1702 1651 1703 1652 if (kbd_triggers_supported) 1704 1653 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit); ··· 1714 1659 if (strcmp(trigger+1, kbd_led_triggers[i]) != 0) 1715 1660 continue; 1716 1661 if (trigger[0] == '+' && 1717 - triggers_enabled && (state.triggers & BIT(i))) 1718 - return count; 1662 + triggers_enabled && (state.triggers & BIT(i))) { 1663 + ret = count; 1664 + goto out; 1665 + } 1719 1666 if (trigger[0] == '-' && 1720 - (!triggers_enabled || !(state.triggers & BIT(i)))) 1721 - return count; 1667 + (!triggers_enabled || !(state.triggers & BIT(i)))) { 1668 + ret = count; 1669 + goto out; 1670 + } 1722 1671 trigger_bit = i; 1723 1672 break; 1724 1673 } 1725 1674 } 1726 1675 1727 - if (trigger_bit != -1) { 1728 - new_state = state; 1729 - if (trigger[0] == '+') 1730 - new_state.triggers |= BIT(trigger_bit); 1731 - else { 1732 - new_state.triggers &= ~BIT(trigger_bit); 1733 - /* NOTE: trackstick bit (2) must be disabled when 1734 - * disabling touchpad bit (1), otherwise touchpad 1735 - * bit (1) will not be disabled */ 1736 - if (trigger_bit == 1) 1737 - new_state.triggers &= ~BIT(2); 1738 - } 1739 - if ((kbd_info.triggers & new_state.triggers) != 1740 - new_state.triggers) 1741 - return -EINVAL; 1742 - if (new_state.triggers && !triggers_enabled) { 1743 - new_state.mode_bit = KBD_MODE_BIT_TRIGGER; 1744 - kbd_set_level(&new_state, kbd_previous_level); 1745 - } else if (new_state.triggers == 0) { 1746 - kbd_set_level(&new_state, 0); 1747 - } 1748 - if (!(kbd_info.modes & BIT(new_state.mode_bit))) 1749 - return -EINVAL; 1750 - ret = kbd_set_state_safe(&new_state, &state); 1751 - if (ret) 1752 - return ret; 1753 - if (new_state.mode_bit != KBD_MODE_BIT_OFF) 1754 - kbd_previous_mode_bit = new_state.mode_bit; 1755 - return count; 1676 + if (trigger_bit == -1) { 1677 + ret = -EINVAL; 1678 + goto out; 1756 1679 } 1757 1680 1758 - return -EINVAL; 1681 + new_state = state; 1682 + if (trigger[0] == '+') 1683 + new_state.triggers |= BIT(trigger_bit); 1684 + else { 1685 + new_state.triggers &= ~BIT(trigger_bit); 1686 + /* 1687 + * NOTE: trackstick bit (2) must be disabled when 1688 + * disabling touchpad bit (1), otherwise touchpad 1689 + * bit (1) will not be disabled 1690 + */ 1691 + if (trigger_bit == 1) 1692 + new_state.triggers &= ~BIT(2); 1693 + } 1694 + if ((kbd_info.triggers & new_state.triggers) != 1695 + new_state.triggers) { 1696 + ret = -EINVAL; 1697 + goto out; 1698 + } 1699 + if (new_state.triggers && !triggers_enabled) { 1700 + new_state.mode_bit = KBD_MODE_BIT_TRIGGER; 1701 + kbd_set_level(&new_state, kbd_previous_level); 1702 + } else if (new_state.triggers == 0) { 1703 + kbd_set_level(&new_state, 0); 1704 + } 1705 + if (!(kbd_info.modes & BIT(new_state.mode_bit))) { 1706 + ret = -EINVAL; 1707 + goto out; 1708 + } 1709 + ret = kbd_set_state_safe(&new_state, &state); 1710 + if (ret) 1711 + goto out; 1712 + if (new_state.mode_bit != KBD_MODE_BIT_OFF) 1713 + kbd_previous_mode_bit = new_state.mode_bit; 1714 + ret = count; 1715 + out: 1716 + mutex_unlock(&kbd_led_mutex); 1717 + return ret; 1759 1718 } 1760 1719 1761 1720 static ssize_t kbd_led_triggers_show(struct device *dev, ··· 1826 1757 if (ret) 1827 1758 return ret; 1828 1759 1760 + mutex_lock(&kbd_led_mutex); 1761 + 1829 1762 ret = kbd_get_state(&state); 1830 1763 if (ret) 1831 - return ret; 1764 + goto out; 1832 1765 1833 - if (enable == kbd_is_als_mode_bit(state.mode_bit)) 1834 - return count; 1766 + if (enable == kbd_is_als_mode_bit(state.mode_bit)) { 1767 + ret = count; 1768 + goto out; 1769 + } 1835 1770 1836 1771 new_state = state; 1837 1772 ··· 1855 1782 new_state.mode_bit = KBD_MODE_BIT_ON; 1856 1783 } 1857 1784 } 1858 - if (!(kbd_info.modes & BIT(new_state.mode_bit))) 1859 - return -EINVAL; 1785 + if (!(kbd_info.modes & BIT(new_state.mode_bit))) { 1786 + ret = -EINVAL; 1787 + goto out; 1788 + } 1860 1789 1861 1790 ret = kbd_set_state_safe(&new_state, &state); 1862 1791 if (ret) 1863 - return ret; 1792 + goto out; 1864 1793 kbd_previous_mode_bit = new_state.mode_bit; 1865 1794 1866 - return count; 1795 + ret = count; 1796 + out: 1797 + mutex_unlock(&kbd_led_mutex); 1798 + return ret; 1867 1799 } 1868 1800 1869 1801 static ssize_t kbd_led_als_enabled_show(struct device *dev, ··· 1903 1825 if (ret) 1904 1826 return ret; 1905 1827 1828 + mutex_lock(&kbd_led_mutex); 1829 + 1906 1830 ret = kbd_get_state(&state); 1907 1831 if (ret) 1908 - return ret; 1832 + goto out; 1909 1833 1910 1834 new_state = state; 1911 1835 new_state.als_setting = setting; 1912 1836 1913 1837 ret = kbd_set_state_safe(&new_state, &state); 1914 1838 if (ret) 1915 - return ret; 1839 + goto out; 1916 1840 1917 - return count; 1841 + ret = count; 1842 + out: 1843 + mutex_unlock(&kbd_led_mutex); 1844 + return ret; 1918 1845 } 1919 1846 1920 1847 static ssize_t kbd_led_als_setting_show(struct device *dev, ··· 2004 1921 u16 num; 2005 1922 int ret; 2006 1923 1924 + mutex_lock(&kbd_led_mutex); 1925 + 2007 1926 if (kbd_get_max_level()) { 2008 1927 ret = kbd_get_state(&state); 2009 1928 if (ret) 2010 - return ret; 1929 + goto out; 2011 1930 new_state = state; 2012 1931 ret = kbd_set_level(&new_state, value); 2013 1932 if (ret) 2014 - return ret; 2015 - return kbd_set_state_safe(&new_state, &state); 2016 - } 2017 - 2018 - if (kbd_get_valid_token_counts()) { 1933 + goto out; 1934 + ret = kbd_set_state_safe(&new_state, &state); 1935 + } else if (kbd_get_valid_token_counts()) { 2019 1936 for (num = kbd_token_bits; num != 0 && value > 0; --value) 2020 1937 num &= num - 1; /* clear the first bit set */ 2021 1938 if (num == 0) 2022 - return 0; 2023 - return kbd_set_token_bit(ffs(num) - 1); 1939 + ret = 0; 1940 + else 1941 + ret = kbd_set_token_bit(ffs(num) - 1); 1942 + } else { 1943 + pr_warn("Keyboard brightness level control not supported\n"); 1944 + ret = -ENXIO; 2024 1945 } 2025 1946 2026 - pr_warn("Keyboard brightness level control not supported\n"); 2027 - return -ENXIO; 1947 + out: 1948 + mutex_unlock(&kbd_led_mutex); 1949 + return ret; 2028 1950 } 2029 1951 2030 1952 static struct led_classdev kbd_led = { 2031 1953 .name = "dell::kbd_backlight", 1954 + .flags = LED_BRIGHT_HW_CHANGED, 2032 1955 .brightness_set_blocking = kbd_led_level_set, 2033 1956 .brightness_get = kbd_led_level_get, 2034 1957 .groups = kbd_led_groups, ··· 2042 1953 2043 1954 static int __init kbd_led_init(struct device *dev) 2044 1955 { 1956 + int ret; 1957 + 2045 1958 kbd_init(); 2046 1959 if (!kbd_led_present) 2047 1960 return -ENODEV; ··· 2055 1964 if (kbd_led.max_brightness) 2056 1965 kbd_led.max_brightness--; 2057 1966 } 2058 - return led_classdev_register(dev, &kbd_led); 1967 + ret = led_classdev_register(dev, &kbd_led); 1968 + if (ret) 1969 + kbd_led_present = false; 1970 + 1971 + return ret; 2059 1972 } 2060 1973 2061 1974 static void brightness_set_exit(struct led_classdev *led_cdev, ··· 2075 1980 kbd_led.brightness_set = brightness_set_exit; 2076 1981 led_classdev_unregister(&kbd_led); 2077 1982 } 1983 + 1984 + static int dell_laptop_notifier_call(struct notifier_block *nb, 1985 + unsigned long action, void *data) 1986 + { 1987 + switch (action) { 1988 + case DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED: 1989 + if (!kbd_led_present) 1990 + break; 1991 + 1992 + led_classdev_notify_brightness_hw_changed(&kbd_led, 1993 + kbd_led_level_get(&kbd_led)); 1994 + break; 1995 + } 1996 + 1997 + return NOTIFY_OK; 1998 + } 1999 + 2000 + static struct notifier_block dell_laptop_notifier = { 2001 + .notifier_call = dell_laptop_notifier_call, 2002 + }; 2078 2003 2079 2004 int dell_micmute_led_set(int state) 2080 2005 { ··· 2164 2049 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, 2165 2050 &dell_debugfs_fops); 2166 2051 2052 + dell_laptop_register_notifier(&dell_laptop_notifier); 2053 + 2167 2054 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2168 2055 return 0; 2169 2056 ··· 2198 2081 2199 2082 dell_backlight_device->props.brightness = 2200 2083 dell_get_intensity(dell_backlight_device); 2084 + if (dell_backlight_device->props.brightness < 0) { 2085 + ret = dell_backlight_device->props.brightness; 2086 + goto fail_get_brightness; 2087 + } 2201 2088 backlight_update_status(dell_backlight_device); 2202 2089 } 2203 2090 2204 2091 return 0; 2205 2092 2093 + fail_get_brightness: 2094 + backlight_device_unregister(dell_backlight_device); 2206 2095 fail_backlight: 2207 2096 dell_cleanup_rfkill(); 2208 2097 fail_rfkill: ··· 2223 2100 2224 2101 static void __exit dell_exit(void) 2225 2102 { 2103 + dell_laptop_unregister_notifier(&dell_laptop_notifier); 2226 2104 debugfs_remove_recursive(dell_laptop_dir); 2227 2105 if (quirks && quirks->touchpad_led) 2228 2106 touchpad_led_exit();
+20
drivers/platform/x86/dell-smbios.c
··· 105 105 } 106 106 EXPORT_SYMBOL_GPL(dell_smbios_find_token); 107 107 108 + static BLOCKING_NOTIFIER_HEAD(dell_laptop_chain_head); 109 + 110 + int dell_laptop_register_notifier(struct notifier_block *nb) 111 + { 112 + return blocking_notifier_chain_register(&dell_laptop_chain_head, nb); 113 + } 114 + EXPORT_SYMBOL_GPL(dell_laptop_register_notifier); 115 + 116 + int dell_laptop_unregister_notifier(struct notifier_block *nb) 117 + { 118 + return blocking_notifier_chain_unregister(&dell_laptop_chain_head, nb); 119 + } 120 + EXPORT_SYMBOL_GPL(dell_laptop_unregister_notifier); 121 + 122 + void dell_laptop_call_notifier(unsigned long action, void *data) 123 + { 124 + blocking_notifier_call_chain(&dell_laptop_chain_head, action, data); 125 + } 126 + EXPORT_SYMBOL_GPL(dell_laptop_call_notifier); 127 + 108 128 static void __init parse_da_table(const struct dmi_header *dm) 109 129 { 110 130 /* Final token is a terminator, so we don't want to copy it */
+11
drivers/platform/x86/dell-smbios.h
··· 16 16 #ifndef _DELL_SMBIOS_H_ 17 17 #define _DELL_SMBIOS_H_ 18 18 19 + struct notifier_block; 20 + 19 21 /* This structure will be modified by the firmware when we enter 20 22 * system management mode, hence the volatiles */ 21 23 ··· 45 43 void dell_smbios_send_request(int class, int select); 46 44 47 45 struct calling_interface_token *dell_smbios_find_token(int tokenid); 46 + 47 + enum dell_laptop_notifier_actions { 48 + DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, 49 + }; 50 + 51 + int dell_laptop_register_notifier(struct notifier_block *nb); 52 + int dell_laptop_unregister_notifier(struct notifier_block *nb); 53 + void dell_laptop_call_notifier(unsigned long action, void *data); 54 + 48 55 #endif
+1 -5
drivers/platform/x86/dell-wmi-aio.c
··· 152 152 err = input_register_device(dell_wmi_aio_input_dev); 153 153 if (err) { 154 154 pr_info("Unable to register input device\n"); 155 - goto err_free_keymap; 155 + goto err_free_dev; 156 156 } 157 157 return 0; 158 158 159 - err_free_keymap: 160 - sparse_keymap_free(dell_wmi_aio_input_dev); 161 159 err_free_dev: 162 160 input_free_device(dell_wmi_aio_input_dev); 163 161 return err; ··· 190 192 err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL); 191 193 if (err) { 192 194 pr_err("Unable to register notify handler - %d\n", err); 193 - sparse_keymap_free(dell_wmi_aio_input_dev); 194 195 input_unregister_device(dell_wmi_aio_input_dev); 195 196 return err; 196 197 } ··· 203 206 204 207 guid = dell_wmi_aio_find(); 205 208 wmi_remove_notify_handler(guid); 206 - sparse_keymap_free(dell_wmi_aio_input_dev); 207 209 input_unregister_device(dell_wmi_aio_input_dev); 208 210 } 209 211
+8 -12
drivers/platform/x86/dell-wmi.c
··· 329 329 if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request) 330 330 return; 331 331 332 + if (key->keycode == KEY_KBDILLUMTOGGLE) 333 + dell_laptop_call_notifier( 334 + DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, NULL); 335 + 332 336 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true); 333 337 } 334 338 ··· 607 603 608 604 err = input_register_device(dell_wmi_input_dev); 609 605 if (err) 610 - goto err_free_keymap; 606 + goto err_free_dev; 611 607 612 608 return 0; 613 609 614 - err_free_keymap: 615 - sparse_keymap_free(dell_wmi_input_dev); 616 610 err_free_dev: 617 611 input_free_device(dell_wmi_input_dev); 618 612 return err; 619 - } 620 - 621 - static void dell_wmi_input_destroy(void) 622 - { 623 - sparse_keymap_free(dell_wmi_input_dev); 624 - input_unregister_device(dell_wmi_input_dev); 625 613 } 626 614 627 615 /* ··· 736 740 status = wmi_install_notify_handler(DELL_EVENT_GUID, 737 741 dell_wmi_notify, NULL); 738 742 if (ACPI_FAILURE(status)) { 739 - dell_wmi_input_destroy(); 743 + input_unregister_device(dell_wmi_input_dev); 740 744 pr_err("Unable to register notify handler - %d\n", status); 741 745 return -ENODEV; 742 746 } ··· 748 752 if (err) { 749 753 pr_err("Failed to enable WMI events\n"); 750 754 wmi_remove_notify_handler(DELL_EVENT_GUID); 751 - dell_wmi_input_destroy(); 755 + input_unregister_device(dell_wmi_input_dev); 752 756 return err; 753 757 } 754 758 } ··· 762 766 if (wmi_requires_smbios_request) 763 767 dell_wmi_events_set_enabled(false); 764 768 wmi_remove_notify_handler(DELL_EVENT_GUID); 765 - dell_wmi_input_destroy(); 769 + input_unregister_device(dell_wmi_input_dev); 766 770 } 767 771 module_exit(dell_wmi_exit);
+4 -6
drivers/platform/x86/eeepc-laptop.c
··· 150 150 { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, 151 151 { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ 152 152 { KE_KEY, 0x38, { KEY_F14 } }, 153 + { KE_IGNORE, 0x50, { KEY_RESERVED } }, /* AC plugged */ 154 + { KE_IGNORE, 0x51, { KEY_RESERVED } }, /* AC unplugged */ 153 155 { KE_END, 0 }, 154 156 }; 155 157 ··· 1207 1205 error = input_register_device(input); 1208 1206 if (error) { 1209 1207 pr_err("Unable to register input device\n"); 1210 - goto err_free_keymap; 1208 + goto err_free_dev; 1211 1209 } 1212 1210 1213 1211 eeepc->inputdev = input; 1214 1212 return 0; 1215 1213 1216 - err_free_keymap: 1217 - sparse_keymap_free(input); 1218 1214 err_free_dev: 1219 1215 input_free_device(input); 1220 1216 return error; ··· 1220 1220 1221 1221 static void eeepc_input_exit(struct eeepc_laptop *eeepc) 1222 1222 { 1223 - if (eeepc->inputdev) { 1224 - sparse_keymap_free(eeepc->inputdev); 1223 + if (eeepc->inputdev) 1225 1224 input_unregister_device(eeepc->inputdev); 1226 - } 1227 1225 eeepc->inputdev = NULL; 1228 1226 } 1229 1227
+479 -749
drivers/platform/x86/fujitsu-laptop.c
··· 32 32 * features made available on a range of Fujitsu laptops including the 33 33 * P2xxx/P5xxx/S6xxx/S7xxx series. 34 34 * 35 - * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/; 36 - * others may be added at a later date. 37 - * 38 - * lcd_level - Screen brightness: contains a single integer in the 39 - * range 0..7. (rw) 40 - * 41 - * In addition to these platform device attributes the driver 42 - * registers itself in the Linux backlight control subsystem and is 43 - * available to userspace under /sys/class/backlight/fujitsu-laptop/. 44 - * 45 - * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are 46 - * also supported by this driver. 35 + * This driver implements a vendor-specific backlight control interface for 36 + * Fujitsu laptops and provides support for hotkeys present on certain Fujitsu 37 + * laptops. 47 38 * 48 39 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and 49 40 * P8010. It should work on most P-series and S-series Lifebooks, but ··· 57 66 #include <linux/backlight.h> 58 67 #include <linux/fb.h> 59 68 #include <linux/input.h> 69 + #include <linux/input/sparse-keymap.h> 60 70 #include <linux/kfifo.h> 71 + #include <linux/leds.h> 61 72 #include <linux/platform_device.h> 62 73 #include <linux/slab.h> 63 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 64 - #include <linux/leds.h> 65 - #endif 66 74 #include <acpi/video.h> 67 75 68 76 #define FUJITSU_DRIVER_VERSION "0.6.0" ··· 92 102 #define FLAG_LID 0x100 93 103 #define FLAG_DOCK 0x200 94 104 95 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 96 105 /* FUNC interface - LED control */ 97 106 #define FUNC_LED_OFF 0x1 98 107 #define FUNC_LED_ON 0x30001 ··· 101 112 #define RADIO_LED_ON 0x20 102 113 #define ECO_LED 0x10000 103 114 #define ECO_LED_ON 0x80000 104 - #endif 105 115 106 116 /* Hotkey details */ 107 117 #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ ··· 131 143 /* Device controlling the backlight and associated keys */ 132 144 struct fujitsu_bl { 133 145 acpi_handle acpi_handle; 134 - struct acpi_device *dev; 135 146 struct input_dev *input; 136 147 char phys[32]; 137 148 struct backlight_device *bl_device; 138 - struct platform_device *pf_device; 139 - int keycode1, keycode2, keycode3, keycode4, keycode5; 140 - 141 149 unsigned int max_brightness; 142 - unsigned int brightness_changed; 143 150 unsigned int brightness_level; 144 151 }; 145 152 146 153 static struct fujitsu_bl *fujitsu_bl; 147 154 static int use_alt_lcd_levels = -1; 148 - static int disable_brightness_adjust = -1; 155 + static bool disable_brightness_adjust; 149 156 150 157 /* Device used to access hotkeys and other features on the laptop */ 151 158 struct fujitsu_laptop { ··· 153 170 spinlock_t fifo_lock; 154 171 int flags_supported; 155 172 int flags_state; 156 - int logolamp_registered; 157 - int kblamps_registered; 158 - int radio_led_registered; 159 - int eco_led_registered; 160 173 }; 161 174 162 175 static struct fujitsu_laptop *fujitsu_laptop; 163 - 164 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 165 - static enum led_brightness logolamp_get(struct led_classdev *cdev); 166 - static int logolamp_set(struct led_classdev *cdev, 167 - enum led_brightness brightness); 168 - 169 - static struct led_classdev logolamp_led = { 170 - .name = "fujitsu::logolamp", 171 - .brightness_get = logolamp_get, 172 - .brightness_set_blocking = logolamp_set 173 - }; 174 - 175 - static enum led_brightness kblamps_get(struct led_classdev *cdev); 176 - static int kblamps_set(struct led_classdev *cdev, 177 - enum led_brightness brightness); 178 - 179 - static struct led_classdev kblamps_led = { 180 - .name = "fujitsu::kblamps", 181 - .brightness_get = kblamps_get, 182 - .brightness_set_blocking = kblamps_set 183 - }; 184 - 185 - static enum led_brightness radio_led_get(struct led_classdev *cdev); 186 - static int radio_led_set(struct led_classdev *cdev, 187 - enum led_brightness brightness); 188 - 189 - static struct led_classdev radio_led = { 190 - .name = "fujitsu::radio_led", 191 - .default_trigger = "rfkill-any", 192 - .brightness_get = radio_led_get, 193 - .brightness_set_blocking = radio_led_set 194 - }; 195 - 196 - static enum led_brightness eco_led_get(struct led_classdev *cdev); 197 - static int eco_led_set(struct led_classdev *cdev, 198 - enum led_brightness brightness); 199 - 200 - static struct led_classdev eco_led = { 201 - .name = "fujitsu::eco_led", 202 - .brightness_get = eco_led_get, 203 - .brightness_set_blocking = eco_led_set 204 - }; 205 - #endif 206 176 207 177 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 208 178 static u32 dbg_level = 0x03; ··· 163 227 164 228 /* Fujitsu ACPI interface function */ 165 229 166 - static int call_fext_func(int cmd, int arg0, int arg1, int arg2) 230 + static int call_fext_func(int func, int op, int feature, int state) 167 231 { 168 - acpi_status status = AE_OK; 169 232 union acpi_object params[4] = { 170 - { .type = ACPI_TYPE_INTEGER }, 171 - { .type = ACPI_TYPE_INTEGER }, 172 - { .type = ACPI_TYPE_INTEGER }, 173 - { .type = ACPI_TYPE_INTEGER } 233 + { .integer.type = ACPI_TYPE_INTEGER, .integer.value = func }, 234 + { .integer.type = ACPI_TYPE_INTEGER, .integer.value = op }, 235 + { .integer.type = ACPI_TYPE_INTEGER, .integer.value = feature }, 236 + { .integer.type = ACPI_TYPE_INTEGER, .integer.value = state } 174 237 }; 175 - struct acpi_object_list arg_list = { 4, &params[0] }; 238 + struct acpi_object_list arg_list = { 4, params }; 176 239 unsigned long long value; 177 - acpi_handle handle = NULL; 240 + acpi_status status; 178 241 179 - status = acpi_get_handle(fujitsu_laptop->acpi_handle, "FUNC", &handle); 242 + status = acpi_evaluate_integer(fujitsu_laptop->acpi_handle, "FUNC", 243 + &arg_list, &value); 180 244 if (ACPI_FAILURE(status)) { 181 - vdbg_printk(FUJLAPTOP_DBG_ERROR, 182 - "FUNC interface is not present\n"); 245 + vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate FUNC\n"); 183 246 return -ENODEV; 184 247 } 185 248 186 - params[0].integer.value = cmd; 187 - params[1].integer.value = arg0; 188 - params[2].integer.value = arg1; 189 - params[3].integer.value = arg2; 190 - 191 - status = acpi_evaluate_integer(handle, NULL, &arg_list, &value); 192 - if (ACPI_FAILURE(status)) { 193 - vdbg_printk(FUJLAPTOP_DBG_WARN, 194 - "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n", 195 - cmd, arg0, arg1, arg2); 196 - return -ENODEV; 197 - } 198 - 199 - vdbg_printk(FUJLAPTOP_DBG_TRACE, 200 - "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", 201 - cmd, arg0, arg1, arg2, (int)value); 249 + vdbg_printk(FUJLAPTOP_DBG_TRACE, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", 250 + func, op, feature, state, (int)value); 202 251 return value; 203 252 } 204 - 205 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 206 - /* LED class callbacks */ 207 - 208 - static int logolamp_set(struct led_classdev *cdev, 209 - enum led_brightness brightness) 210 - { 211 - int poweron = FUNC_LED_ON, always = FUNC_LED_ON; 212 - int ret; 213 - 214 - if (brightness < LED_HALF) 215 - poweron = FUNC_LED_OFF; 216 - 217 - if (brightness < LED_FULL) 218 - always = FUNC_LED_OFF; 219 - 220 - ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron); 221 - if (ret < 0) 222 - return ret; 223 - 224 - return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always); 225 - } 226 - 227 - static int kblamps_set(struct led_classdev *cdev, 228 - enum led_brightness brightness) 229 - { 230 - if (brightness >= LED_FULL) 231 - return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON); 232 - else 233 - return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); 234 - } 235 - 236 - static int radio_led_set(struct led_classdev *cdev, 237 - enum led_brightness brightness) 238 - { 239 - if (brightness >= LED_FULL) 240 - return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, RADIO_LED_ON); 241 - else 242 - return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0); 243 - } 244 - 245 - static int eco_led_set(struct led_classdev *cdev, 246 - enum led_brightness brightness) 247 - { 248 - int curr; 249 - 250 - curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0); 251 - if (brightness >= LED_FULL) 252 - return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON); 253 - else 254 - return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON); 255 - } 256 - 257 - static enum led_brightness logolamp_get(struct led_classdev *cdev) 258 - { 259 - int ret; 260 - 261 - ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); 262 - if (ret == FUNC_LED_ON) 263 - return LED_FULL; 264 - 265 - ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); 266 - if (ret == FUNC_LED_ON) 267 - return LED_HALF; 268 - 269 - return LED_OFF; 270 - } 271 - 272 - static enum led_brightness kblamps_get(struct led_classdev *cdev) 273 - { 274 - enum led_brightness brightness = LED_OFF; 275 - 276 - if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON) 277 - brightness = LED_FULL; 278 - 279 - return brightness; 280 - } 281 - 282 - static enum led_brightness radio_led_get(struct led_classdev *cdev) 283 - { 284 - enum led_brightness brightness = LED_OFF; 285 - 286 - if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON) 287 - brightness = LED_FULL; 288 - 289 - return brightness; 290 - } 291 - 292 - static enum led_brightness eco_led_get(struct led_classdev *cdev) 293 - { 294 - enum led_brightness brightness = LED_OFF; 295 - 296 - if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON) 297 - brightness = LED_FULL; 298 - 299 - return brightness; 300 - } 301 - #endif 302 253 303 254 /* Hardware access for LCD brightness control */ 304 255 305 256 static int set_lcd_level(int level) 306 257 { 307 - acpi_status status = AE_OK; 308 - acpi_handle handle = NULL; 258 + acpi_status status; 259 + char *method; 309 260 310 - vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n", 311 - level); 261 + switch (use_alt_lcd_levels) { 262 + case -1: 263 + if (acpi_has_method(fujitsu_bl->acpi_handle, "SBL2")) 264 + method = "SBL2"; 265 + else 266 + method = "SBLL"; 267 + break; 268 + case 1: 269 + method = "SBL2"; 270 + break; 271 + default: 272 + method = "SBLL"; 273 + break; 274 + } 275 + 276 + vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via %s [%d]\n", 277 + method, level); 312 278 313 279 if (level < 0 || level >= fujitsu_bl->max_brightness) 314 280 return -EINVAL; 315 281 316 - status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBLL", &handle); 282 + status = acpi_execute_simple_method(fujitsu_bl->acpi_handle, method, 283 + level); 317 284 if (ACPI_FAILURE(status)) { 318 - vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); 285 + vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate %s\n", 286 + method); 319 287 return -ENODEV; 320 288 } 321 289 322 - 323 - status = acpi_execute_simple_method(handle, NULL, level); 324 - if (ACPI_FAILURE(status)) 325 - return -ENODEV; 326 - 327 - return 0; 328 - } 329 - 330 - static int set_lcd_level_alt(int level) 331 - { 332 - acpi_status status = AE_OK; 333 - acpi_handle handle = NULL; 334 - 335 - vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n", 336 - level); 337 - 338 - if (level < 0 || level >= fujitsu_bl->max_brightness) 339 - return -EINVAL; 340 - 341 - status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBL2", &handle); 342 - if (ACPI_FAILURE(status)) { 343 - vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); 344 - return -ENODEV; 345 - } 346 - 347 - status = acpi_execute_simple_method(handle, NULL, level); 348 - if (ACPI_FAILURE(status)) 349 - return -ENODEV; 290 + fujitsu_bl->brightness_level = level; 350 291 351 292 return 0; 352 293 } ··· 241 428 return 0; 242 429 243 430 fujitsu_bl->brightness_level = state & 0x0fffffff; 244 - 245 - if (state & 0x80000000) 246 - fujitsu_bl->brightness_changed = 1; 247 - else 248 - fujitsu_bl->brightness_changed = 0; 249 431 250 432 return fujitsu_bl->brightness_level; 251 433 } ··· 266 458 267 459 static int bl_get_brightness(struct backlight_device *b) 268 460 { 269 - return get_lcd_level(); 461 + return b->props.power == FB_BLANK_POWERDOWN ? 0 : get_lcd_level(); 270 462 } 271 463 272 464 static int bl_update_status(struct backlight_device *b) 273 465 { 274 - int ret; 275 466 if (b->props.power == FB_BLANK_POWERDOWN) 276 - ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3); 467 + call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3); 277 468 else 278 - ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0); 279 - if (ret != 0) 280 - vdbg_printk(FUJLAPTOP_DBG_ERROR, 281 - "Unable to adjust backlight power, error code %i\n", 282 - ret); 469 + call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0); 283 470 284 - if (use_alt_lcd_levels) 285 - ret = set_lcd_level_alt(b->props.brightness); 286 - else 287 - ret = set_lcd_level(b->props.brightness); 288 - if (ret != 0) 289 - vdbg_printk(FUJLAPTOP_DBG_ERROR, 290 - "Unable to adjust LCD brightness, error code %i\n", 291 - ret); 292 - return ret; 471 + return set_lcd_level(b->props.brightness); 293 472 } 294 473 295 474 static const struct backlight_ops fujitsu_bl_ops = { ··· 284 489 .update_status = bl_update_status, 285 490 }; 286 491 287 - /* Platform LCD brightness device */ 288 - 289 - static ssize_t 290 - show_max_brightness(struct device *dev, 291 - struct device_attribute *attr, char *buf) 292 - { 293 - 294 - int ret; 295 - 296 - ret = get_max_brightness(); 297 - if (ret < 0) 298 - return ret; 299 - 300 - return sprintf(buf, "%i\n", ret); 301 - } 302 - 303 - static ssize_t 304 - show_brightness_changed(struct device *dev, 305 - struct device_attribute *attr, char *buf) 306 - { 307 - 308 - int ret; 309 - 310 - ret = fujitsu_bl->brightness_changed; 311 - if (ret < 0) 312 - return ret; 313 - 314 - return sprintf(buf, "%i\n", ret); 315 - } 316 - 317 - static ssize_t show_lcd_level(struct device *dev, 318 - struct device_attribute *attr, char *buf) 319 - { 320 - 321 - int ret; 322 - 323 - ret = get_lcd_level(); 324 - if (ret < 0) 325 - return ret; 326 - 327 - return sprintf(buf, "%i\n", ret); 328 - } 329 - 330 - static ssize_t store_lcd_level(struct device *dev, 331 - struct device_attribute *attr, const char *buf, 332 - size_t count) 333 - { 334 - 335 - int level, ret; 336 - 337 - if (sscanf(buf, "%i", &level) != 1 338 - || (level < 0 || level >= fujitsu_bl->max_brightness)) 339 - return -EINVAL; 340 - 341 - if (use_alt_lcd_levels) 342 - ret = set_lcd_level_alt(level); 343 - else 344 - ret = set_lcd_level(level); 345 - if (ret < 0) 346 - return ret; 347 - 348 - ret = get_lcd_level(); 349 - if (ret < 0) 350 - return ret; 351 - 352 - return count; 353 - } 354 - 355 - static ssize_t 356 - ignore_store(struct device *dev, 357 - struct device_attribute *attr, const char *buf, size_t count) 358 - { 359 - return count; 360 - } 361 - 362 - static ssize_t 363 - show_lid_state(struct device *dev, 364 - struct device_attribute *attr, char *buf) 492 + static ssize_t lid_show(struct device *dev, struct device_attribute *attr, 493 + char *buf) 365 494 { 366 495 if (!(fujitsu_laptop->flags_supported & FLAG_LID)) 367 496 return sprintf(buf, "unknown\n"); ··· 295 576 return sprintf(buf, "closed\n"); 296 577 } 297 578 298 - static ssize_t 299 - show_dock_state(struct device *dev, 300 - struct device_attribute *attr, char *buf) 579 + static ssize_t dock_show(struct device *dev, struct device_attribute *attr, 580 + char *buf) 301 581 { 302 582 if (!(fujitsu_laptop->flags_supported & FLAG_DOCK)) 303 583 return sprintf(buf, "unknown\n"); ··· 306 588 return sprintf(buf, "undocked\n"); 307 589 } 308 590 309 - static ssize_t 310 - show_radios_state(struct device *dev, 311 - struct device_attribute *attr, char *buf) 591 + static ssize_t radios_show(struct device *dev, struct device_attribute *attr, 592 + char *buf) 312 593 { 313 594 if (!(fujitsu_laptop->flags_supported & FLAG_RFKILL)) 314 595 return sprintf(buf, "unknown\n"); ··· 317 600 return sprintf(buf, "killed\n"); 318 601 } 319 602 320 - static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); 321 - static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, 322 - ignore_store); 323 - static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); 324 - static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store); 325 - static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store); 326 - static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store); 603 + static DEVICE_ATTR_RO(lid); 604 + static DEVICE_ATTR_RO(dock); 605 + static DEVICE_ATTR_RO(radios); 327 606 328 607 static struct attribute *fujitsu_pf_attributes[] = { 329 - &dev_attr_brightness_changed.attr, 330 - &dev_attr_max_brightness.attr, 331 - &dev_attr_lcd_level.attr, 332 608 &dev_attr_lid.attr, 333 609 &dev_attr_dock.attr, 334 610 &dev_attr_radios.attr, ··· 338 628 } 339 629 }; 340 630 341 - static void __init dmi_check_cb_common(const struct dmi_system_id *id) 342 - { 343 - pr_info("Identified laptop model '%s'\n", id->ident); 344 - } 631 + /* ACPI device for LCD brightness control */ 345 632 346 - static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) 347 - { 348 - dmi_check_cb_common(id); 349 - fujitsu_bl->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 350 - fujitsu_bl->keycode2 = KEY_HELP; /* "Mobility Center" */ 351 - return 1; 352 - } 353 - 354 - static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) 355 - { 356 - dmi_check_cb_common(id); 357 - fujitsu_bl->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 358 - fujitsu_bl->keycode2 = KEY_HELP; /* "Mobility Center" */ 359 - return 1; 360 - } 361 - 362 - static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) 363 - { 364 - dmi_check_cb_common(id); 365 - fujitsu_bl->keycode1 = KEY_HELP; /* "Support" */ 366 - fujitsu_bl->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ 367 - fujitsu_bl->keycode4 = KEY_WWW; /* "Internet" */ 368 - return 1; 369 - } 370 - 371 - static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { 372 - { 373 - .ident = "Fujitsu Siemens S6410", 374 - .matches = { 375 - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 376 - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), 377 - }, 378 - .callback = dmi_check_cb_s6410}, 379 - { 380 - .ident = "Fujitsu Siemens S6420", 381 - .matches = { 382 - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 383 - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), 384 - }, 385 - .callback = dmi_check_cb_s6420}, 386 - { 387 - .ident = "Fujitsu LifeBook P8010", 388 - .matches = { 389 - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 390 - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), 391 - }, 392 - .callback = dmi_check_cb_p8010}, 393 - {} 633 + static const struct key_entry keymap_backlight[] = { 634 + { KE_KEY, true, { KEY_BRIGHTNESSUP } }, 635 + { KE_KEY, false, { KEY_BRIGHTNESSDOWN } }, 636 + { KE_END, 0 } 394 637 }; 395 638 396 - /* ACPI device for LCD brightness control */ 639 + static int acpi_fujitsu_bl_input_setup(struct acpi_device *device) 640 + { 641 + struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device); 642 + int ret; 643 + 644 + fujitsu_bl->input = devm_input_allocate_device(&device->dev); 645 + if (!fujitsu_bl->input) 646 + return -ENOMEM; 647 + 648 + snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys), 649 + "%s/video/input0", acpi_device_hid(device)); 650 + 651 + fujitsu_bl->input->name = acpi_device_name(device); 652 + fujitsu_bl->input->phys = fujitsu_bl->phys; 653 + fujitsu_bl->input->id.bustype = BUS_HOST; 654 + fujitsu_bl->input->id.product = 0x06; 655 + 656 + ret = sparse_keymap_setup(fujitsu_bl->input, keymap_backlight, NULL); 657 + if (ret) 658 + return ret; 659 + 660 + return input_register_device(fujitsu_bl->input); 661 + } 662 + 663 + static int fujitsu_backlight_register(struct acpi_device *device) 664 + { 665 + const struct backlight_properties props = { 666 + .brightness = fujitsu_bl->brightness_level, 667 + .max_brightness = fujitsu_bl->max_brightness - 1, 668 + .type = BACKLIGHT_PLATFORM 669 + }; 670 + struct backlight_device *bd; 671 + 672 + bd = devm_backlight_device_register(&device->dev, "fujitsu-laptop", 673 + &device->dev, NULL, 674 + &fujitsu_bl_ops, &props); 675 + if (IS_ERR(bd)) 676 + return PTR_ERR(bd); 677 + 678 + fujitsu_bl->bl_device = bd; 679 + 680 + return 0; 681 + } 397 682 398 683 static int acpi_fujitsu_bl_add(struct acpi_device *device) 399 684 { 400 685 int state = 0; 401 - struct input_dev *input; 402 686 int error; 687 + 688 + if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 689 + return -ENODEV; 403 690 404 691 if (!device) 405 692 return -EINVAL; ··· 406 699 sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); 407 700 device->driver_data = fujitsu_bl; 408 701 409 - fujitsu_bl->input = input = input_allocate_device(); 410 - if (!input) { 411 - error = -ENOMEM; 412 - goto err_stop; 413 - } 414 - 415 - snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys), 416 - "%s/video/input0", acpi_device_hid(device)); 417 - 418 - input->name = acpi_device_name(device); 419 - input->phys = fujitsu_bl->phys; 420 - input->id.bustype = BUS_HOST; 421 - input->id.product = 0x06; 422 - input->dev.parent = &device->dev; 423 - input->evbit[0] = BIT(EV_KEY); 424 - set_bit(KEY_BRIGHTNESSUP, input->keybit); 425 - set_bit(KEY_BRIGHTNESSDOWN, input->keybit); 426 - set_bit(KEY_UNKNOWN, input->keybit); 427 - 428 - error = input_register_device(input); 702 + error = acpi_fujitsu_bl_input_setup(device); 429 703 if (error) 430 - goto err_free_input_dev; 704 + return error; 431 705 432 706 error = acpi_bus_update_power(fujitsu_bl->acpi_handle, &state); 433 707 if (error) { 434 708 pr_err("Error reading power state\n"); 435 - goto err_unregister_input_dev; 709 + return error; 436 710 } 437 711 438 712 pr_info("ACPI: %s [%s] (%s)\n", 439 713 acpi_device_name(device), acpi_device_bid(device), 440 714 !device->power.state ? "on" : "off"); 441 - 442 - fujitsu_bl->dev = device; 443 715 444 716 if (acpi_has_method(device->handle, METHOD_NAME__INI)) { 445 717 vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); ··· 428 742 pr_err("_INI Method failed\n"); 429 743 } 430 744 431 - if (use_alt_lcd_levels == -1) { 432 - if (acpi_has_method(NULL, "\\_SB.PCI0.LPCB.FJEX.SBL2")) 433 - use_alt_lcd_levels = 1; 434 - else 435 - use_alt_lcd_levels = 0; 436 - vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as %i\n", 437 - use_alt_lcd_levels); 438 - } 439 - 440 - /* do config (detect defaults) */ 441 - use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; 442 - disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; 443 - vdbg_printk(FUJLAPTOP_DBG_INFO, 444 - "config: [alt interface: %d], [adjust disable: %d]\n", 445 - use_alt_lcd_levels, disable_brightness_adjust); 446 - 447 745 if (get_max_brightness() <= 0) 448 746 fujitsu_bl->max_brightness = FUJITSU_LCD_N_LEVELS; 449 747 get_lcd_level(); 450 748 451 - return 0; 452 - 453 - err_unregister_input_dev: 454 - input_unregister_device(input); 455 - input = NULL; 456 - err_free_input_dev: 457 - input_free_device(input); 458 - err_stop: 459 - return error; 460 - } 461 - 462 - static int acpi_fujitsu_bl_remove(struct acpi_device *device) 463 - { 464 - struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device); 465 - struct input_dev *input = fujitsu_bl->input; 466 - 467 - input_unregister_device(input); 468 - 469 - fujitsu_bl->acpi_handle = NULL; 749 + error = fujitsu_backlight_register(device); 750 + if (error) 751 + return error; 470 752 471 753 return 0; 472 754 } ··· 444 790 static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event) 445 791 { 446 792 struct input_dev *input; 447 - int keycode; 448 793 int oldb, newb; 449 794 450 795 input = fujitsu_bl->input; 451 796 452 - switch (event) { 453 - case ACPI_FUJITSU_NOTIFY_CODE1: 454 - keycode = 0; 455 - oldb = fujitsu_bl->brightness_level; 456 - get_lcd_level(); 457 - newb = fujitsu_bl->brightness_level; 458 - 459 - vdbg_printk(FUJLAPTOP_DBG_TRACE, 460 - "brightness button event [%i -> %i (%i)]\n", 461 - oldb, newb, fujitsu_bl->brightness_changed); 462 - 463 - if (oldb < newb) { 464 - if (disable_brightness_adjust != 1) { 465 - if (use_alt_lcd_levels) 466 - set_lcd_level_alt(newb); 467 - else 468 - set_lcd_level(newb); 469 - } 470 - keycode = KEY_BRIGHTNESSUP; 471 - } else if (oldb > newb) { 472 - if (disable_brightness_adjust != 1) { 473 - if (use_alt_lcd_levels) 474 - set_lcd_level_alt(newb); 475 - else 476 - set_lcd_level(newb); 477 - } 478 - keycode = KEY_BRIGHTNESSDOWN; 479 - } 480 - break; 481 - default: 482 - keycode = KEY_UNKNOWN; 797 + if (event != ACPI_FUJITSU_NOTIFY_CODE1) { 483 798 vdbg_printk(FUJLAPTOP_DBG_WARN, 484 799 "unsupported event [0x%x]\n", event); 485 - break; 800 + sparse_keymap_report_event(input, -1, 1, true); 801 + return; 486 802 } 487 803 488 - if (keycode != 0) { 489 - input_report_key(input, keycode, 1); 490 - input_sync(input); 491 - input_report_key(input, keycode, 0); 492 - input_sync(input); 493 - } 804 + oldb = fujitsu_bl->brightness_level; 805 + get_lcd_level(); 806 + newb = fujitsu_bl->brightness_level; 807 + 808 + vdbg_printk(FUJLAPTOP_DBG_TRACE, "brightness button event [%i -> %i]\n", 809 + oldb, newb); 810 + 811 + if (oldb == newb) 812 + return; 813 + 814 + if (!disable_brightness_adjust) 815 + set_lcd_level(newb); 816 + 817 + sparse_keymap_report_event(input, oldb < newb, 1, true); 494 818 } 495 819 496 820 /* ACPI device for hotkey handling */ 497 821 822 + static const struct key_entry keymap_default[] = { 823 + { KE_KEY, KEY1_CODE, { KEY_PROG1 } }, 824 + { KE_KEY, KEY2_CODE, { KEY_PROG2 } }, 825 + { KE_KEY, KEY3_CODE, { KEY_PROG3 } }, 826 + { KE_KEY, KEY4_CODE, { KEY_PROG4 } }, 827 + { KE_KEY, KEY5_CODE, { KEY_RFKILL } }, 828 + { KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } }, 829 + { KE_END, 0 } 830 + }; 831 + 832 + static const struct key_entry keymap_s64x0[] = { 833 + { KE_KEY, KEY1_CODE, { KEY_SCREENLOCK } }, /* "Lock" */ 834 + { KE_KEY, KEY2_CODE, { KEY_HELP } }, /* "Mobility Center */ 835 + { KE_KEY, KEY3_CODE, { KEY_PROG3 } }, 836 + { KE_KEY, KEY4_CODE, { KEY_PROG4 } }, 837 + { KE_END, 0 } 838 + }; 839 + 840 + static const struct key_entry keymap_p8010[] = { 841 + { KE_KEY, KEY1_CODE, { KEY_HELP } }, /* "Support" */ 842 + { KE_KEY, KEY2_CODE, { KEY_PROG2 } }, 843 + { KE_KEY, KEY3_CODE, { KEY_SWITCHVIDEOMODE } }, /* "Presentation" */ 844 + { KE_KEY, KEY4_CODE, { KEY_WWW } }, /* "WWW" */ 845 + { KE_END, 0 } 846 + }; 847 + 848 + static const struct key_entry *keymap = keymap_default; 849 + 850 + static int fujitsu_laptop_dmi_keymap_override(const struct dmi_system_id *id) 851 + { 852 + pr_info("Identified laptop model '%s'\n", id->ident); 853 + keymap = id->driver_data; 854 + return 1; 855 + } 856 + 857 + static const struct dmi_system_id fujitsu_laptop_dmi_table[] = { 858 + { 859 + .callback = fujitsu_laptop_dmi_keymap_override, 860 + .ident = "Fujitsu Siemens S6410", 861 + .matches = { 862 + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 863 + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), 864 + }, 865 + .driver_data = (void *)keymap_s64x0 866 + }, 867 + { 868 + .callback = fujitsu_laptop_dmi_keymap_override, 869 + .ident = "Fujitsu Siemens S6420", 870 + .matches = { 871 + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 872 + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), 873 + }, 874 + .driver_data = (void *)keymap_s64x0 875 + }, 876 + { 877 + .callback = fujitsu_laptop_dmi_keymap_override, 878 + .ident = "Fujitsu LifeBook P8010", 879 + .matches = { 880 + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 881 + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), 882 + }, 883 + .driver_data = (void *)keymap_p8010 884 + }, 885 + {} 886 + }; 887 + 888 + static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device) 889 + { 890 + struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device); 891 + int ret; 892 + 893 + fujitsu_laptop->input = devm_input_allocate_device(&device->dev); 894 + if (!fujitsu_laptop->input) 895 + return -ENOMEM; 896 + 897 + snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys), 898 + "%s/video/input0", acpi_device_hid(device)); 899 + 900 + fujitsu_laptop->input->name = acpi_device_name(device); 901 + fujitsu_laptop->input->phys = fujitsu_laptop->phys; 902 + fujitsu_laptop->input->id.bustype = BUS_HOST; 903 + fujitsu_laptop->input->id.product = 0x06; 904 + 905 + dmi_check_system(fujitsu_laptop_dmi_table); 906 + ret = sparse_keymap_setup(fujitsu_laptop->input, keymap, NULL); 907 + if (ret) 908 + return ret; 909 + 910 + return input_register_device(fujitsu_laptop->input); 911 + } 912 + 913 + static int fujitsu_laptop_platform_add(void) 914 + { 915 + int ret; 916 + 917 + fujitsu_laptop->pf_device = platform_device_alloc("fujitsu-laptop", -1); 918 + if (!fujitsu_laptop->pf_device) 919 + return -ENOMEM; 920 + 921 + ret = platform_device_add(fujitsu_laptop->pf_device); 922 + if (ret) 923 + goto err_put_platform_device; 924 + 925 + ret = sysfs_create_group(&fujitsu_laptop->pf_device->dev.kobj, 926 + &fujitsu_pf_attribute_group); 927 + if (ret) 928 + goto err_del_platform_device; 929 + 930 + return 0; 931 + 932 + err_del_platform_device: 933 + platform_device_del(fujitsu_laptop->pf_device); 934 + err_put_platform_device: 935 + platform_device_put(fujitsu_laptop->pf_device); 936 + 937 + return ret; 938 + } 939 + 940 + static void fujitsu_laptop_platform_remove(void) 941 + { 942 + sysfs_remove_group(&fujitsu_laptop->pf_device->dev.kobj, 943 + &fujitsu_pf_attribute_group); 944 + platform_device_unregister(fujitsu_laptop->pf_device); 945 + } 946 + 947 + static int logolamp_set(struct led_classdev *cdev, 948 + enum led_brightness brightness) 949 + { 950 + int poweron = FUNC_LED_ON, always = FUNC_LED_ON; 951 + int ret; 952 + 953 + if (brightness < LED_HALF) 954 + poweron = FUNC_LED_OFF; 955 + 956 + if (brightness < LED_FULL) 957 + always = FUNC_LED_OFF; 958 + 959 + ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron); 960 + if (ret < 0) 961 + return ret; 962 + 963 + return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always); 964 + } 965 + 966 + static enum led_brightness logolamp_get(struct led_classdev *cdev) 967 + { 968 + int ret; 969 + 970 + ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); 971 + if (ret == FUNC_LED_ON) 972 + return LED_FULL; 973 + 974 + ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); 975 + if (ret == FUNC_LED_ON) 976 + return LED_HALF; 977 + 978 + return LED_OFF; 979 + } 980 + 981 + static struct led_classdev logolamp_led = { 982 + .name = "fujitsu::logolamp", 983 + .brightness_set_blocking = logolamp_set, 984 + .brightness_get = logolamp_get 985 + }; 986 + 987 + static int kblamps_set(struct led_classdev *cdev, 988 + enum led_brightness brightness) 989 + { 990 + if (brightness >= LED_FULL) 991 + return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, 992 + FUNC_LED_ON); 993 + else 994 + return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, 995 + FUNC_LED_OFF); 996 + } 997 + 998 + static enum led_brightness kblamps_get(struct led_classdev *cdev) 999 + { 1000 + enum led_brightness brightness = LED_OFF; 1001 + 1002 + if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON) 1003 + brightness = LED_FULL; 1004 + 1005 + return brightness; 1006 + } 1007 + 1008 + static struct led_classdev kblamps_led = { 1009 + .name = "fujitsu::kblamps", 1010 + .brightness_set_blocking = kblamps_set, 1011 + .brightness_get = kblamps_get 1012 + }; 1013 + 1014 + static int radio_led_set(struct led_classdev *cdev, 1015 + enum led_brightness brightness) 1016 + { 1017 + if (brightness >= LED_FULL) 1018 + return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 1019 + RADIO_LED_ON); 1020 + else 1021 + return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0); 1022 + } 1023 + 1024 + static enum led_brightness radio_led_get(struct led_classdev *cdev) 1025 + { 1026 + enum led_brightness brightness = LED_OFF; 1027 + 1028 + if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON) 1029 + brightness = LED_FULL; 1030 + 1031 + return brightness; 1032 + } 1033 + 1034 + static struct led_classdev radio_led = { 1035 + .name = "fujitsu::radio_led", 1036 + .brightness_set_blocking = radio_led_set, 1037 + .brightness_get = radio_led_get, 1038 + .default_trigger = "rfkill-any" 1039 + }; 1040 + 1041 + static int eco_led_set(struct led_classdev *cdev, 1042 + enum led_brightness brightness) 1043 + { 1044 + int curr; 1045 + 1046 + curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0); 1047 + if (brightness >= LED_FULL) 1048 + return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, 1049 + curr | ECO_LED_ON); 1050 + else 1051 + return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, 1052 + curr & ~ECO_LED_ON); 1053 + } 1054 + 1055 + static enum led_brightness eco_led_get(struct led_classdev *cdev) 1056 + { 1057 + enum led_brightness brightness = LED_OFF; 1058 + 1059 + if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON) 1060 + brightness = LED_FULL; 1061 + 1062 + return brightness; 1063 + } 1064 + 1065 + static struct led_classdev eco_led = { 1066 + .name = "fujitsu::eco_led", 1067 + .brightness_set_blocking = eco_led_set, 1068 + .brightness_get = eco_led_get 1069 + }; 1070 + 1071 + static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) 1072 + { 1073 + int result; 1074 + 1075 + if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 1076 + result = devm_led_classdev_register(&device->dev, 1077 + &logolamp_led); 1078 + if (result) 1079 + return result; 1080 + } 1081 + 1082 + if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) && 1083 + (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) { 1084 + result = devm_led_classdev_register(&device->dev, &kblamps_led); 1085 + if (result) 1086 + return result; 1087 + } 1088 + 1089 + /* 1090 + * BTNI bit 24 seems to indicate the presence of a radio toggle 1091 + * button in place of a slide switch, and all such machines appear 1092 + * to also have an RF LED. Therefore use bit 24 as an indicator 1093 + * that an RF LED is present. 1094 + */ 1095 + if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) { 1096 + result = devm_led_classdev_register(&device->dev, &radio_led); 1097 + if (result) 1098 + return result; 1099 + } 1100 + 1101 + /* Support for eco led is not always signaled in bit corresponding 1102 + * to the bit used to control the led. According to the DSDT table, 1103 + * bit 14 seems to indicate presence of said led as well. 1104 + * Confirm by testing the status. 1105 + */ 1106 + if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) && 1107 + (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) { 1108 + result = devm_led_classdev_register(&device->dev, &eco_led); 1109 + if (result) 1110 + return result; 1111 + } 1112 + 1113 + return 0; 1114 + } 1115 + 498 1116 static int acpi_fujitsu_laptop_add(struct acpi_device *device) 499 1117 { 500 - int result = 0; 501 1118 int state = 0; 502 - struct input_dev *input; 503 1119 int error; 504 1120 int i; 505 1121 ··· 791 867 goto err_stop; 792 868 } 793 869 794 - fujitsu_laptop->input = input = input_allocate_device(); 795 - if (!input) { 796 - error = -ENOMEM; 797 - goto err_free_fifo; 798 - } 799 - 800 - snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys), 801 - "%s/video/input0", acpi_device_hid(device)); 802 - 803 - input->name = acpi_device_name(device); 804 - input->phys = fujitsu_laptop->phys; 805 - input->id.bustype = BUS_HOST; 806 - input->id.product = 0x06; 807 - input->dev.parent = &device->dev; 808 - 809 - set_bit(EV_KEY, input->evbit); 810 - set_bit(fujitsu_bl->keycode1, input->keybit); 811 - set_bit(fujitsu_bl->keycode2, input->keybit); 812 - set_bit(fujitsu_bl->keycode3, input->keybit); 813 - set_bit(fujitsu_bl->keycode4, input->keybit); 814 - set_bit(fujitsu_bl->keycode5, input->keybit); 815 - set_bit(KEY_TOUCHPAD_TOGGLE, input->keybit); 816 - set_bit(KEY_UNKNOWN, input->keybit); 817 - 818 - error = input_register_device(input); 870 + error = acpi_fujitsu_laptop_input_setup(device); 819 871 if (error) 820 - goto err_free_input_dev; 872 + goto err_free_fifo; 821 873 822 874 error = acpi_bus_update_power(fujitsu_laptop->acpi_handle, &state); 823 875 if (error) { 824 876 pr_err("Error reading power state\n"); 825 - goto err_unregister_input_dev; 877 + goto err_free_fifo; 826 878 } 827 879 828 880 pr_info("ACPI: %s [%s] (%s)\n", ··· 836 936 /* Suspect this is a keymap of the application panel, print it */ 837 937 pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); 838 938 839 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 840 - if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 841 - result = led_classdev_register(&fujitsu_bl->pf_device->dev, 842 - &logolamp_led); 843 - if (result == 0) { 844 - fujitsu_laptop->logolamp_registered = 1; 845 - } else { 846 - pr_err("Could not register LED handler for logo lamp, error %i\n", 847 - result); 848 - } 939 + /* Sync backlight power status */ 940 + if (fujitsu_bl->bl_device && 941 + acpi_video_get_backlight_type() == acpi_backlight_vendor) { 942 + if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3) 943 + fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN; 944 + else 945 + fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; 849 946 } 850 947 851 - if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) && 852 - (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) { 853 - result = led_classdev_register(&fujitsu_bl->pf_device->dev, 854 - &kblamps_led); 855 - if (result == 0) { 856 - fujitsu_laptop->kblamps_registered = 1; 857 - } else { 858 - pr_err("Could not register LED handler for keyboard lamps, error %i\n", 859 - result); 860 - } 861 - } 948 + error = acpi_fujitsu_laptop_leds_register(device); 949 + if (error) 950 + goto err_free_fifo; 862 951 863 - /* 864 - * BTNI bit 24 seems to indicate the presence of a radio toggle 865 - * button in place of a slide switch, and all such machines appear 866 - * to also have an RF LED. Therefore use bit 24 as an indicator 867 - * that an RF LED is present. 868 - */ 869 - if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) { 870 - result = led_classdev_register(&fujitsu_bl->pf_device->dev, 871 - &radio_led); 872 - if (result == 0) { 873 - fujitsu_laptop->radio_led_registered = 1; 874 - } else { 875 - pr_err("Could not register LED handler for radio LED, error %i\n", 876 - result); 877 - } 878 - } 952 + error = fujitsu_laptop_platform_add(); 953 + if (error) 954 + goto err_free_fifo; 879 955 880 - /* Support for eco led is not always signaled in bit corresponding 881 - * to the bit used to control the led. According to the DSDT table, 882 - * bit 14 seems to indicate presence of said led as well. 883 - * Confirm by testing the status. 884 - */ 885 - if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) && 886 - (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) { 887 - result = led_classdev_register(&fujitsu_bl->pf_device->dev, 888 - &eco_led); 889 - if (result == 0) { 890 - fujitsu_laptop->eco_led_registered = 1; 891 - } else { 892 - pr_err("Could not register LED handler for eco LED, error %i\n", 893 - result); 894 - } 895 - } 896 - #endif 956 + return 0; 897 957 898 - return result; 899 - 900 - err_unregister_input_dev: 901 - input_unregister_device(input); 902 - input = NULL; 903 - err_free_input_dev: 904 - input_free_device(input); 905 958 err_free_fifo: 906 959 kfifo_free(&fujitsu_laptop->fifo); 907 960 err_stop: ··· 864 1011 static int acpi_fujitsu_laptop_remove(struct acpi_device *device) 865 1012 { 866 1013 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device); 867 - struct input_dev *input = fujitsu_laptop->input; 868 1014 869 - #if IS_ENABLED(CONFIG_LEDS_CLASS) 870 - if (fujitsu_laptop->logolamp_registered) 871 - led_classdev_unregister(&logolamp_led); 872 - 873 - if (fujitsu_laptop->kblamps_registered) 874 - led_classdev_unregister(&kblamps_led); 875 - 876 - if (fujitsu_laptop->radio_led_registered) 877 - led_classdev_unregister(&radio_led); 878 - 879 - if (fujitsu_laptop->eco_led_registered) 880 - led_classdev_unregister(&eco_led); 881 - #endif 882 - 883 - input_unregister_device(input); 1015 + fujitsu_laptop_platform_remove(); 884 1016 885 1017 kfifo_free(&fujitsu_laptop->fifo); 886 - 887 - fujitsu_laptop->acpi_handle = NULL; 888 1018 889 1019 return 0; 890 1020 } 891 1021 892 - static void acpi_fujitsu_laptop_press(int keycode) 1022 + static void acpi_fujitsu_laptop_press(int scancode) 893 1023 { 894 1024 struct input_dev *input = fujitsu_laptop->input; 895 1025 int status; 896 1026 897 1027 status = kfifo_in_locked(&fujitsu_laptop->fifo, 898 - (unsigned char *)&keycode, sizeof(keycode), 1028 + (unsigned char *)&scancode, sizeof(scancode), 899 1029 &fujitsu_laptop->fifo_lock); 900 - if (status != sizeof(keycode)) { 1030 + if (status != sizeof(scancode)) { 901 1031 vdbg_printk(FUJLAPTOP_DBG_WARN, 902 - "Could not push keycode [0x%x]\n", keycode); 1032 + "Could not push scancode [0x%x]\n", scancode); 903 1033 return; 904 1034 } 905 - input_report_key(input, keycode, 1); 906 - input_sync(input); 1035 + sparse_keymap_report_event(input, scancode, 1, false); 907 1036 vdbg_printk(FUJLAPTOP_DBG_TRACE, 908 - "Push keycode into ringbuffer [%d]\n", keycode); 1037 + "Push scancode into ringbuffer [0x%x]\n", scancode); 909 1038 } 910 1039 911 1040 static void acpi_fujitsu_laptop_release(void) 912 1041 { 913 1042 struct input_dev *input = fujitsu_laptop->input; 914 - int keycode, status; 1043 + int scancode, status; 915 1044 916 1045 while (true) { 917 1046 status = kfifo_out_locked(&fujitsu_laptop->fifo, 918 - (unsigned char *)&keycode, 919 - sizeof(keycode), 1047 + (unsigned char *)&scancode, 1048 + sizeof(scancode), 920 1049 &fujitsu_laptop->fifo_lock); 921 - if (status != sizeof(keycode)) 1050 + if (status != sizeof(scancode)) 922 1051 return; 923 - input_report_key(input, keycode, 0); 924 - input_sync(input); 1052 + sparse_keymap_report_event(input, scancode, 0, false); 925 1053 vdbg_printk(FUJLAPTOP_DBG_TRACE, 926 - "Pop keycode from ringbuffer [%d]\n", keycode); 1054 + "Pop scancode from ringbuffer [0x%x]\n", scancode); 927 1055 } 928 1056 } 929 1057 930 1058 static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) 931 1059 { 932 1060 struct input_dev *input; 933 - int keycode; 934 - unsigned int irb = 1; 935 - int i; 1061 + int scancode, i = 0; 1062 + unsigned int irb; 936 1063 937 1064 input = fujitsu_laptop->input; 938 1065 939 1066 if (event != ACPI_FUJITSU_NOTIFY_CODE1) { 940 - keycode = KEY_UNKNOWN; 941 1067 vdbg_printk(FUJLAPTOP_DBG_WARN, 942 1068 "Unsupported event [0x%x]\n", event); 943 - input_report_key(input, keycode, 1); 944 - input_sync(input); 945 - input_report_key(input, keycode, 0); 946 - input_sync(input); 1069 + sparse_keymap_report_event(input, -1, 1, true); 947 1070 return; 948 1071 } 949 1072 ··· 927 1098 fujitsu_laptop->flags_state = 928 1099 call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0); 929 1100 930 - i = 0; 931 - while ((irb = 932 - call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 933 - && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { 934 - switch (irb & 0x4ff) { 935 - case KEY1_CODE: 936 - keycode = fujitsu_bl->keycode1; 937 - break; 938 - case KEY2_CODE: 939 - keycode = fujitsu_bl->keycode2; 940 - break; 941 - case KEY3_CODE: 942 - keycode = fujitsu_bl->keycode3; 943 - break; 944 - case KEY4_CODE: 945 - keycode = fujitsu_bl->keycode4; 946 - break; 947 - case KEY5_CODE: 948 - keycode = fujitsu_bl->keycode5; 949 - break; 950 - case 0: 951 - keycode = 0; 952 - break; 953 - default: 1101 + while ((irb = call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 && 1102 + i++ < MAX_HOTKEY_RINGBUFFER_SIZE) { 1103 + scancode = irb & 0x4ff; 1104 + if (sparse_keymap_entry_from_scancode(input, scancode)) 1105 + acpi_fujitsu_laptop_press(scancode); 1106 + else if (scancode == 0) 1107 + acpi_fujitsu_laptop_release(); 1108 + else 954 1109 vdbg_printk(FUJLAPTOP_DBG_WARN, 955 1110 "Unknown GIRB result [%x]\n", irb); 956 - keycode = -1; 957 - break; 958 - } 959 - 960 - if (keycode > 0) 961 - acpi_fujitsu_laptop_press(keycode); 962 - else if (keycode == 0) 963 - acpi_fujitsu_laptop_release(); 964 1111 } 965 1112 966 1113 /* On some models (first seen on the Skylake-based Lifebook ··· 944 1139 * handled in software; its state is queried using FUNC_FLAGS 945 1140 */ 946 1141 if ((fujitsu_laptop->flags_supported & BIT(26)) && 947 - (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26))) { 948 - keycode = KEY_TOUCHPAD_TOGGLE; 949 - input_report_key(input, keycode, 1); 950 - input_sync(input); 951 - input_report_key(input, keycode, 0); 952 - input_sync(input); 953 - } 954 - 1142 + (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26))) 1143 + sparse_keymap_report_event(input, BIT(26), 1, true); 955 1144 } 956 1145 957 1146 /* Initialization */ ··· 961 1162 .ids = fujitsu_bl_device_ids, 962 1163 .ops = { 963 1164 .add = acpi_fujitsu_bl_add, 964 - .remove = acpi_fujitsu_bl_remove, 965 1165 .notify = acpi_fujitsu_bl_notify, 966 1166 }, 967 1167 }; ··· 990 1192 991 1193 static int __init fujitsu_init(void) 992 1194 { 993 - int ret, max_brightness; 1195 + int ret; 994 1196 995 1197 if (acpi_disabled) 996 1198 return -ENODEV; ··· 998 1200 fujitsu_bl = kzalloc(sizeof(struct fujitsu_bl), GFP_KERNEL); 999 1201 if (!fujitsu_bl) 1000 1202 return -ENOMEM; 1001 - fujitsu_bl->keycode1 = KEY_PROG1; 1002 - fujitsu_bl->keycode2 = KEY_PROG2; 1003 - fujitsu_bl->keycode3 = KEY_PROG3; 1004 - fujitsu_bl->keycode4 = KEY_PROG4; 1005 - fujitsu_bl->keycode5 = KEY_RFKILL; 1006 - dmi_check_system(fujitsu_dmi_table); 1007 1203 1008 1204 ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver); 1009 1205 if (ret) 1010 - goto fail_acpi; 1206 + goto err_free_fujitsu_bl; 1011 1207 1012 1208 /* Register platform stuff */ 1013 1209 1014 - fujitsu_bl->pf_device = platform_device_alloc("fujitsu-laptop", -1); 1015 - if (!fujitsu_bl->pf_device) { 1016 - ret = -ENOMEM; 1017 - goto fail_platform_driver; 1018 - } 1019 - 1020 - ret = platform_device_add(fujitsu_bl->pf_device); 1021 - if (ret) 1022 - goto fail_platform_device1; 1023 - 1024 - ret = 1025 - sysfs_create_group(&fujitsu_bl->pf_device->dev.kobj, 1026 - &fujitsu_pf_attribute_group); 1027 - if (ret) 1028 - goto fail_platform_device2; 1029 - 1030 - /* Register backlight stuff */ 1031 - 1032 - if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { 1033 - struct backlight_properties props; 1034 - 1035 - memset(&props, 0, sizeof(struct backlight_properties)); 1036 - max_brightness = fujitsu_bl->max_brightness; 1037 - props.type = BACKLIGHT_PLATFORM; 1038 - props.max_brightness = max_brightness - 1; 1039 - fujitsu_bl->bl_device = backlight_device_register("fujitsu-laptop", 1040 - NULL, NULL, 1041 - &fujitsu_bl_ops, 1042 - &props); 1043 - if (IS_ERR(fujitsu_bl->bl_device)) { 1044 - ret = PTR_ERR(fujitsu_bl->bl_device); 1045 - fujitsu_bl->bl_device = NULL; 1046 - goto fail_sysfs_group; 1047 - } 1048 - fujitsu_bl->bl_device->props.brightness = fujitsu_bl->brightness_level; 1049 - } 1050 - 1051 1210 ret = platform_driver_register(&fujitsu_pf_driver); 1052 1211 if (ret) 1053 - goto fail_backlight; 1212 + goto err_unregister_acpi; 1054 1213 1055 1214 /* Register laptop driver */ 1056 1215 1057 1216 fujitsu_laptop = kzalloc(sizeof(struct fujitsu_laptop), GFP_KERNEL); 1058 1217 if (!fujitsu_laptop) { 1059 1218 ret = -ENOMEM; 1060 - goto fail_laptop; 1219 + goto err_unregister_platform_driver; 1061 1220 } 1062 1221 1063 1222 ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver); 1064 1223 if (ret) 1065 - goto fail_laptop1; 1066 - 1067 - /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */ 1068 - if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { 1069 - if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3) 1070 - fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN; 1071 - else 1072 - fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; 1073 - } 1224 + goto err_free_fujitsu_laptop; 1074 1225 1075 1226 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n"); 1076 1227 1077 1228 return 0; 1078 1229 1079 - fail_laptop1: 1230 + err_free_fujitsu_laptop: 1080 1231 kfree(fujitsu_laptop); 1081 - fail_laptop: 1232 + err_unregister_platform_driver: 1082 1233 platform_driver_unregister(&fujitsu_pf_driver); 1083 - fail_backlight: 1084 - backlight_device_unregister(fujitsu_bl->bl_device); 1085 - fail_sysfs_group: 1086 - sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj, 1087 - &fujitsu_pf_attribute_group); 1088 - fail_platform_device2: 1089 - platform_device_del(fujitsu_bl->pf_device); 1090 - fail_platform_device1: 1091 - platform_device_put(fujitsu_bl->pf_device); 1092 - fail_platform_driver: 1234 + err_unregister_acpi: 1093 1235 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1094 - fail_acpi: 1236 + err_free_fujitsu_bl: 1095 1237 kfree(fujitsu_bl); 1096 1238 1097 1239 return ret; ··· 1045 1307 1046 1308 platform_driver_unregister(&fujitsu_pf_driver); 1047 1309 1048 - backlight_device_unregister(fujitsu_bl->bl_device); 1049 - 1050 - sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj, 1051 - &fujitsu_pf_attribute_group); 1052 - 1053 - platform_device_unregister(fujitsu_bl->pf_device); 1054 - 1055 1310 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1056 1311 1057 1312 kfree(fujitsu_bl); ··· 1055 1324 module_init(fujitsu_init); 1056 1325 module_exit(fujitsu_cleanup); 1057 1326 1058 - module_param(use_alt_lcd_levels, uint, 0644); 1059 - MODULE_PARM_DESC(use_alt_lcd_levels, 1060 - "Use alternative interface for lcd_levels (needed for Lifebook s6410)."); 1061 - module_param(disable_brightness_adjust, uint, 0644); 1062 - MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment ."); 1327 + module_param(use_alt_lcd_levels, int, 0644); 1328 + MODULE_PARM_DESC(use_alt_lcd_levels, "Interface used for setting LCD brightness level (-1 = auto, 0 = force SBLL, 1 = force SBL2)"); 1329 + module_param(disable_brightness_adjust, bool, 0644); 1330 + MODULE_PARM_DESC(disable_brightness_adjust, "Disable LCD brightness adjustment"); 1063 1331 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 1064 1332 module_param_named(debug, dbg_level, uint, 0644); 1065 1333 MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
+5 -22
drivers/platform/x86/hp-wireless.c
··· 1 1 /* 2 - * hp-wireless button for Windows 8 2 + * Airplane mode button for HP & Xiaomi laptops 3 3 * 4 - * Copyright (C) 2014 Alex Hung <alex.hung@canonical.com> 4 + * Copyright (C) 2014-2017 Alex Hung <alex.hung@canonical.com> 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify 7 7 * it under the terms of the GNU General Public License as published by ··· 29 29 MODULE_LICENSE("GPL"); 30 30 MODULE_AUTHOR("Alex Hung"); 31 31 MODULE_ALIAS("acpi*:HPQ6001:*"); 32 + MODULE_ALIAS("acpi*:WSTADEF:*"); 32 33 33 34 static struct input_dev *hpwl_input_dev; 34 35 35 36 static const struct acpi_device_id hpwl_ids[] = { 36 37 {"HPQ6001", 0}, 38 + {"WSTADEF", 0}, 37 39 {"", 0}, 38 40 }; 39 41 ··· 110 108 }, 111 109 }; 112 110 113 - static int __init hpwl_init(void) 114 - { 115 - int err; 116 - 117 - pr_info("Initializing HPQ6001 module\n"); 118 - err = acpi_bus_register_driver(&hpwl_driver); 119 - if (err) 120 - pr_err("Unable to register HP wireless control driver.\n"); 121 - 122 - return err; 123 - } 124 - 125 - static void __exit hpwl_exit(void) 126 - { 127 - pr_info("Exiting HPQ6001 module\n"); 128 - acpi_bus_unregister_driver(&hpwl_driver); 129 - } 130 - 131 - module_init(hpwl_init); 132 - module_exit(hpwl_exit); 111 + module_acpi_driver(hpwl_driver);
+199 -219
drivers/platform/x86/hp-wmi.c
··· 48 48 #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" 49 49 #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4" 50 50 51 - #define HPWMI_DISPLAY_QUERY 0x1 52 - #define HPWMI_HDDTEMP_QUERY 0x2 53 - #define HPWMI_ALS_QUERY 0x3 54 - #define HPWMI_HARDWARE_QUERY 0x4 55 - #define HPWMI_WIRELESS_QUERY 0x5 56 - #define HPWMI_BIOS_QUERY 0x9 57 - #define HPWMI_FEATURE_QUERY 0xb 58 - #define HPWMI_HOTKEY_QUERY 0xc 59 - #define HPWMI_FEATURE2_QUERY 0xd 60 - #define HPWMI_WIRELESS2_QUERY 0x1b 61 - #define HPWMI_POSTCODEERROR_QUERY 0x2a 62 - 63 51 enum hp_wmi_radio { 64 - HPWMI_WIFI = 0, 65 - HPWMI_BLUETOOTH = 1, 66 - HPWMI_WWAN = 2, 67 - HPWMI_GPS = 3, 52 + HPWMI_WIFI = 0x0, 53 + HPWMI_BLUETOOTH = 0x1, 54 + HPWMI_WWAN = 0x2, 55 + HPWMI_GPS = 0x3, 68 56 }; 69 57 70 58 enum hp_wmi_event_ids { 71 - HPWMI_DOCK_EVENT = 1, 72 - HPWMI_PARK_HDD = 2, 73 - HPWMI_SMART_ADAPTER = 3, 74 - HPWMI_BEZEL_BUTTON = 4, 75 - HPWMI_WIRELESS = 5, 76 - HPWMI_CPU_BATTERY_THROTTLE = 6, 77 - HPWMI_LOCK_SWITCH = 7, 78 - HPWMI_LID_SWITCH = 8, 79 - HPWMI_SCREEN_ROTATION = 9, 80 - HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A, 81 - HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B, 82 - HPWMI_PROXIMITY_SENSOR = 0x0C, 83 - HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, 84 - HPWMI_PEAKSHIFT_PERIOD = 0x0F, 85 - HPWMI_BATTERY_CHARGE_PERIOD = 0x10, 59 + HPWMI_DOCK_EVENT = 0x01, 60 + HPWMI_PARK_HDD = 0x02, 61 + HPWMI_SMART_ADAPTER = 0x03, 62 + HPWMI_BEZEL_BUTTON = 0x04, 63 + HPWMI_WIRELESS = 0x05, 64 + HPWMI_CPU_BATTERY_THROTTLE = 0x06, 65 + HPWMI_LOCK_SWITCH = 0x07, 66 + HPWMI_LID_SWITCH = 0x08, 67 + HPWMI_SCREEN_ROTATION = 0x09, 68 + HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A, 69 + HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B, 70 + HPWMI_PROXIMITY_SENSOR = 0x0C, 71 + HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, 72 + HPWMI_PEAKSHIFT_PERIOD = 0x0F, 73 + HPWMI_BATTERY_CHARGE_PERIOD = 0x10, 86 74 }; 87 75 88 76 struct bios_args { ··· 80 92 u32 datasize; 81 93 u32 data; 82 94 }; 95 + 96 + enum hp_wmi_commandtype { 97 + HPWMI_DISPLAY_QUERY = 0x01, 98 + HPWMI_HDDTEMP_QUERY = 0x02, 99 + HPWMI_ALS_QUERY = 0x03, 100 + HPWMI_HARDWARE_QUERY = 0x04, 101 + HPWMI_WIRELESS_QUERY = 0x05, 102 + HPWMI_BATTERY_QUERY = 0x07, 103 + HPWMI_BIOS_QUERY = 0x09, 104 + HPWMI_FEATURE_QUERY = 0x0b, 105 + HPWMI_HOTKEY_QUERY = 0x0c, 106 + HPWMI_FEATURE2_QUERY = 0x0d, 107 + HPWMI_WIRELESS2_QUERY = 0x1b, 108 + HPWMI_POSTCODEERROR_QUERY = 0x2a, 109 + }; 110 + 111 + enum hp_wmi_command { 112 + HPWMI_READ = 0x01, 113 + HPWMI_WRITE = 0x02, 114 + HPWMI_ODM = 0x03, 115 + }; 116 + 117 + enum hp_wmi_hardware_mask { 118 + HPWMI_DOCK_MASK = 0x01, 119 + HPWMI_TABLET_MASK = 0x04, 120 + }; 121 + 122 + #define BIOS_ARGS_INIT(write, ctype, size) \ 123 + (struct bios_args) { .signature = 0x55434553, \ 124 + .command = (write) ? 0x2 : 0x1, \ 125 + .commandtype = (ctype), \ 126 + .datasize = (size), \ 127 + .data = 0 } 83 128 84 129 struct bios_return { 85 130 u32 sigpass; ··· 191 170 /* 192 171 * hp_wmi_perform_query 193 172 * 194 - * query: The commandtype -> What should be queried 195 - * write: The command -> 0 read, 1 write, 3 ODM specific 173 + * query: The commandtype (enum hp_wmi_commandtype) 174 + * write: The command (enum hp_wmi_command) 196 175 * buffer: Buffer used as input and/or output 197 176 * insize: Size of input buffer 198 177 * outsize: Size of output buffer ··· 203 182 * -EINVAL if the output buffer size exceeds buffersize 204 183 * 205 184 * Note: The buffersize must at least be the maximum of the input and output 206 - * size. E.g. Battery info query (0x7) is defined to have 1 byte input 185 + * size. E.g. Battery info query is defined to have 1 byte input 207 186 * and 128 byte output. The caller would do: 208 187 * buffer = kzalloc(128, GFP_KERNEL); 209 - * ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128) 188 + * ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128) 210 189 */ 211 - static int hp_wmi_perform_query(int query, int write, void *buffer, 212 - int insize, int outsize) 190 + static int hp_wmi_perform_query(int query, enum hp_wmi_command command, 191 + void *buffer, int insize, int outsize) 213 192 { 214 193 struct bios_return *bios_return; 215 194 int actual_outsize; 216 195 union acpi_object *obj; 217 196 struct bios_args args = { 218 197 .signature = 0x55434553, 219 - .command = write ? 0x2 : 0x1, 198 + .command = command, 220 199 .commandtype = query, 221 200 .datasize = insize, 222 201 .data = 0, 223 202 }; 224 203 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 225 204 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 226 - u32 rc; 205 + int ret = 0; 227 206 228 207 if (WARN_ON(insize > sizeof(args.data))) 229 208 return -EINVAL; ··· 235 214 236 215 if (!obj) 237 216 return -EINVAL; 238 - else if (obj->type != ACPI_TYPE_BUFFER) { 239 - kfree(obj); 240 - return -EINVAL; 217 + 218 + if (obj->type != ACPI_TYPE_BUFFER) { 219 + ret = -EINVAL; 220 + goto out_free; 241 221 } 242 222 243 223 bios_return = (struct bios_return *)obj->buffer.pointer; 244 - rc = bios_return->return_code; 224 + ret = bios_return->return_code; 245 225 246 - if (rc) { 247 - if (rc != HPWMI_RET_UNKNOWN_CMDTYPE) 248 - pr_warn("query 0x%x returned error 0x%x\n", query, rc); 249 - kfree(obj); 250 - return rc; 226 + if (ret) { 227 + if (ret != HPWMI_RET_UNKNOWN_CMDTYPE) 228 + pr_warn("query 0x%x returned error 0x%x\n", query, ret); 229 + goto out_free; 251 230 } 252 231 253 - if (!outsize) { 254 - /* ignore output data */ 255 - kfree(obj); 256 - return 0; 257 - } 232 + /* Ignore output data of zero size */ 233 + if (!outsize) 234 + goto out_free; 258 235 259 236 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); 260 237 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); 261 238 memset(buffer + actual_outsize, 0, outsize - actual_outsize); 239 + 240 + out_free: 262 241 kfree(obj); 263 - return 0; 242 + return ret; 264 243 } 265 244 266 - static int hp_wmi_display_state(void) 245 + static int hp_wmi_read_int(int query) 267 246 { 268 - int state = 0; 269 - int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, 270 - sizeof(state), sizeof(state)); 247 + int val = 0, ret; 248 + 249 + ret = hp_wmi_perform_query(query, HPWMI_READ, &val, 250 + sizeof(val), sizeof(val)); 251 + 271 252 if (ret) 272 - return -EINVAL; 273 - return state; 253 + return ret < 0 ? ret : -EINVAL; 254 + 255 + return val; 274 256 } 275 257 276 - static int hp_wmi_hddtemp_state(void) 258 + static int hp_wmi_hw_state(int mask) 277 259 { 278 - int state = 0; 279 - int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, 280 - sizeof(state), sizeof(state)); 281 - if (ret) 282 - return -EINVAL; 283 - return state; 284 - } 260 + int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); 285 261 286 - static int hp_wmi_als_state(void) 287 - { 288 - int state = 0; 289 - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, 290 - sizeof(state), sizeof(state)); 291 - if (ret) 292 - return -EINVAL; 293 - return state; 294 - } 295 - 296 - static int hp_wmi_dock_state(void) 297 - { 298 - int state = 0; 299 - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, 300 - sizeof(state), sizeof(state)); 301 - 302 - if (ret) 303 - return -EINVAL; 262 + if (state < 0) 263 + return state; 304 264 305 265 return state & 0x1; 306 - } 307 - 308 - static int hp_wmi_tablet_state(void) 309 - { 310 - int state = 0; 311 - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, 312 - sizeof(state), sizeof(state)); 313 - if (ret) 314 - return ret; 315 - 316 - return (state & 0x4) ? 1 : 0; 317 266 } 318 267 319 268 static int __init hp_wmi_bios_2008_later(void) 320 269 { 321 270 int state = 0; 322 - int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, 271 + int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state, 323 272 sizeof(state), sizeof(state)); 324 273 if (!ret) 325 274 return 1; ··· 300 309 static int __init hp_wmi_bios_2009_later(void) 301 310 { 302 311 int state = 0; 303 - int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state, 312 + int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state, 304 313 sizeof(state), sizeof(state)); 305 314 if (!ret) 306 315 return 1; ··· 311 320 static int __init hp_wmi_enable_hotkeys(void) 312 321 { 313 322 int value = 0x6e; 314 - int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value, 323 + int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value, 315 324 sizeof(value), 0); 316 - if (ret) 317 - return -EINVAL; 318 - return 0; 325 + 326 + return ret <= 0 ? ret : -EINVAL; 319 327 } 320 328 321 329 static int hp_wmi_set_block(void *data, bool blocked) ··· 323 333 int query = BIT(r + 8) | ((!blocked) << r); 324 334 int ret; 325 335 326 - ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 336 + ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, 327 337 &query, sizeof(query), 0); 328 - if (ret) 329 - return -EINVAL; 330 - return 0; 338 + 339 + return ret <= 0 ? ret : -EINVAL; 331 340 } 332 341 333 342 static const struct rfkill_ops hp_wmi_rfkill_ops = { ··· 335 346 336 347 static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 337 348 { 338 - int wireless = 0; 339 - int mask; 340 - hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 341 - &wireless, sizeof(wireless), 342 - sizeof(wireless)); 349 + int mask = 0x200 << (r * 8); 350 + 351 + int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 352 + 343 353 /* TBD: Pass error */ 354 + WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 344 355 345 - mask = 0x200 << (r * 8); 346 - 347 - if (wireless & mask) 348 - return false; 349 - else 350 - return true; 356 + return !(wireless & mask); 351 357 } 352 358 353 359 static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 354 360 { 355 - int wireless = 0; 356 - int mask; 357 - hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 358 - &wireless, sizeof(wireless), 359 - sizeof(wireless)); 361 + int mask = 0x800 << (r * 8); 362 + 363 + int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 364 + 360 365 /* TBD: Pass error */ 366 + WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 361 367 362 - mask = 0x800 << (r * 8); 363 - 364 - if (wireless & mask) 365 - return false; 366 - else 367 - return true; 368 + return !(wireless & mask); 368 369 } 369 370 370 371 static int hp_wmi_rfkill2_set_block(void *data, bool blocked) 371 372 { 372 373 int rfkill_id = (int)(long)data; 373 374 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; 375 + int ret; 374 376 375 - if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1, 376 - buffer, sizeof(buffer), 0)) 377 - return -EINVAL; 378 - return 0; 377 + ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE, 378 + buffer, sizeof(buffer), 0); 379 + 380 + return ret <= 0 ? ret : -EINVAL; 379 381 } 380 382 381 383 static const struct rfkill_ops hp_wmi_rfkill2_ops = { ··· 375 395 376 396 static int hp_wmi_rfkill2_refresh(void) 377 397 { 378 - int err, i; 379 398 struct bios_rfkill2_state state; 399 + int err, i; 380 400 381 - err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 401 + err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 382 402 0, sizeof(state)); 383 403 if (err) 384 404 return err; ··· 402 422 return 0; 403 423 } 404 424 405 - static int hp_wmi_post_code_state(void) 406 - { 407 - int state = 0; 408 - int ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 0, &state, 409 - sizeof(state), sizeof(state)); 410 - if (ret) 411 - return -EINVAL; 412 - return state; 413 - } 414 - 415 - static ssize_t show_display(struct device *dev, struct device_attribute *attr, 425 + static ssize_t display_show(struct device *dev, struct device_attribute *attr, 416 426 char *buf) 417 427 { 418 - int value = hp_wmi_display_state(); 428 + int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY); 419 429 if (value < 0) 420 - return -EINVAL; 430 + return value; 421 431 return sprintf(buf, "%d\n", value); 422 432 } 423 433 424 - static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr, 434 + static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr, 425 435 char *buf) 426 436 { 427 - int value = hp_wmi_hddtemp_state(); 437 + int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY); 428 438 if (value < 0) 429 - return -EINVAL; 439 + return value; 430 440 return sprintf(buf, "%d\n", value); 431 441 } 432 442 433 - static ssize_t show_als(struct device *dev, struct device_attribute *attr, 443 + static ssize_t als_show(struct device *dev, struct device_attribute *attr, 434 444 char *buf) 435 445 { 436 - int value = hp_wmi_als_state(); 446 + int value = hp_wmi_read_int(HPWMI_ALS_QUERY); 437 447 if (value < 0) 438 - return -EINVAL; 448 + return value; 439 449 return sprintf(buf, "%d\n", value); 440 450 } 441 451 442 - static ssize_t show_dock(struct device *dev, struct device_attribute *attr, 452 + static ssize_t dock_show(struct device *dev, struct device_attribute *attr, 443 453 char *buf) 444 454 { 445 - int value = hp_wmi_dock_state(); 455 + int value = hp_wmi_hw_state(HPWMI_DOCK_MASK); 446 456 if (value < 0) 447 - return -EINVAL; 457 + return value; 448 458 return sprintf(buf, "%d\n", value); 449 459 } 450 460 451 - static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, 452 - char *buf) 461 + static ssize_t tablet_show(struct device *dev, struct device_attribute *attr, 462 + char *buf) 453 463 { 454 - int value = hp_wmi_tablet_state(); 464 + int value = hp_wmi_hw_state(HPWMI_TABLET_MASK); 455 465 if (value < 0) 456 - return -EINVAL; 466 + return value; 457 467 return sprintf(buf, "%d\n", value); 458 468 } 459 469 460 - static ssize_t show_postcode(struct device *dev, struct device_attribute *attr, 461 - char *buf) 470 + static ssize_t postcode_show(struct device *dev, struct device_attribute *attr, 471 + char *buf) 462 472 { 463 473 /* Get the POST error code of previous boot failure. */ 464 - int value = hp_wmi_post_code_state(); 474 + int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY); 465 475 if (value < 0) 466 - return -EINVAL; 476 + return value; 467 477 return sprintf(buf, "0x%x\n", value); 468 478 } 469 479 470 - static ssize_t set_als(struct device *dev, struct device_attribute *attr, 471 - const char *buf, size_t count) 480 + static ssize_t als_store(struct device *dev, struct device_attribute *attr, 481 + const char *buf, size_t count) 472 482 { 473 483 u32 tmp = simple_strtoul(buf, NULL, 10); 474 - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, 484 + int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp, 475 485 sizeof(tmp), sizeof(tmp)); 476 486 if (ret) 477 - return -EINVAL; 487 + return ret < 0 ? ret : -EINVAL; 478 488 479 489 return count; 480 490 } 481 491 482 - static ssize_t set_postcode(struct device *dev, struct device_attribute *attr, 483 - const char *buf, size_t count) 492 + static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, 493 + const char *buf, size_t count) 484 494 { 495 + long unsigned int tmp2; 485 496 int ret; 486 497 u32 tmp; 487 - long unsigned int tmp2; 488 498 489 499 ret = kstrtoul(buf, 10, &tmp2); 490 - if (ret || tmp2 != 1) 491 - return -EINVAL; 500 + if (!ret && tmp2 != 1) 501 + ret = -EINVAL; 502 + if (ret) 503 + goto out; 492 504 493 505 /* Clear the POST error code. It is kept until until cleared. */ 494 506 tmp = (u32) tmp2; 495 - ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 1, &tmp, 507 + ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, 496 508 sizeof(tmp), sizeof(tmp)); 509 + 510 + out: 497 511 if (ret) 498 - return -EINVAL; 512 + return ret < 0 ? ret : -EINVAL; 499 513 500 514 return count; 501 515 } 502 516 503 - static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); 504 - static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); 505 - static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); 506 - static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 507 - static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 508 - static DEVICE_ATTR(postcode, S_IRUGO | S_IWUSR, show_postcode, set_postcode); 517 + static DEVICE_ATTR_RO(display); 518 + static DEVICE_ATTR_RO(hddtemp); 519 + static DEVICE_ATTR_RW(als); 520 + static DEVICE_ATTR_RO(dock); 521 + static DEVICE_ATTR_RO(tablet); 522 + static DEVICE_ATTR_RW(postcode); 509 523 510 524 static void hp_wmi_notify(u32 value, void *context) 511 525 { 512 526 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 513 - union acpi_object *obj; 514 527 u32 event_id, event_data; 515 - int key_code = 0, ret; 516 - u32 *location; 528 + union acpi_object *obj; 517 529 acpi_status status; 530 + u32 *location; 531 + int key_code; 518 532 519 533 status = wmi_get_event_data(value, &response); 520 534 if (status != AE_OK) { ··· 546 572 547 573 switch (event_id) { 548 574 case HPWMI_DOCK_EVENT: 549 - input_report_switch(hp_wmi_input_dev, SW_DOCK, 550 - hp_wmi_dock_state()); 551 - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 552 - hp_wmi_tablet_state()); 575 + if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 576 + input_report_switch(hp_wmi_input_dev, SW_DOCK, 577 + hp_wmi_hw_state(HPWMI_DOCK_MASK)); 578 + if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 579 + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 580 + hp_wmi_hw_state(HPWMI_TABLET_MASK)); 553 581 input_sync(hp_wmi_input_dev); 554 582 break; 555 583 case HPWMI_PARK_HDD: ··· 559 583 case HPWMI_SMART_ADAPTER: 560 584 break; 561 585 case HPWMI_BEZEL_BUTTON: 562 - ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 563 - &key_code, 564 - sizeof(key_code), 565 - sizeof(key_code)); 566 - if (ret) 586 + key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); 587 + if (key_code < 0) 567 588 break; 568 589 569 590 if (!sparse_keymap_report_event(hp_wmi_input_dev, ··· 616 643 static int __init hp_wmi_input_setup(void) 617 644 { 618 645 acpi_status status; 619 - int err; 646 + int err, val; 620 647 621 648 hp_wmi_input_dev = input_allocate_device(); 622 649 if (!hp_wmi_input_dev) ··· 627 654 hp_wmi_input_dev->id.bustype = BUS_HOST; 628 655 629 656 __set_bit(EV_SW, hp_wmi_input_dev->evbit); 630 - __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 631 - __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 657 + 658 + /* Dock */ 659 + val = hp_wmi_hw_state(HPWMI_DOCK_MASK); 660 + if (!(val < 0)) { 661 + __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 662 + input_report_switch(hp_wmi_input_dev, SW_DOCK, val); 663 + } 664 + 665 + /* Tablet mode */ 666 + val = hp_wmi_hw_state(HPWMI_TABLET_MASK); 667 + if (!(val < 0)) { 668 + __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 669 + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); 670 + } 632 671 633 672 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); 634 673 if (err) 635 674 goto err_free_dev; 636 675 637 676 /* Set initial hardware state */ 638 - input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); 639 - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 640 - hp_wmi_tablet_state()); 641 677 input_sync(hp_wmi_input_dev); 642 678 643 679 if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) ··· 655 673 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); 656 674 if (ACPI_FAILURE(status)) { 657 675 err = -EIO; 658 - goto err_free_keymap; 676 + goto err_free_dev; 659 677 } 660 678 661 679 err = input_register_device(hp_wmi_input_dev); ··· 666 684 667 685 err_uninstall_notifier: 668 686 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 669 - err_free_keymap: 670 - sparse_keymap_free(hp_wmi_input_dev); 671 687 err_free_dev: 672 688 input_free_device(hp_wmi_input_dev); 673 689 return err; ··· 674 694 static void hp_wmi_input_destroy(void) 675 695 { 676 696 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 677 - sparse_keymap_free(hp_wmi_input_dev); 678 697 input_unregister_device(hp_wmi_input_dev); 679 698 } 680 699 ··· 689 710 690 711 static int __init hp_wmi_rfkill_setup(struct platform_device *device) 691 712 { 692 - int err; 693 - int wireless = 0; 713 + int err, wireless; 694 714 695 - err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, 696 - sizeof(wireless), sizeof(wireless)); 697 - if (err) 698 - return err; 715 + wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 716 + if (wireless < 0) 717 + return wireless; 699 718 700 - err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless, 719 + err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless, 701 720 sizeof(wireless), 0); 702 721 if (err) 703 722 return err; ··· 772 795 773 796 static int __init hp_wmi_rfkill2_setup(struct platform_device *device) 774 797 { 775 - int err, i; 776 798 struct bios_rfkill2_state state; 777 - err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 799 + int err, i; 800 + 801 + err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 778 802 0, sizeof(state)); 779 803 if (err) 780 - return err; 804 + return err < 0 ? err : -EINVAL; 781 805 782 806 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { 783 807 pr_warn("unable to parse 0x1b query output\n"); ··· 928 950 * changed. 929 951 */ 930 952 if (hp_wmi_input_dev) { 931 - input_report_switch(hp_wmi_input_dev, SW_DOCK, 932 - hp_wmi_dock_state()); 933 - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 934 - hp_wmi_tablet_state()); 953 + if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 954 + input_report_switch(hp_wmi_input_dev, SW_DOCK, 955 + hp_wmi_hw_state(HPWMI_DOCK_MASK)); 956 + if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 957 + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 958 + hp_wmi_hw_state(HPWMI_TABLET_MASK)); 935 959 input_sync(hp_wmi_input_dev); 936 960 } 937 961 ··· 971 991 972 992 static int __init hp_wmi_init(void) 973 993 { 974 - int err; 975 994 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); 976 995 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 996 + int err; 977 997 978 998 if (!bios_capable && !event_capable) 979 999 return -ENODEV;
+15 -4
drivers/platform/x86/ideapad-laptop.c
··· 604 604 error = input_register_device(inputdev); 605 605 if (error) { 606 606 pr_err("Unable to register input device\n"); 607 - goto err_free_keymap; 607 + goto err_free_dev; 608 608 } 609 609 610 610 priv->inputdev = inputdev; 611 611 return 0; 612 612 613 - err_free_keymap: 614 - sparse_keymap_free(inputdev); 615 613 err_free_dev: 616 614 input_free_device(inputdev); 617 615 return error; ··· 617 619 618 620 static void ideapad_input_exit(struct ideapad_private *priv) 619 621 { 620 - sparse_keymap_free(priv->inputdev); 621 622 input_unregister_device(priv->inputdev); 622 623 priv->inputdev = NULL; 623 624 } ··· 866 869 .matches = { 867 870 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 868 871 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"), 872 + }, 873 + }, 874 + { 875 + .ident = "Lenovo V310-15ISK", 876 + .matches = { 877 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 878 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"), 879 + }, 880 + }, 881 + { 882 + .ident = "Lenovo ideapad 310-15IKB", 883 + .matches = { 884 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 885 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"), 869 886 }, 870 887 }, 871 888 {
+13 -38
drivers/platform/x86/intel-hid.c
··· 77 77 struct input_dev *array; 78 78 }; 79 79 80 - static int intel_hid_set_enable(struct device *device, int enable) 80 + static int intel_hid_set_enable(struct device *device, bool enable) 81 81 { 82 - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 83 - struct acpi_object_list args = { 1, &arg0 }; 84 82 acpi_status status; 85 83 86 - arg0.integer.value = enable; 87 - status = acpi_evaluate_object(ACPI_HANDLE(device), "HDSM", &args, NULL); 84 + status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM", 85 + enable); 88 86 if (ACPI_FAILURE(status)) { 89 87 dev_warn(device, "failed to %sable hotkeys\n", 90 88 enable ? "en" : "dis"); ··· 118 120 119 121 static int intel_hid_pl_suspend_handler(struct device *device) 120 122 { 121 - intel_hid_set_enable(device, 0); 123 + intel_hid_set_enable(device, false); 122 124 intel_button_array_enable(device, false); 123 125 124 126 return 0; ··· 126 128 127 129 static int intel_hid_pl_resume_handler(struct device *device) 128 130 { 129 - intel_hid_set_enable(device, 1); 131 + intel_hid_set_enable(device, true); 130 132 intel_button_array_enable(device, true); 131 133 132 134 return 0; ··· 134 136 135 137 static const struct dev_pm_ops intel_hid_pl_pm_ops = { 136 138 .freeze = intel_hid_pl_suspend_handler, 139 + .thaw = intel_hid_pl_resume_handler, 137 140 .restore = intel_hid_pl_resume_handler, 138 141 .suspend = intel_hid_pl_suspend_handler, 139 142 .resume = intel_hid_pl_resume_handler, ··· 145 146 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); 146 147 int ret; 147 148 148 - priv->input_dev = input_allocate_device(); 149 + priv->input_dev = devm_input_allocate_device(&device->dev); 149 150 if (!priv->input_dev) 150 151 return -ENOMEM; 151 152 152 153 ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL); 153 154 if (ret) 154 - goto err_free_device; 155 + return ret; 155 156 156 - priv->input_dev->dev.parent = &device->dev; 157 157 priv->input_dev->name = "Intel HID events"; 158 158 priv->input_dev->id.bustype = BUS_HOST; 159 - set_bit(KEY_RFKILL, priv->input_dev->keybit); 160 159 161 - ret = input_register_device(priv->input_dev); 162 - if (ret) 163 - goto err_free_device; 164 - 165 - return 0; 166 - 167 - err_free_device: 168 - input_free_device(priv->input_dev); 169 - return ret; 160 + return input_register_device(priv->input_dev); 170 161 } 171 162 172 163 static int intel_button_array_input_setup(struct platform_device *device) ··· 173 184 if (ret) 174 185 return ret; 175 186 176 - priv->array->dev.parent = &device->dev; 177 187 priv->array->name = "Intel HID 5 button array"; 178 188 priv->array->id.bustype = BUS_HOST; 179 189 180 190 return input_register_device(priv->array); 181 - } 182 - 183 - static void intel_hid_input_destroy(struct platform_device *device) 184 - { 185 - struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); 186 - 187 - input_unregister_device(priv->input_dev); 188 191 } 189 192 190 193 static void notify_handler(acpi_handle handle, u32 event, void *context) ··· 253 272 ACPI_DEVICE_NOTIFY, 254 273 notify_handler, 255 274 device); 256 - if (ACPI_FAILURE(status)) { 257 - err = -EBUSY; 258 - goto err_remove_input; 259 - } 275 + if (ACPI_FAILURE(status)) 276 + return -EBUSY; 260 277 261 - err = intel_hid_set_enable(&device->dev, 1); 278 + err = intel_hid_set_enable(&device->dev, true); 262 279 if (err) 263 280 goto err_remove_notify; 264 281 ··· 275 296 err_remove_notify: 276 297 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 277 298 278 - err_remove_input: 279 - intel_hid_input_destroy(device); 280 - 281 299 return err; 282 300 } 283 301 ··· 283 307 acpi_handle handle = ACPI_HANDLE(&device->dev); 284 308 285 309 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 286 - intel_hid_input_destroy(device); 287 - intel_hid_set_enable(&device->dev, 0); 310 + intel_hid_set_enable(&device->dev, false); 288 311 intel_button_array_enable(&device->dev, false); 289 312 290 313 /*
+4
drivers/platform/x86/intel-vbtn.c
··· 37 37 static const struct key_entry intel_vbtn_keymap[] = { 38 38 { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */ 39 39 { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */ 40 + { KE_KEY, 0xC4, { KEY_VOLUMEUP } }, /* volume-up key press */ 41 + { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* volume-up key release */ 42 + { KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* volume-down key press */ 43 + { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */ 40 44 { KE_END }, 41 45 }; 42 46
+143
drivers/platform/x86/intel_cht_int33fe.c
··· 1 + /* 2 + * Intel Cherry Trail ACPI INT33FE pseudo device driver 3 + * 4 + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + * Some Intel Cherry Trail based device which ship with Windows 10, have 11 + * this weird INT33FE ACPI device with a CRS table with 4 I2cSerialBusV2 12 + * resources, for 4 different chips attached to various i2c busses: 13 + * 1. The Whiskey Cove pmic, which is also described by the INT34D3 ACPI device 14 + * 2. Maxim MAX17047 Fuel Gauge Controller 15 + * 3. FUSB302 USB Type-C Controller 16 + * 4. PI3USB30532 USB switch 17 + * 18 + * So this driver is a stub / pseudo driver whose only purpose is to 19 + * instantiate i2c-clients for chips 2 - 4, so that standard i2c drivers 20 + * for these chips can bind to the them. 21 + */ 22 + 23 + #include <linux/acpi.h> 24 + #include <linux/i2c.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/module.h> 27 + #include <linux/slab.h> 28 + 29 + #define EXPECTED_PTYPE 4 30 + 31 + struct cht_int33fe_data { 32 + struct i2c_client *max17047; 33 + struct i2c_client *fusb302; 34 + struct i2c_client *pi3usb30532; 35 + }; 36 + 37 + static int cht_int33fe_probe(struct i2c_client *client) 38 + { 39 + struct device *dev = &client->dev; 40 + struct i2c_board_info board_info; 41 + struct cht_int33fe_data *data; 42 + unsigned long long ptyp; 43 + acpi_status status; 44 + int fusb302_irq; 45 + 46 + status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp); 47 + if (ACPI_FAILURE(status)) { 48 + dev_err(dev, "Error getting PTYPE\n"); 49 + return -ENODEV; 50 + } 51 + 52 + /* 53 + * The same ACPI HID is used for different configurations check PTYP 54 + * to ensure that we are dealing with the expected config. 55 + */ 56 + if (ptyp != EXPECTED_PTYPE) 57 + return -ENODEV; 58 + 59 + /* The FUSB302 uses the irq at index 1 and is the only irq user */ 60 + fusb302_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 1); 61 + if (fusb302_irq < 0) { 62 + if (fusb302_irq != -EPROBE_DEFER) 63 + dev_err(dev, "Error getting FUSB302 irq\n"); 64 + return fusb302_irq; 65 + } 66 + 67 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 68 + if (!data) 69 + return -ENOMEM; 70 + 71 + memset(&board_info, 0, sizeof(board_info)); 72 + strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); 73 + 74 + data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); 75 + if (!data->max17047) 76 + return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ 77 + 78 + memset(&board_info, 0, sizeof(board_info)); 79 + strlcpy(board_info.type, "fusb302", I2C_NAME_SIZE); 80 + board_info.irq = fusb302_irq; 81 + 82 + data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); 83 + if (!data->fusb302) 84 + goto out_unregister_max17047; 85 + 86 + memset(&board_info, 0, sizeof(board_info)); 87 + strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); 88 + 89 + data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); 90 + if (!data->pi3usb30532) 91 + goto out_unregister_fusb302; 92 + 93 + i2c_set_clientdata(client, data); 94 + 95 + return 0; 96 + 97 + out_unregister_fusb302: 98 + i2c_unregister_device(data->fusb302); 99 + 100 + out_unregister_max17047: 101 + i2c_unregister_device(data->max17047); 102 + 103 + return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ 104 + } 105 + 106 + static int cht_int33fe_remove(struct i2c_client *i2c) 107 + { 108 + struct cht_int33fe_data *data = i2c_get_clientdata(i2c); 109 + 110 + i2c_unregister_device(data->pi3usb30532); 111 + i2c_unregister_device(data->fusb302); 112 + i2c_unregister_device(data->max17047); 113 + 114 + return 0; 115 + } 116 + 117 + static const struct i2c_device_id cht_int33fe_i2c_id[] = { 118 + { } 119 + }; 120 + MODULE_DEVICE_TABLE(i2c, cht_int33fe_i2c_id); 121 + 122 + static const struct acpi_device_id cht_int33fe_acpi_ids[] = { 123 + { "INT33FE", }, 124 + { } 125 + }; 126 + MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids); 127 + 128 + static struct i2c_driver cht_int33fe_driver = { 129 + .driver = { 130 + .name = "Intel Cherry Trail ACPI INT33FE driver", 131 + .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), 132 + }, 133 + .probe_new = cht_int33fe_probe, 134 + .remove = cht_int33fe_remove, 135 + .id_table = cht_int33fe_i2c_id, 136 + .disable_i2c_core_irq_mapping = true, 137 + }; 138 + 139 + module_i2c_driver(cht_int33fe_driver); 140 + 141 + MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver"); 142 + MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 143 + MODULE_LICENSE("GPL");
+136 -20
drivers/platform/x86/intel_pmc_ipc.c
··· 57 57 #define IPC_WRITE_BUFFER 0x80 58 58 #define IPC_READ_BUFFER 0x90 59 59 60 - /* PMC Global Control Registers */ 61 - #define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078 62 - #define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080 63 - 64 60 /* Residency with clock rate at 19.2MHz to usecs */ 65 61 #define S0IX_RESIDENCY_IN_USECS(d, s) \ 66 62 ({ \ ··· 78 82 /* exported resources from IFWI */ 79 83 #define PLAT_RESOURCE_IPC_INDEX 0 80 84 #define PLAT_RESOURCE_IPC_SIZE 0x1000 81 - #define PLAT_RESOURCE_GCR_OFFSET 0x1008 85 + #define PLAT_RESOURCE_GCR_OFFSET 0x1000 82 86 #define PLAT_RESOURCE_GCR_SIZE 0x1000 83 87 #define PLAT_RESOURCE_BIOS_DATA_INDEX 1 84 88 #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 ··· 108 112 #define TCO_PMC_OFFSET 0x8 109 113 #define TCO_PMC_SIZE 0x4 110 114 115 + /* PMC register bit definitions */ 116 + 117 + /* PMC_CFG_REG bit masks */ 118 + #define PMC_CFG_NO_REBOOT_MASK (1 << 4) 119 + #define PMC_CFG_NO_REBOOT_EN (1 << 4) 120 + #define PMC_CFG_NO_REBOOT_DIS (0 << 4) 121 + 111 122 static struct intel_pmc_ipc_dev { 112 123 struct device *dev; 113 124 void __iomem *ipc_base; ··· 129 126 struct platform_device *tco_dev; 130 127 131 128 /* gcr */ 132 - resource_size_t gcr_base; 133 - int gcr_size; 129 + void __iomem *gcr_mem_base; 134 130 bool has_gcr_regs; 135 131 136 132 /* punit */ ··· 198 196 199 197 static inline u64 gcr_data_readq(u32 offset) 200 198 { 201 - return readq(ipcdev.ipc_base + offset); 199 + return readq(ipcdev.gcr_mem_base + offset); 200 + } 201 + 202 + static inline int is_gcr_valid(u32 offset) 203 + { 204 + if (!ipcdev.has_gcr_regs) 205 + return -EACCES; 206 + 207 + if (offset > PLAT_RESOURCE_GCR_SIZE) 208 + return -EINVAL; 209 + 210 + return 0; 211 + } 212 + 213 + /** 214 + * intel_pmc_gcr_read() - Read PMC GCR register 215 + * @offset: offset of GCR register from GCR address base 216 + * @data: data pointer for storing the register output 217 + * 218 + * Reads the PMC GCR register of given offset. 219 + * 220 + * Return: negative value on error or 0 on success. 221 + */ 222 + int intel_pmc_gcr_read(u32 offset, u32 *data) 223 + { 224 + int ret; 225 + 226 + mutex_lock(&ipclock); 227 + 228 + ret = is_gcr_valid(offset); 229 + if (ret < 0) { 230 + mutex_unlock(&ipclock); 231 + return ret; 232 + } 233 + 234 + *data = readl(ipcdev.gcr_mem_base + offset); 235 + 236 + mutex_unlock(&ipclock); 237 + 238 + return 0; 239 + } 240 + EXPORT_SYMBOL_GPL(intel_pmc_gcr_read); 241 + 242 + /** 243 + * intel_pmc_gcr_write() - Write PMC GCR register 244 + * @offset: offset of GCR register from GCR address base 245 + * @data: register update value 246 + * 247 + * Writes the PMC GCR register of given offset with given 248 + * value. 249 + * 250 + * Return: negative value on error or 0 on success. 251 + */ 252 + int intel_pmc_gcr_write(u32 offset, u32 data) 253 + { 254 + int ret; 255 + 256 + mutex_lock(&ipclock); 257 + 258 + ret = is_gcr_valid(offset); 259 + if (ret < 0) { 260 + mutex_unlock(&ipclock); 261 + return ret; 262 + } 263 + 264 + writel(data, ipcdev.gcr_mem_base + offset); 265 + 266 + mutex_unlock(&ipclock); 267 + 268 + return 0; 269 + } 270 + EXPORT_SYMBOL_GPL(intel_pmc_gcr_write); 271 + 272 + /** 273 + * intel_pmc_gcr_update() - Update PMC GCR register bits 274 + * @offset: offset of GCR register from GCR address base 275 + * @mask: bit mask for update operation 276 + * @val: update value 277 + * 278 + * Updates the bits of given GCR register as specified by 279 + * @mask and @val. 280 + * 281 + * Return: negative value on error or 0 on success. 282 + */ 283 + int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) 284 + { 285 + u32 new_val; 286 + int ret = 0; 287 + 288 + mutex_lock(&ipclock); 289 + 290 + ret = is_gcr_valid(offset); 291 + if (ret < 0) 292 + goto gcr_ipc_unlock; 293 + 294 + new_val = readl(ipcdev.gcr_mem_base + offset); 295 + 296 + new_val &= ~mask; 297 + new_val |= val & mask; 298 + 299 + writel(new_val, ipcdev.gcr_mem_base + offset); 300 + 301 + new_val = readl(ipcdev.gcr_mem_base + offset); 302 + 303 + /* check whether the bit update is successful */ 304 + if ((new_val & mask) != (val & mask)) { 305 + ret = -EIO; 306 + goto gcr_ipc_unlock; 307 + } 308 + 309 + gcr_ipc_unlock: 310 + mutex_unlock(&ipclock); 311 + return ret; 312 + } 313 + EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); 314 + 315 + static int update_no_reboot_bit(void *priv, bool set) 316 + { 317 + u32 value = set ? PMC_CFG_NO_REBOOT_EN : PMC_CFG_NO_REBOOT_DIS; 318 + 319 + return intel_pmc_gcr_update(PMC_GCR_PMC_CFG_REG, 320 + PMC_CFG_NO_REBOOT_MASK, value); 202 321 } 203 322 204 323 static int intel_pmc_ipc_check_status(void) ··· 639 516 { 640 517 .flags = IORESOURCE_IO, 641 518 }, 642 - /* GCS */ 643 - { 644 - .flags = IORESOURCE_MEM, 645 - }, 646 519 }; 647 520 648 521 static struct itco_wdt_platform_data tco_info = { 649 522 .name = "Apollo Lake SoC", 650 523 .version = 5, 524 + .no_reboot_priv = &ipcdev, 525 + .update_no_reboot_bit = update_no_reboot_bit, 651 526 }; 652 527 653 528 #define TELEMETRY_RESOURCE_PUNIT_SSRAM 0 ··· 701 580 res = tco_res + TCO_RESOURCE_SMI_EN_IO; 702 581 res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; 703 582 res->end = res->start + SMI_EN_SIZE - 1; 704 - 705 - res = tco_res + TCO_RESOURCE_GCR_MEM; 706 - res->start = ipcdev.gcr_base + TCO_PMC_OFFSET; 707 - res->end = res->start + TCO_PMC_SIZE - 1; 708 583 709 584 pdev = platform_device_register_full(&pdevinfo); 710 585 if (IS_ERR(pdev)) ··· 863 746 } 864 747 ipcdev.ipc_base = addr; 865 748 866 - ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET; 867 - ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; 749 + ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; 868 750 dev_info(&pdev->dev, "ipc res: %pR\n", res); 869 751 870 752 ipcdev.telem_res_inval = 0; ··· 898 782 if (!ipcdev.has_gcr_regs) 899 783 return -EACCES; 900 784 901 - deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET); 902 - shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET); 785 + deep = gcr_data_readq(PMC_GCR_TELEM_DEEP_S0IX_REG); 786 + shlw = gcr_data_readq(PMC_GCR_TELEM_SHLW_S0IX_REG); 903 787 904 788 *data = S0IX_RESIDENCY_IN_USECS(deep, shlw); 905 789
+80 -26
drivers/platform/x86/intel_scu_ipc.c
··· 491 491 } 492 492 EXPORT_SYMBOL(intel_scu_ipc_command); 493 493 494 + #define IPC_SPTR 0x08 495 + #define IPC_DPTR 0x0C 496 + 497 + /** 498 + * intel_scu_ipc_raw_command() - IPC command with data and pointers 499 + * @cmd: IPC command code. 500 + * @sub: IPC command sub type. 501 + * @in: input data of this IPC command. 502 + * @inlen: input data length in dwords. 503 + * @out: output data of this IPC command. 504 + * @outlen: output data length in dwords. 505 + * @sptr: data writing to SPTR register. 506 + * @dptr: data writing to DPTR register. 507 + * 508 + * Send an IPC command to SCU with input/output data and source/dest pointers. 509 + * 510 + * Return: an IPC error code or 0 on success. 511 + */ 512 + int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen, 513 + u32 *out, int outlen, u32 dptr, u32 sptr) 514 + { 515 + struct intel_scu_ipc_dev *scu = &ipcdev; 516 + int inbuflen = DIV_ROUND_UP(inlen, 4); 517 + u32 inbuf[4]; 518 + int i, err; 519 + 520 + /* Up to 16 bytes */ 521 + if (inbuflen > 4) 522 + return -EINVAL; 523 + 524 + mutex_lock(&ipclock); 525 + if (scu->dev == NULL) { 526 + mutex_unlock(&ipclock); 527 + return -ENODEV; 528 + } 529 + 530 + writel(dptr, scu->ipc_base + IPC_DPTR); 531 + writel(sptr, scu->ipc_base + IPC_SPTR); 532 + 533 + /* 534 + * SRAM controller doesn't support 8-bit writes, it only 535 + * supports 32-bit writes, so we have to copy input data into 536 + * the temporary buffer, and SCU FW will use the inlen to 537 + * determine the actual input data length in the temporary 538 + * buffer. 539 + */ 540 + memcpy(inbuf, in, inlen); 541 + 542 + for (i = 0; i < inbuflen; i++) 543 + ipc_data_writel(scu, inbuf[i], 4 * i); 544 + 545 + ipc_command(scu, (inlen << 16) | (sub << 12) | cmd); 546 + err = intel_scu_ipc_check_status(scu); 547 + if (!err) { 548 + for (i = 0; i < outlen; i++) 549 + *out++ = ipc_data_readl(scu, 4 * i); 550 + } 551 + 552 + mutex_unlock(&ipclock); 553 + return err; 554 + } 555 + EXPORT_SYMBOL_GPL(intel_scu_ipc_raw_command); 556 + 494 557 /* I2C commands */ 495 558 #define IPC_I2C_WRITE 1 /* I2C Write command */ 496 559 #define IPC_I2C_READ 2 /* I2C Read command */ ··· 629 566 */ 630 567 static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 631 568 { 632 - int platform; /* Platform type */ 633 569 int err; 634 570 struct intel_scu_ipc_dev *scu = &ipcdev; 635 571 struct intel_scu_ipc_pdata_t *pdata; 636 - 637 - platform = intel_mid_identify_cpu(); 638 - if (platform == 0) 639 - return -ENODEV; 640 572 641 573 if (scu->dev) /* We support only one SCU */ 642 574 return -EBUSY; 643 575 644 576 pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data; 577 + if (!pdata) 578 + return -ENODEV; 645 579 646 - scu->dev = &pdev->dev; 647 580 scu->irq_mode = pdata->irq_mode; 648 581 649 582 err = pcim_enable_device(pdev); ··· 652 593 653 594 init_completion(&scu->cmd_complete); 654 595 655 - err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc", 656 - scu); 657 - if (err) 658 - return err; 659 - 660 596 scu->ipc_base = pcim_iomap_table(pdev)[0]; 661 597 662 598 scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len); 663 599 if (!scu->i2c_base) 664 600 return -ENOMEM; 601 + 602 + err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc", 603 + scu); 604 + if (err) 605 + return err; 606 + 607 + /* Assign device at last */ 608 + scu->dev = &pdev->dev; 665 609 666 610 intel_scu_devices_create(); 667 611 ··· 672 610 return 0; 673 611 } 674 612 613 + #define SCU_DEVICE(id, pdata) {PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&pdata} 614 + 675 615 static const struct pci_device_id pci_ids[] = { 676 - { 677 - PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), 678 - (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, 679 - }, { 680 - PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL), 681 - (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, 682 - }, { 683 - PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CLOVERVIEW), 684 - (kernel_ulong_t)&intel_scu_ipc_penwell_pdata, 685 - }, { 686 - PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER), 687 - (kernel_ulong_t)&intel_scu_ipc_tangier_pdata, 688 - }, { 689 - 0, 690 - } 616 + SCU_DEVICE(PCI_DEVICE_ID_LINCROFT, intel_scu_ipc_lincroft_pdata), 617 + SCU_DEVICE(PCI_DEVICE_ID_PENWELL, intel_scu_ipc_penwell_pdata), 618 + SCU_DEVICE(PCI_DEVICE_ID_CLOVERVIEW, intel_scu_ipc_penwell_pdata), 619 + SCU_DEVICE(PCI_DEVICE_ID_TANGIER, intel_scu_ipc_tangier_pdata), 620 + {} 691 621 }; 692 622 693 623 static struct pci_driver ipc_driver = {
+3 -11
drivers/platform/x86/msi-laptop.c
··· 976 976 977 977 err = input_register_device(msi_laptop_input_dev); 978 978 if (err) 979 - goto err_free_keymap; 979 + goto err_free_dev; 980 980 981 981 return 0; 982 982 983 - err_free_keymap: 984 - sparse_keymap_free(msi_laptop_input_dev); 985 983 err_free_dev: 986 984 input_free_device(msi_laptop_input_dev); 987 985 return err; 988 - } 989 - 990 - static void msi_laptop_input_destroy(void) 991 - { 992 - sparse_keymap_free(msi_laptop_input_dev); 993 - input_unregister_device(msi_laptop_input_dev); 994 986 } 995 987 996 988 static int __init load_scm_model_init(struct platform_device *sdev) ··· 1029 1037 return 0; 1030 1038 1031 1039 fail_filter: 1032 - msi_laptop_input_destroy(); 1040 + input_unregister_device(msi_laptop_input_dev); 1033 1041 1034 1042 fail_input: 1035 1043 rfkill_cleanup(); ··· 1150 1158 { 1151 1159 if (quirks->load_scm_model) { 1152 1160 i8042_remove_filter(msi_laptop_i8042_filter); 1153 - msi_laptop_input_destroy(); 1161 + input_unregister_device(msi_laptop_input_dev); 1154 1162 cancel_delayed_work_sync(&msi_rfkill_dwork); 1155 1163 cancel_work_sync(&msi_rfkill_work); 1156 1164 rfkill_cleanup();
+2 -7
drivers/platform/x86/msi-wmi.c
··· 281 281 err = input_register_device(msi_wmi_input_dev); 282 282 283 283 if (err) 284 - goto err_free_keymap; 284 + goto err_free_dev; 285 285 286 286 last_pressed = 0; 287 287 288 288 return 0; 289 289 290 - err_free_keymap: 291 - sparse_keymap_free(msi_wmi_input_dev); 292 290 err_free_dev: 293 291 input_free_device(msi_wmi_input_dev); 294 292 return err; ··· 340 342 if (event_wmi) 341 343 wmi_remove_notify_handler(event_wmi->guid); 342 344 err_free_input: 343 - if (event_wmi) { 344 - sparse_keymap_free(msi_wmi_input_dev); 345 + if (event_wmi) 345 346 input_unregister_device(msi_wmi_input_dev); 346 - } 347 347 return err; 348 348 } 349 349 ··· 349 353 { 350 354 if (event_wmi) { 351 355 wmi_remove_notify_handler(event_wmi->guid); 352 - sparse_keymap_free(msi_wmi_input_dev); 353 356 input_unregister_device(msi_wmi_input_dev); 354 357 } 355 358 backlight_device_unregister(backlight);
+3 -15
drivers/platform/x86/panasonic-laptop.c
··· 520 520 if (error) { 521 521 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 522 522 "Unable to register input device\n")); 523 - goto err_free_keymap; 523 + goto err_free_dev; 524 524 } 525 525 526 526 pcc->input_dev = input_dev; 527 527 return 0; 528 528 529 - err_free_keymap: 530 - sparse_keymap_free(input_dev); 531 529 err_free_dev: 532 530 input_free_device(input_dev); 533 531 return error; 534 - } 535 - 536 - static void acpi_pcc_destroy_input(struct pcc_acpi *pcc) 537 - { 538 - sparse_keymap_free(pcc->input_dev); 539 - input_unregister_device(pcc->input_dev); 540 - /* 541 - * No need to input_free_device() since core input API refcounts 542 - * and free()s the device. 543 - */ 544 532 } 545 533 546 534 /* kernel module interface */ ··· 628 640 out_backlight: 629 641 backlight_device_unregister(pcc->backlight); 630 642 out_input: 631 - acpi_pcc_destroy_input(pcc); 643 + input_unregister_device(pcc->input_dev); 632 644 out_sinf: 633 645 kfree(pcc->sinf); 634 646 out_hotkey: ··· 648 660 649 661 backlight_device_unregister(pcc->backlight); 650 662 651 - acpi_pcc_destroy_input(pcc); 663 + input_unregister_device(pcc->input_dev); 652 664 653 665 kfree(pcc->sinf); 654 666 kfree(pcc);
+65 -15
drivers/platform/x86/silead_dmi.c
··· 22 22 23 23 struct silead_ts_dmi_data { 24 24 const char *acpi_name; 25 - struct property_entry *properties; 25 + const struct property_entry *properties; 26 26 }; 27 27 28 - static struct property_entry cube_iwork8_air_props[] = { 28 + static const struct property_entry cube_iwork8_air_props[] = { 29 29 PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 30 30 PROPERTY_ENTRY_U32("touchscreen-size-y", 900), 31 31 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), ··· 39 39 .properties = cube_iwork8_air_props, 40 40 }; 41 41 42 - static struct property_entry jumper_ezpad_mini3_props[] = { 42 + static const struct property_entry jumper_ezpad_mini3_props[] = { 43 43 PROPERTY_ENTRY_U32("touchscreen-size-x", 1700), 44 44 PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 45 45 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), ··· 51 51 static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = { 52 52 .acpi_name = "MSSL1680:00", 53 53 .properties = jumper_ezpad_mini3_props, 54 + }; 55 + 56 + static const struct property_entry dexp_ursus_7w_props[] = { 57 + PROPERTY_ENTRY_U32("touchscreen-size-x", 890), 58 + PROPERTY_ENTRY_U32("touchscreen-size-y", 630), 59 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"), 60 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 61 + { } 62 + }; 63 + 64 + static const struct silead_ts_dmi_data dexp_ursus_7w_data = { 65 + .acpi_name = "MSSL1680:00", 66 + .properties = dexp_ursus_7w_props, 67 + }; 68 + 69 + static const struct property_entry surftab_wintron70_st70416_6_props[] = { 70 + PROPERTY_ENTRY_U32("touchscreen-size-x", 884), 71 + PROPERTY_ENTRY_U32("touchscreen-size-y", 632), 72 + PROPERTY_ENTRY_STRING("firmware-name", 73 + "gsl1686-surftab-wintron70-st70416-6.fw"), 74 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 75 + { } 76 + }; 77 + 78 + static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = { 79 + .acpi_name = "MSSL1680:00", 80 + .properties = surftab_wintron70_st70416_6_props, 54 81 }; 55 82 56 83 static const struct dmi_system_id silead_ts_dmi_table[] = { ··· 99 72 DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), 100 73 }, 101 74 }, 75 + { 76 + /* DEXP Ursus 7W */ 77 + .driver_data = (void *)&dexp_ursus_7w_data, 78 + .matches = { 79 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 80 + DMI_MATCH(DMI_PRODUCT_NAME, "7W"), 81 + }, 82 + }, 83 + { 84 + /* Trekstor Surftab Wintron 7.0 ST70416-6 */ 85 + .driver_data = (void *)&surftab_wintron70_st70416_6_data, 86 + .matches = { 87 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 88 + DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"), 89 + /* Exact match, different versions need different fw */ 90 + DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"), 91 + }, 92 + }, 102 93 { }, 103 94 }; 104 95 105 - static void silead_ts_dmi_add_props(struct device *dev) 96 + static const struct silead_ts_dmi_data *silead_ts_data; 97 + 98 + static void silead_ts_dmi_add_props(struct i2c_client *client) 106 99 { 107 - struct i2c_client *client = to_i2c_client(dev); 108 - const struct dmi_system_id *dmi_id; 109 - const struct silead_ts_dmi_data *ts_data; 100 + struct device *dev = &client->dev; 110 101 int error; 111 102 112 - dmi_id = dmi_first_match(silead_ts_dmi_table); 113 - if (!dmi_id) 114 - return; 115 - 116 - ts_data = dmi_id->driver_data; 117 103 if (has_acpi_companion(dev) && 118 - !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { 119 - error = device_add_properties(dev, ts_data->properties); 104 + !strncmp(silead_ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { 105 + error = device_add_properties(dev, silead_ts_data->properties); 120 106 if (error) 121 107 dev_err(dev, "failed to add properties: %d\n", error); 122 108 } ··· 139 99 unsigned long action, void *data) 140 100 { 141 101 struct device *dev = data; 102 + struct i2c_client *client; 142 103 143 104 switch (action) { 144 105 case BUS_NOTIFY_ADD_DEVICE: 145 - silead_ts_dmi_add_props(dev); 106 + client = i2c_verify_client(dev); 107 + if (client) 108 + silead_ts_dmi_add_props(client); 146 109 break; 147 110 148 111 default: ··· 161 118 162 119 static int __init silead_ts_dmi_init(void) 163 120 { 121 + const struct dmi_system_id *dmi_id; 164 122 int error; 123 + 124 + dmi_id = dmi_first_match(silead_ts_dmi_table); 125 + if (!dmi_id) 126 + return 0; /* Not an error */ 127 + 128 + silead_ts_data = dmi_id->driver_data; 165 129 166 130 error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier); 167 131 if (error)
+84 -15
drivers/platform/x86/thinkpad_acpi.c
··· 1922 1922 TP_ACPI_HOTKEYSCAN_UNK7, 1923 1923 TP_ACPI_HOTKEYSCAN_UNK8, 1924 1924 1925 - TP_ACPI_HOTKEYSCAN_MUTE2, 1925 + /* Adaptive keyboard keycodes */ 1926 + TP_ACPI_HOTKEYSCAN_ADAPTIVE_START, 1927 + TP_ACPI_HOTKEYSCAN_MUTE2 = TP_ACPI_HOTKEYSCAN_ADAPTIVE_START, 1926 1928 TP_ACPI_HOTKEYSCAN_BRIGHTNESS_ZERO, 1927 1929 TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL, 1928 1930 TP_ACPI_HOTKEYSCAN_CLOUD, ··· 1944 1942 TP_ACPI_HOTKEYSCAN_MIC_CANCELLATION, 1945 1943 TP_ACPI_HOTKEYSCAN_CAMERA_MODE, 1946 1944 TP_ACPI_HOTKEYSCAN_ROTATE_DISPLAY, 1945 + 1946 + /* Lenovo extended keymap, starting at 0x1300 */ 1947 + TP_ACPI_HOTKEYSCAN_EXTENDED_START, 1948 + /* first new observed key (star, favorites) is 0x1311 */ 1949 + TP_ACPI_HOTKEYSCAN_STAR = 69, 1950 + TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL2, 1951 + TP_ACPI_HOTKEYSCAN_UNK25, 1952 + TP_ACPI_HOTKEYSCAN_BLUETOOTH, 1953 + TP_ACPI_HOTKEYSCAN_KEYBOARD, 1947 1954 1948 1955 /* Hotkey keymap size */ 1949 1956 TPACPI_HOTKEY_MAP_LEN ··· 3261 3250 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3262 3251 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3263 3252 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3253 + 3254 + /* No assignment, used for newer Lenovo models */ 3255 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3256 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3257 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3258 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3259 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3260 + KEY_UNKNOWN, KEY_UNKNOWN 3261 + 3264 3262 }, 3265 3263 3266 3264 /* Generic keymap for Lenovo ThinkPads */ ··· 3355 3335 KEY_RESERVED, /* Microphone cancellation */ 3356 3336 KEY_RESERVED, /* Camera mode */ 3357 3337 KEY_RESERVED, /* Rotate display, 0x116 */ 3338 + 3339 + /* 3340 + * These are found in 2017 models (e.g. T470s, X270). 3341 + * The lowest known value is 0x311, which according to 3342 + * the manual should launch a user defined favorite 3343 + * application. 3344 + * 3345 + * The offset for these is TP_ACPI_HOTKEYSCAN_EXTENDED_START, 3346 + * corresponding to 0x34. 3347 + */ 3348 + 3349 + /* (assignments unknown, please report if found) */ 3350 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3351 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3352 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3353 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3354 + KEY_UNKNOWN, 3355 + 3356 + KEY_FAVORITES, /* Favorite app, 0x311 */ 3357 + KEY_RESERVED, /* Clipping tool */ 3358 + KEY_RESERVED, 3359 + KEY_BLUETOOTH, /* Bluetooth */ 3360 + KEY_KEYBOARD /* Keyboard, 0x315 */ 3358 3361 }, 3359 3362 }; 3360 3363 ··· 3699 3656 #define DFR_CHANGE_ROW 0x101 3700 3657 #define DFR_SHOW_QUICKVIEW_ROW 0x102 3701 3658 #define FIRST_ADAPTIVE_KEY 0x103 3702 - #define ADAPTIVE_KEY_OFFSET 0x020 3703 3659 3704 3660 /* press Fn key a while second, it will switch to Function Mode. Then 3705 3661 * release Fn key, previous mode be restored. ··· 3788 3746 3789 3747 default: 3790 3748 if (scancode < FIRST_ADAPTIVE_KEY || 3791 - scancode >= FIRST_ADAPTIVE_KEY + TPACPI_HOTKEY_MAP_LEN - 3792 - ADAPTIVE_KEY_OFFSET) { 3749 + scancode >= FIRST_ADAPTIVE_KEY + 3750 + TP_ACPI_HOTKEYSCAN_EXTENDED_START - 3751 + TP_ACPI_HOTKEYSCAN_ADAPTIVE_START) { 3793 3752 pr_info("Unhandled adaptive keyboard key: 0x%x\n", 3794 3753 scancode); 3795 3754 return false; 3796 3755 } 3797 - keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY + ADAPTIVE_KEY_OFFSET]; 3756 + keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY + 3757 + TP_ACPI_HOTKEYSCAN_ADAPTIVE_START]; 3798 3758 if (keycode != KEY_RESERVED) { 3799 3759 mutex_lock(&tpacpi_inputdev_send_mutex); 3800 3760 ··· 3821 3777 *send_acpi_ev = true; 3822 3778 *ignore_acpi_ev = false; 3823 3779 3824 - /* HKEY event 0x1001 is scancode 0x00 */ 3825 - if (scancode > 0 && scancode <= TPACPI_HOTKEY_MAP_LEN) { 3826 - scancode--; 3827 - if (!(hotkey_source_mask & (1 << scancode))) { 3828 - tpacpi_input_send_key_masked(scancode); 3829 - *send_acpi_ev = false; 3830 - } else { 3831 - *ignore_acpi_ev = true; 3780 + /* 3781 + * Original events are in the 0x10XX range, the adaptive keyboard 3782 + * found in 2014 X1 Carbon emits events are of 0x11XX. In 2017 3783 + * models, additional keys are emitted through 0x13XX. 3784 + */ 3785 + switch ((hkey >> 8) & 0xf) { 3786 + case 0: 3787 + if (scancode > 0 && 3788 + scancode <= TP_ACPI_HOTKEYSCAN_ADAPTIVE_START) { 3789 + /* HKEY event 0x1001 is scancode 0x00 */ 3790 + scancode--; 3791 + if (!(hotkey_source_mask & (1 << scancode))) { 3792 + tpacpi_input_send_key_masked(scancode); 3793 + *send_acpi_ev = false; 3794 + } else { 3795 + *ignore_acpi_ev = true; 3796 + } 3797 + return true; 3832 3798 } 3833 - return true; 3834 - } else { 3799 + break; 3800 + 3801 + case 1: 3835 3802 return adaptive_keyboard_hotkey_notify_hotkey(scancode); 3803 + 3804 + case 3: 3805 + /* Extended keycodes start at 0x300 and our offset into the map 3806 + * TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode 3807 + * will be positive, but might not be in the correct range. 3808 + */ 3809 + scancode -= (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START); 3810 + if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START && 3811 + scancode < TPACPI_HOTKEY_MAP_LEN) { 3812 + tpacpi_input_send_key(scancode); 3813 + return true; 3814 + } 3815 + break; 3836 3816 } 3817 + 3837 3818 return false; 3838 3819 } 3839 3820
+1 -4
drivers/platform/x86/topstar-laptop.c
··· 113 113 error = input_register_device(input); 114 114 if (error) { 115 115 pr_err("Unable to register input device\n"); 116 - goto err_free_keymap; 116 + goto err_free_dev; 117 117 } 118 118 119 119 hkey->inputdev = input; 120 120 return 0; 121 121 122 - err_free_keymap: 123 - sparse_keymap_free(input); 124 122 err_free_dev: 125 123 input_free_device(input); 126 124 return error; ··· 155 157 156 158 acpi_topstar_fncx_switch(device, false); 157 159 158 - sparse_keymap_free(tps_hkey->inputdev); 159 160 input_unregister_device(tps_hkey->inputdev); 160 161 kfree(tps_hkey); 161 162
+1 -4
drivers/platform/x86/toshiba-wmi.c
··· 96 96 toshiba_wmi_notify, NULL); 97 97 if (ACPI_FAILURE(status)) { 98 98 err = -EIO; 99 - goto err_free_keymap; 99 + goto err_free_dev; 100 100 } 101 101 102 102 err = input_register_device(toshiba_wmi_input_dev); ··· 107 107 108 108 err_remove_notifier: 109 109 wmi_remove_notify_handler(WMI_EVENT_GUID); 110 - err_free_keymap: 111 - sparse_keymap_free(toshiba_wmi_input_dev); 112 110 err_free_dev: 113 111 input_free_device(toshiba_wmi_input_dev); 114 112 return err; ··· 115 117 static void toshiba_wmi_input_destroy(void) 116 118 { 117 119 wmi_remove_notify_handler(WMI_EVENT_GUID); 118 - sparse_keymap_free(toshiba_wmi_input_dev); 119 120 input_unregister_device(toshiba_wmi_input_dev); 120 121 } 121 122
+2 -6
drivers/platform/x86/toshiba_acpi.c
··· 2849 2849 error = i8042_install_filter(toshiba_acpi_i8042_filter); 2850 2850 if (error) { 2851 2851 pr_err("Error installing key filter\n"); 2852 - goto err_free_keymap; 2852 + goto err_free_dev; 2853 2853 } 2854 2854 2855 2855 dev->ntfy_supported = 1; ··· 2880 2880 err_remove_filter: 2881 2881 if (dev->ntfy_supported) 2882 2882 i8042_remove_filter(toshiba_acpi_i8042_filter); 2883 - err_free_keymap: 2884 - sparse_keymap_free(dev->hotkey_dev); 2885 2883 err_free_dev: 2886 2884 input_free_device(dev->hotkey_dev); 2887 2885 dev->hotkey_dev = NULL; ··· 3016 3018 cancel_work_sync(&dev->hotkey_work); 3017 3019 } 3018 3020 3019 - if (dev->hotkey_dev) { 3021 + if (dev->hotkey_dev) 3020 3022 input_unregister_device(dev->hotkey_dev); 3021 - sparse_keymap_free(dev->hotkey_dev); 3022 - } 3023 3023 3024 3024 backlight_device_unregister(dev->backlight_dev); 3025 3025
+64 -36
drivers/watchdog/iTCO_wdt.c
··· 106 106 struct pci_dev *pci_dev; 107 107 /* whether or not the watchdog has been suspended */ 108 108 bool suspended; 109 + /* no reboot API private data */ 110 + void *no_reboot_priv; 111 + /* no reboot update function pointer */ 112 + int (*update_no_reboot_bit)(void *p, bool set); 109 113 }; 110 114 111 115 /* module parameters */ ··· 174 170 return enable_bit; 175 171 } 176 172 177 - static void iTCO_wdt_set_NO_REBOOT_bit(struct iTCO_wdt_private *p) 173 + static int update_no_reboot_bit_def(void *priv, bool set) 178 174 { 179 - u32 val32; 180 - 181 - /* Set the NO_REBOOT bit: this disables reboots */ 182 - if (p->iTCO_version >= 2) { 183 - val32 = readl(p->gcs_pmc); 184 - val32 |= no_reboot_bit(p); 185 - writel(val32, p->gcs_pmc); 186 - } else if (p->iTCO_version == 1) { 187 - pci_read_config_dword(p->pci_dev, 0xd4, &val32); 188 - val32 |= no_reboot_bit(p); 189 - pci_write_config_dword(p->pci_dev, 0xd4, val32); 190 - } 175 + return 0; 191 176 } 192 177 193 - static int iTCO_wdt_unset_NO_REBOOT_bit(struct iTCO_wdt_private *p) 178 + static int update_no_reboot_bit_pci(void *priv, bool set) 194 179 { 195 - u32 enable_bit = no_reboot_bit(p); 196 - u32 val32 = 0; 180 + struct iTCO_wdt_private *p = priv; 181 + u32 val32 = 0, newval32 = 0; 197 182 198 - /* Unset the NO_REBOOT bit: this enables reboots */ 199 - if (p->iTCO_version >= 2) { 200 - val32 = readl(p->gcs_pmc); 201 - val32 &= ~enable_bit; 202 - writel(val32, p->gcs_pmc); 183 + pci_read_config_dword(p->pci_dev, 0xd4, &val32); 184 + if (set) 185 + val32 |= no_reboot_bit(p); 186 + else 187 + val32 &= ~no_reboot_bit(p); 188 + pci_write_config_dword(p->pci_dev, 0xd4, val32); 189 + pci_read_config_dword(p->pci_dev, 0xd4, &newval32); 203 190 204 - val32 = readl(p->gcs_pmc); 205 - } else if (p->iTCO_version == 1) { 206 - pci_read_config_dword(p->pci_dev, 0xd4, &val32); 207 - val32 &= ~enable_bit; 208 - pci_write_config_dword(p->pci_dev, 0xd4, val32); 209 - 210 - pci_read_config_dword(p->pci_dev, 0xd4, &val32); 211 - } 212 - 213 - if (val32 & enable_bit) 191 + /* make sure the update is successful */ 192 + if (val32 != newval32) 214 193 return -EIO; 215 194 216 195 return 0; 196 + } 197 + 198 + static int update_no_reboot_bit_mem(void *priv, bool set) 199 + { 200 + struct iTCO_wdt_private *p = priv; 201 + u32 val32 = 0, newval32 = 0; 202 + 203 + val32 = readl(p->gcs_pmc); 204 + if (set) 205 + val32 |= no_reboot_bit(p); 206 + else 207 + val32 &= ~no_reboot_bit(p); 208 + writel(val32, p->gcs_pmc); 209 + newval32 = readl(p->gcs_pmc); 210 + 211 + /* make sure the update is successful */ 212 + if (val32 != newval32) 213 + return -EIO; 214 + 215 + return 0; 216 + } 217 + 218 + static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p, 219 + struct itco_wdt_platform_data *pdata) 220 + { 221 + if (pdata->update_no_reboot_bit) { 222 + p->update_no_reboot_bit = pdata->update_no_reboot_bit; 223 + p->no_reboot_priv = pdata->no_reboot_priv; 224 + return; 225 + } 226 + 227 + if (p->iTCO_version >= 2) 228 + p->update_no_reboot_bit = update_no_reboot_bit_mem; 229 + else if (p->iTCO_version == 1) 230 + p->update_no_reboot_bit = update_no_reboot_bit_pci; 231 + else 232 + p->update_no_reboot_bit = update_no_reboot_bit_def; 233 + 234 + p->no_reboot_priv = p; 217 235 } 218 236 219 237 static int iTCO_wdt_start(struct watchdog_device *wd_dev) ··· 248 222 iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); 249 223 250 224 /* disable chipset's NO_REBOOT bit */ 251 - if (iTCO_wdt_unset_NO_REBOOT_bit(p)) { 225 + if (p->update_no_reboot_bit(p->no_reboot_priv, false)) { 252 226 spin_unlock(&p->io_lock); 253 227 pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); 254 228 return -EIO; ··· 289 263 val = inw(TCO1_CNT(p)); 290 264 291 265 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 292 - iTCO_wdt_set_NO_REBOOT_bit(p); 266 + p->update_no_reboot_bit(p->no_reboot_priv, true); 293 267 294 268 spin_unlock(&p->io_lock); 295 269 ··· 454 428 p->iTCO_version = pdata->version; 455 429 p->pci_dev = to_pci_dev(dev->parent); 456 430 431 + iTCO_wdt_no_reboot_bit_setup(p, pdata); 432 + 457 433 /* 458 434 * Get the Memory-Mapped GCS or PMC register, we need it for the 459 435 * NO_REBOOT flag (TCO v2 and v3). 460 436 */ 461 - if (p->iTCO_version >= 2) { 437 + if (p->iTCO_version >= 2 && !pdata->update_no_reboot_bit) { 462 438 p->gcs_pmc_res = platform_get_resource(pdev, 463 439 IORESOURCE_MEM, 464 440 ICH_RES_MEM_GCS_PMC); ··· 470 442 } 471 443 472 444 /* Check chipset's NO_REBOOT bit */ 473 - if (iTCO_wdt_unset_NO_REBOOT_bit(p) && 445 + if (p->update_no_reboot_bit(p->no_reboot_priv, false) && 474 446 iTCO_vendor_check_noreboot_on()) { 475 447 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); 476 448 return -ENODEV; /* Cannot reset NO_REBOOT bit */ 477 449 } 478 450 479 451 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 480 - iTCO_wdt_set_NO_REBOOT_bit(p); 452 + p->update_no_reboot_bit(p->no_reboot_priv, true); 481 453 482 454 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 483 455 if (!devm_request_region(dev, p->smi_res->start,
+4
include/linux/platform_data/itco_wdt.h
··· 14 14 struct itco_wdt_platform_data { 15 15 char name[32]; 16 16 unsigned int version; 17 + /* private data to be passed to update_no_reboot_bit API */ 18 + void *no_reboot_priv; 19 + /* pointer for platform specific no reboot update function */ 20 + int (*update_no_reboot_bit)(void *priv, bool set); 17 21 }; 18 22 19 23 #endif /* _ITCO_WDT_H_ */