mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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 ...
This commit is contained in:
@@ -23,6 +23,11 @@
|
||||
#define IPC_ERR_EMSECURITY 6
|
||||
#define IPC_ERR_UNSIGNEDKERNEL 7
|
||||
|
||||
/* GCR reg offsets from gcr base*/
|
||||
#define PMC_GCR_PMC_CFG_REG 0x08
|
||||
#define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78
|
||||
#define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80
|
||||
|
||||
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
|
||||
|
||||
int intel_pmc_ipc_simple_command(int cmd, int sub);
|
||||
@@ -31,6 +36,9 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
u32 *out, u32 outlen);
|
||||
int intel_pmc_s0ix_counter_read(u64 *data);
|
||||
int intel_pmc_gcr_read(u32 offset, u32 *data);
|
||||
int intel_pmc_gcr_write(u32 offset, u32 data);
|
||||
int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val);
|
||||
|
||||
#else
|
||||
|
||||
@@ -56,6 +64,21 @@ static inline int intel_pmc_s0ix_counter_read(u64 *data)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_read(u32 offset, u32 *data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_write(u32 offset, u32 data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif /*CONFIG_INTEL_PMC_IPC*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#define IPCMSG_INDIRECT_READ 0x02
|
||||
#define IPCMSG_INDIRECT_WRITE 0x05
|
||||
|
||||
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
|
||||
|
||||
#define IPCMSG_WARM_RESET 0xF0
|
||||
@@ -45,7 +48,10 @@ int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
|
||||
/* Issue commands to the SCU with or without data */
|
||||
int intel_scu_ipc_simple_command(int cmd, int sub);
|
||||
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
|
||||
u32 *out, int outlen);
|
||||
u32 *out, int outlen);
|
||||
int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
|
||||
u32 *out, int outlen, u32 dptr, u32 sptr);
|
||||
|
||||
/* I2C control api */
|
||||
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
|
||||
|
||||
|
||||
@@ -182,7 +182,8 @@ config FUJITSU_LAPTOP
|
||||
depends on INPUT
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on ACPI_VIDEO || ACPI_VIDEO = n
|
||||
depends on LEDS_CLASS || LEDS_CLASS=n
|
||||
select INPUT_SPARSEKMAP
|
||||
select LEDS_CLASS
|
||||
---help---
|
||||
This is a driver for laptops built by Fujitsu:
|
||||
|
||||
@@ -780,6 +781,19 @@ config ACPI_CMPC
|
||||
keys as input device, backlight device, tablet and accelerometer
|
||||
devices.
|
||||
|
||||
config INTEL_CHT_INT33FE
|
||||
tristate "Intel Cherry Trail ACPI INT33FE Driver"
|
||||
depends on X86 && ACPI && I2C
|
||||
---help---
|
||||
This driver add support for the INT33FE ACPI device found on
|
||||
some Intel Cherry Trail devices.
|
||||
|
||||
The INT33FE ACPI device has a CRS table with I2cSerialBusV2
|
||||
resources for 3 devices: Maxim MAX17047 Fuel Gauge Controller,
|
||||
FUSB302 USB Type-C Controller and PI3USB30532 USB switch.
|
||||
This driver instantiates i2c-clients for these, so that standard
|
||||
i2c drivers for these chips can bind to the them.
|
||||
|
||||
config INTEL_HID_EVENT
|
||||
tristate "INTEL HID Event"
|
||||
depends on ACPI
|
||||
@@ -1087,7 +1101,7 @@ config INTEL_TURBO_MAX_3
|
||||
|
||||
config SILEAD_DMI
|
||||
bool "Tablets with Silead touchscreens"
|
||||
depends on ACPI && DMI && I2C=y && INPUT
|
||||
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
|
||||
---help---
|
||||
Certain ACPI based tablets with Silead touchscreens do not have
|
||||
enough data in ACPI tables for the touchscreen driver to handle
|
||||
|
||||
@@ -45,6 +45,7 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
|
||||
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
|
||||
obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
|
||||
obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
|
||||
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
|
||||
obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
|
||||
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
|
||||
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
|
||||
|
||||
@@ -1896,7 +1896,7 @@ static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
|
||||
if (!strcmp(ctx, "SENR")) {
|
||||
if (acpi_bus_get_device(ah, &dev))
|
||||
return AE_OK;
|
||||
if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
|
||||
if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
|
||||
return AE_OK;
|
||||
} else
|
||||
return AE_OK;
|
||||
@@ -1917,8 +1917,7 @@ static int __init acer_wmi_get_handle(const char *name, const char *prop,
|
||||
handle = NULL;
|
||||
status = acpi_get_devices(prop, acer_wmi_get_handle_cb,
|
||||
(void *)name, &handle);
|
||||
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (ACPI_SUCCESS(status) && handle) {
|
||||
*ah = handle;
|
||||
return 0;
|
||||
} else {
|
||||
@@ -1987,7 +1986,7 @@ static int __init acer_wmi_input_setup(void)
|
||||
acer_wmi_notify, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
err = -EIO;
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
err = input_register_device(acer_wmi_input_dev);
|
||||
@@ -1998,8 +1997,6 @@ static int __init acer_wmi_input_setup(void)
|
||||
|
||||
err_uninstall_notifier:
|
||||
wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(acer_wmi_input_dev);
|
||||
err_free_dev:
|
||||
input_free_device(acer_wmi_input_dev);
|
||||
return err;
|
||||
@@ -2008,7 +2005,6 @@ err_free_dev:
|
||||
static void acer_wmi_input_destroy(void)
|
||||
{
|
||||
wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
|
||||
sparse_keymap_free(acer_wmi_input_dev);
|
||||
input_unregister_device(acer_wmi_input_dev);
|
||||
}
|
||||
|
||||
@@ -2290,8 +2286,8 @@ static int __init acer_wmi_init(void)
|
||||
if (err)
|
||||
return err;
|
||||
err = acer_wmi_accel_setup();
|
||||
if (err)
|
||||
return err;
|
||||
if (err && err != -ENODEV)
|
||||
pr_warn("Cannot enable accelerometer\n");
|
||||
}
|
||||
|
||||
err = platform_driver_register(&acer_platform_driver);
|
||||
|
||||
@@ -1516,14 +1516,12 @@ static int asus_input_init(struct asus_laptop *asus)
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
pr_warn("Unable to register input device\n");
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
asus->inputdev = input;
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(input);
|
||||
err_free_dev:
|
||||
input_free_device(input);
|
||||
return error;
|
||||
@@ -1531,10 +1529,8 @@ err_free_dev:
|
||||
|
||||
static void asus_input_exit(struct asus_laptop *asus)
|
||||
{
|
||||
if (asus->inputdev) {
|
||||
sparse_keymap_free(asus->inputdev);
|
||||
if (asus->inputdev)
|
||||
input_unregister_device(asus->inputdev);
|
||||
}
|
||||
asus->inputdev = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,10 @@ static struct quirk_entry quirk_asus_x550lb = {
|
||||
.xusb2pr = 0x01D9,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_asus_ux330uak = {
|
||||
.wmi_force_als_set = true,
|
||||
};
|
||||
|
||||
static int dmi_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
pr_info("Identified laptop model '%s'\n", dmi->ident);
|
||||
@@ -142,6 +146,15 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
*/
|
||||
.driver_data = &quirk_asus_wapf4,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. X302UA",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"),
|
||||
},
|
||||
.driver_data = &quirk_asus_wapf4,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. X401U",
|
||||
@@ -367,6 +380,15 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
},
|
||||
.driver_data = &quirk_asus_ux303ub,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. UX330UAK",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"),
|
||||
},
|
||||
.driver_data = &quirk_asus_ux330uak,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. X550LB",
|
||||
|
||||
@@ -269,12 +269,10 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
|
||||
|
||||
err = input_register_device(asus->inputdev);
|
||||
if (err)
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(asus->inputdev);
|
||||
err_free_dev:
|
||||
input_free_device(asus->inputdev);
|
||||
return err;
|
||||
@@ -282,10 +280,8 @@ err_free_dev:
|
||||
|
||||
static void asus_wmi_input_exit(struct asus_wmi *asus)
|
||||
{
|
||||
if (asus->inputdev) {
|
||||
sparse_keymap_free(asus->inputdev);
|
||||
if (asus->inputdev)
|
||||
input_unregister_device(asus->inputdev);
|
||||
}
|
||||
|
||||
asus->inputdev = NULL;
|
||||
}
|
||||
@@ -1108,6 +1104,15 @@ static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
|
||||
orig_ports_available, ports_available);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some devices dont support or have borcken get_als method
|
||||
* but still support set method.
|
||||
*/
|
||||
static void asus_wmi_set_als(void)
|
||||
{
|
||||
asus_wmi_set_devstate(ASUS_WMI_DEVID_ALS_ENABLE, 1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hwmon device
|
||||
*/
|
||||
@@ -1761,7 +1766,7 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
|
||||
ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME);
|
||||
ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE);
|
||||
|
||||
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int value, rv;
|
||||
@@ -1778,7 +1783,7 @@ static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
|
||||
static DEVICE_ATTR_WO(cpufv);
|
||||
|
||||
static struct attribute *platform_attributes[] = {
|
||||
&dev_attr_cpufv.attr,
|
||||
@@ -2117,6 +2122,9 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
goto fail_rfkill;
|
||||
}
|
||||
|
||||
if (asus->driver->quirks->wmi_force_als_set)
|
||||
asus_wmi_set_als();
|
||||
|
||||
/* Some Asus desktop boards export an acpi-video backlight interface,
|
||||
stop this from showing up */
|
||||
chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
|
||||
|
||||
@@ -44,6 +44,7 @@ struct quirk_entry {
|
||||
bool store_backlight_power;
|
||||
bool wmi_backlight_power;
|
||||
bool wmi_backlight_native;
|
||||
bool wmi_force_als_set;
|
||||
int wapf;
|
||||
/*
|
||||
* For machines with AMD graphic chips, it will send out WMI event
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define KBD_LED_AUTO_100_TOKEN 0x02F6
|
||||
#define GLOBAL_MIC_MUTE_ENABLE 0x0364
|
||||
#define GLOBAL_MIC_MUTE_DISABLE 0x0365
|
||||
#define KBD_LED_AC_TOKEN 0x0451
|
||||
|
||||
struct quirk_entry {
|
||||
u8 touchpad_led;
|
||||
@@ -1027,7 +1028,7 @@ static void touchpad_led_exit(void)
|
||||
* bit 2 Pointing stick
|
||||
* bit 3 Any mouse
|
||||
* bits 4-7 Reserved for future use
|
||||
* cbRES2, byte3 Current Timeout
|
||||
* cbRES2, byte3 Current Timeout on battery
|
||||
* bits 7:6 Timeout units indicator:
|
||||
* 00b Seconds
|
||||
* 01b Minutes
|
||||
@@ -1039,6 +1040,15 @@ static void touchpad_led_exit(void)
|
||||
* cbRES3, byte0 Current setting of ALS value that turns the light on or off.
|
||||
* cbRES3, byte1 Current ALS reading
|
||||
* cbRES3, byte2 Current keyboard light level.
|
||||
* cbRES3, byte3 Current timeout on AC Power
|
||||
* bits 7:6 Timeout units indicator:
|
||||
* 00b Seconds
|
||||
* 01b Minutes
|
||||
* 10b Hours
|
||||
* 11b Days
|
||||
* Bits 5:0 Timeout value (0-63) in sec/min/hr/day
|
||||
* NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte2
|
||||
* are set upon return from the upon return from the [Get Feature information] call.
|
||||
*
|
||||
* cbArg1 0x2 = Set New State
|
||||
* cbRES1 Standard return codes (0, -1, -2)
|
||||
@@ -1061,7 +1071,7 @@ static void touchpad_led_exit(void)
|
||||
* bit 2 Pointing stick
|
||||
* bit 3 Any mouse
|
||||
* bits 4-7 Reserved for future use
|
||||
* cbArg2, byte3 Desired Timeout
|
||||
* cbArg2, byte3 Desired Timeout on battery
|
||||
* bits 7:6 Timeout units indicator:
|
||||
* 00b Seconds
|
||||
* 01b Minutes
|
||||
@@ -1070,6 +1080,13 @@ static void touchpad_led_exit(void)
|
||||
* bits 5:0 Timeout value (0-63) in sec/min/hr/day
|
||||
* cbArg3, byte0 Desired setting of ALS value that turns the light on or off.
|
||||
* cbArg3, byte2 Desired keyboard light level.
|
||||
* cbArg3, byte3 Desired Timeout on AC power
|
||||
* bits 7:6 Timeout units indicator:
|
||||
* 00b Seconds
|
||||
* 01b Minutes
|
||||
* 10b Hours
|
||||
* 11b Days
|
||||
* bits 5:0 Timeout value (0-63) in sec/min/hr/day
|
||||
*/
|
||||
|
||||
|
||||
@@ -1115,6 +1132,8 @@ struct kbd_state {
|
||||
u8 triggers;
|
||||
u8 timeout_value;
|
||||
u8 timeout_unit;
|
||||
u8 timeout_value_ac;
|
||||
u8 timeout_unit_ac;
|
||||
u8 als_setting;
|
||||
u8 als_value;
|
||||
u8 level;
|
||||
@@ -1134,6 +1153,7 @@ static u16 kbd_token_bits;
|
||||
static struct kbd_info kbd_info;
|
||||
static bool kbd_als_supported;
|
||||
static bool kbd_triggers_supported;
|
||||
static bool kbd_timeout_ac_supported;
|
||||
|
||||
static u8 kbd_mode_levels[16];
|
||||
static int kbd_mode_levels_count;
|
||||
@@ -1142,6 +1162,7 @@ static u8 kbd_previous_level;
|
||||
static u8 kbd_previous_mode_bit;
|
||||
|
||||
static bool kbd_led_present;
|
||||
static DEFINE_MUTEX(kbd_led_mutex);
|
||||
|
||||
/*
|
||||
* NOTE: there are three ways to set the keyboard backlight level.
|
||||
@@ -1272,6 +1293,8 @@ static int kbd_get_state(struct kbd_state *state)
|
||||
state->als_setting = buffer->output[2] & 0xFF;
|
||||
state->als_value = (buffer->output[2] >> 8) & 0xFF;
|
||||
state->level = (buffer->output[2] >> 16) & 0xFF;
|
||||
state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F;
|
||||
state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3;
|
||||
|
||||
out:
|
||||
dell_smbios_release_buffer();
|
||||
@@ -1291,6 +1314,8 @@ static int kbd_set_state(struct kbd_state *state)
|
||||
buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
|
||||
buffer->input[2] = state->als_setting & 0xFF;
|
||||
buffer->input[2] |= (state->level & 0xFF) << 16;
|
||||
buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24;
|
||||
buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30;
|
||||
dell_smbios_send_request(4, 11);
|
||||
ret = buffer->output[0];
|
||||
dell_smbios_release_buffer();
|
||||
@@ -1397,6 +1422,13 @@ static inline int kbd_init_info(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* NOTE: Old models without KBD_LED_AC_TOKEN token supports only one
|
||||
* timeout value which is shared for both battery and AC power
|
||||
* settings. So do not try to set AC values on old models.
|
||||
*/
|
||||
if (dell_smbios_find_token(KBD_LED_AC_TOKEN))
|
||||
kbd_timeout_ac_supported = true;
|
||||
|
||||
kbd_get_state(&state);
|
||||
|
||||
/* NOTE: timeout value is stored in 6 bits so max value is 63 */
|
||||
@@ -1571,35 +1603,56 @@ static ssize_t kbd_led_timeout_store(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&kbd_led_mutex);
|
||||
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
new_state = state;
|
||||
new_state.timeout_value = value;
|
||||
new_state.timeout_unit = unit;
|
||||
|
||||
if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
|
||||
new_state.timeout_value_ac = value;
|
||||
new_state.timeout_unit_ac = unit;
|
||||
} else {
|
||||
new_state.timeout_value = value;
|
||||
new_state.timeout_unit = unit;
|
||||
}
|
||||
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
return count;
|
||||
ret = count;
|
||||
out:
|
||||
mutex_unlock(&kbd_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t kbd_led_timeout_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct kbd_state state;
|
||||
int value;
|
||||
int ret;
|
||||
int len;
|
||||
u8 unit;
|
||||
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = sprintf(buf, "%d", state.timeout_value);
|
||||
if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
|
||||
value = state.timeout_value_ac;
|
||||
unit = state.timeout_unit_ac;
|
||||
} else {
|
||||
value = state.timeout_value;
|
||||
unit = state.timeout_unit;
|
||||
}
|
||||
|
||||
switch (state.timeout_unit) {
|
||||
len = sprintf(buf, "%d", value);
|
||||
|
||||
switch (unit) {
|
||||
case KBD_TIMEOUT_SECONDS:
|
||||
return len + sprintf(buf+len, "s\n");
|
||||
case KBD_TIMEOUT_MINUTES:
|
||||
@@ -1643,9 +1696,11 @@ static ssize_t kbd_led_triggers_store(struct device *dev,
|
||||
if (trigger[0] != '+' && trigger[0] != '-')
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kbd_led_mutex);
|
||||
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (kbd_triggers_supported)
|
||||
triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
|
||||
@@ -1659,48 +1714,62 @@ static ssize_t kbd_led_triggers_store(struct device *dev,
|
||||
if (strcmp(trigger+1, kbd_led_triggers[i]) != 0)
|
||||
continue;
|
||||
if (trigger[0] == '+' &&
|
||||
triggers_enabled && (state.triggers & BIT(i)))
|
||||
return count;
|
||||
triggers_enabled && (state.triggers & BIT(i))) {
|
||||
ret = count;
|
||||
goto out;
|
||||
}
|
||||
if (trigger[0] == '-' &&
|
||||
(!triggers_enabled || !(state.triggers & BIT(i))))
|
||||
return count;
|
||||
(!triggers_enabled || !(state.triggers & BIT(i)))) {
|
||||
ret = count;
|
||||
goto out;
|
||||
}
|
||||
trigger_bit = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger_bit != -1) {
|
||||
new_state = state;
|
||||
if (trigger[0] == '+')
|
||||
new_state.triggers |= BIT(trigger_bit);
|
||||
else {
|
||||
new_state.triggers &= ~BIT(trigger_bit);
|
||||
/* NOTE: trackstick bit (2) must be disabled when
|
||||
* disabling touchpad bit (1), otherwise touchpad
|
||||
* bit (1) will not be disabled */
|
||||
if (trigger_bit == 1)
|
||||
new_state.triggers &= ~BIT(2);
|
||||
}
|
||||
if ((kbd_info.triggers & new_state.triggers) !=
|
||||
new_state.triggers)
|
||||
return -EINVAL;
|
||||
if (new_state.triggers && !triggers_enabled) {
|
||||
new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
|
||||
kbd_set_level(&new_state, kbd_previous_level);
|
||||
} else if (new_state.triggers == 0) {
|
||||
kbd_set_level(&new_state, 0);
|
||||
}
|
||||
if (!(kbd_info.modes & BIT(new_state.mode_bit)))
|
||||
return -EINVAL;
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_state.mode_bit != KBD_MODE_BIT_OFF)
|
||||
kbd_previous_mode_bit = new_state.mode_bit;
|
||||
return count;
|
||||
if (trigger_bit == -1) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
new_state = state;
|
||||
if (trigger[0] == '+')
|
||||
new_state.triggers |= BIT(trigger_bit);
|
||||
else {
|
||||
new_state.triggers &= ~BIT(trigger_bit);
|
||||
/*
|
||||
* NOTE: trackstick bit (2) must be disabled when
|
||||
* disabling touchpad bit (1), otherwise touchpad
|
||||
* bit (1) will not be disabled
|
||||
*/
|
||||
if (trigger_bit == 1)
|
||||
new_state.triggers &= ~BIT(2);
|
||||
}
|
||||
if ((kbd_info.triggers & new_state.triggers) !=
|
||||
new_state.triggers) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (new_state.triggers && !triggers_enabled) {
|
||||
new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
|
||||
kbd_set_level(&new_state, kbd_previous_level);
|
||||
} else if (new_state.triggers == 0) {
|
||||
kbd_set_level(&new_state, 0);
|
||||
}
|
||||
if (!(kbd_info.modes & BIT(new_state.mode_bit))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (new_state.mode_bit != KBD_MODE_BIT_OFF)
|
||||
kbd_previous_mode_bit = new_state.mode_bit;
|
||||
ret = count;
|
||||
out:
|
||||
mutex_unlock(&kbd_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t kbd_led_triggers_show(struct device *dev,
|
||||
@@ -1757,12 +1826,16 @@ static ssize_t kbd_led_als_enabled_store(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&kbd_led_mutex);
|
||||
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (enable == kbd_is_als_mode_bit(state.mode_bit))
|
||||
return count;
|
||||
if (enable == kbd_is_als_mode_bit(state.mode_bit)) {
|
||||
ret = count;
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_state = state;
|
||||
|
||||
@@ -1782,15 +1855,20 @@ static ssize_t kbd_led_als_enabled_store(struct device *dev,
|
||||
new_state.mode_bit = KBD_MODE_BIT_ON;
|
||||
}
|
||||
}
|
||||
if (!(kbd_info.modes & BIT(new_state.mode_bit)))
|
||||
return -EINVAL;
|
||||
if (!(kbd_info.modes & BIT(new_state.mode_bit))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
kbd_previous_mode_bit = new_state.mode_bit;
|
||||
|
||||
return count;
|
||||
ret = count;
|
||||
out:
|
||||
mutex_unlock(&kbd_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t kbd_led_als_enabled_show(struct device *dev,
|
||||
@@ -1825,18 +1903,23 @@ static ssize_t kbd_led_als_setting_store(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&kbd_led_mutex);
|
||||
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
new_state = state;
|
||||
new_state.als_setting = setting;
|
||||
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
return count;
|
||||
ret = count;
|
||||
out:
|
||||
mutex_unlock(&kbd_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t kbd_led_als_setting_show(struct device *dev,
|
||||
@@ -1921,31 +2004,37 @@ static int kbd_led_level_set(struct led_classdev *led_cdev,
|
||||
u16 num;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&kbd_led_mutex);
|
||||
|
||||
if (kbd_get_max_level()) {
|
||||
ret = kbd_get_state(&state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
new_state = state;
|
||||
ret = kbd_set_level(&new_state, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
return kbd_set_state_safe(&new_state, &state);
|
||||
}
|
||||
|
||||
if (kbd_get_valid_token_counts()) {
|
||||
goto out;
|
||||
ret = kbd_set_state_safe(&new_state, &state);
|
||||
} else if (kbd_get_valid_token_counts()) {
|
||||
for (num = kbd_token_bits; num != 0 && value > 0; --value)
|
||||
num &= num - 1; /* clear the first bit set */
|
||||
if (num == 0)
|
||||
return 0;
|
||||
return kbd_set_token_bit(ffs(num) - 1);
|
||||
ret = 0;
|
||||
else
|
||||
ret = kbd_set_token_bit(ffs(num) - 1);
|
||||
} else {
|
||||
pr_warn("Keyboard brightness level control not supported\n");
|
||||
ret = -ENXIO;
|
||||
}
|
||||
|
||||
pr_warn("Keyboard brightness level control not supported\n");
|
||||
return -ENXIO;
|
||||
out:
|
||||
mutex_unlock(&kbd_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct led_classdev kbd_led = {
|
||||
.name = "dell::kbd_backlight",
|
||||
.flags = LED_BRIGHT_HW_CHANGED,
|
||||
.brightness_set_blocking = kbd_led_level_set,
|
||||
.brightness_get = kbd_led_level_get,
|
||||
.groups = kbd_led_groups,
|
||||
@@ -1953,6 +2042,8 @@ static struct led_classdev kbd_led = {
|
||||
|
||||
static int __init kbd_led_init(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
kbd_init();
|
||||
if (!kbd_led_present)
|
||||
return -ENODEV;
|
||||
@@ -1964,7 +2055,11 @@ static int __init kbd_led_init(struct device *dev)
|
||||
if (kbd_led.max_brightness)
|
||||
kbd_led.max_brightness--;
|
||||
}
|
||||
return led_classdev_register(dev, &kbd_led);
|
||||
ret = led_classdev_register(dev, &kbd_led);
|
||||
if (ret)
|
||||
kbd_led_present = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void brightness_set_exit(struct led_classdev *led_cdev,
|
||||
@@ -1981,6 +2076,26 @@ static void kbd_led_exit(void)
|
||||
led_classdev_unregister(&kbd_led);
|
||||
}
|
||||
|
||||
static int dell_laptop_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
switch (action) {
|
||||
case DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED:
|
||||
if (!kbd_led_present)
|
||||
break;
|
||||
|
||||
led_classdev_notify_brightness_hw_changed(&kbd_led,
|
||||
kbd_led_level_get(&kbd_led));
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block dell_laptop_notifier = {
|
||||
.notifier_call = dell_laptop_notifier_call,
|
||||
};
|
||||
|
||||
int dell_micmute_led_set(int state)
|
||||
{
|
||||
struct calling_interface_buffer *buffer;
|
||||
@@ -2049,6 +2164,8 @@ static int __init dell_init(void)
|
||||
debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
|
||||
&dell_debugfs_fops);
|
||||
|
||||
dell_laptop_register_notifier(&dell_laptop_notifier);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
|
||||
return 0;
|
||||
|
||||
@@ -2081,11 +2198,17 @@ static int __init dell_init(void)
|
||||
|
||||
dell_backlight_device->props.brightness =
|
||||
dell_get_intensity(dell_backlight_device);
|
||||
if (dell_backlight_device->props.brightness < 0) {
|
||||
ret = dell_backlight_device->props.brightness;
|
||||
goto fail_get_brightness;
|
||||
}
|
||||
backlight_update_status(dell_backlight_device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_get_brightness:
|
||||
backlight_device_unregister(dell_backlight_device);
|
||||
fail_backlight:
|
||||
dell_cleanup_rfkill();
|
||||
fail_rfkill:
|
||||
@@ -2100,6 +2223,7 @@ fail_platform_driver:
|
||||
|
||||
static void __exit dell_exit(void)
|
||||
{
|
||||
dell_laptop_unregister_notifier(&dell_laptop_notifier);
|
||||
debugfs_remove_recursive(dell_laptop_dir);
|
||||
if (quirks && quirks->touchpad_led)
|
||||
touchpad_led_exit();
|
||||
|
||||
@@ -105,6 +105,26 @@ struct calling_interface_token *dell_smbios_find_token(int tokenid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dell_smbios_find_token);
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(dell_laptop_chain_head);
|
||||
|
||||
int dell_laptop_register_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&dell_laptop_chain_head, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dell_laptop_register_notifier);
|
||||
|
||||
int dell_laptop_unregister_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&dell_laptop_chain_head, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dell_laptop_unregister_notifier);
|
||||
|
||||
void dell_laptop_call_notifier(unsigned long action, void *data)
|
||||
{
|
||||
blocking_notifier_call_chain(&dell_laptop_chain_head, action, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);
|
||||
|
||||
static void __init parse_da_table(const struct dmi_header *dm)
|
||||
{
|
||||
/* Final token is a terminator, so we don't want to copy it */
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#ifndef _DELL_SMBIOS_H_
|
||||
#define _DELL_SMBIOS_H_
|
||||
|
||||
struct notifier_block;
|
||||
|
||||
/* This structure will be modified by the firmware when we enter
|
||||
* system management mode, hence the volatiles */
|
||||
|
||||
@@ -43,4 +45,13 @@ void dell_smbios_release_buffer(void);
|
||||
void dell_smbios_send_request(int class, int select);
|
||||
|
||||
struct calling_interface_token *dell_smbios_find_token(int tokenid);
|
||||
|
||||
enum dell_laptop_notifier_actions {
|
||||
DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED,
|
||||
};
|
||||
|
||||
int dell_laptop_register_notifier(struct notifier_block *nb);
|
||||
int dell_laptop_unregister_notifier(struct notifier_block *nb);
|
||||
void dell_laptop_call_notifier(unsigned long action, void *data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -152,12 +152,10 @@ static int __init dell_wmi_aio_input_setup(void)
|
||||
err = input_register_device(dell_wmi_aio_input_dev);
|
||||
if (err) {
|
||||
pr_info("Unable to register input device\n");
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(dell_wmi_aio_input_dev);
|
||||
err_free_dev:
|
||||
input_free_device(dell_wmi_aio_input_dev);
|
||||
return err;
|
||||
@@ -192,7 +190,6 @@ static int __init dell_wmi_aio_init(void)
|
||||
err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
|
||||
if (err) {
|
||||
pr_err("Unable to register notify handler - %d\n", err);
|
||||
sparse_keymap_free(dell_wmi_aio_input_dev);
|
||||
input_unregister_device(dell_wmi_aio_input_dev);
|
||||
return err;
|
||||
}
|
||||
@@ -206,7 +203,6 @@ static void __exit dell_wmi_aio_exit(void)
|
||||
|
||||
guid = dell_wmi_aio_find();
|
||||
wmi_remove_notify_handler(guid);
|
||||
sparse_keymap_free(dell_wmi_aio_input_dev);
|
||||
input_unregister_device(dell_wmi_aio_input_dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -329,6 +329,10 @@ static void dell_wmi_process_key(int type, int code)
|
||||
if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request)
|
||||
return;
|
||||
|
||||
if (key->keycode == KEY_KBDILLUMTOGGLE)
|
||||
dell_laptop_call_notifier(
|
||||
DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, NULL);
|
||||
|
||||
sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
|
||||
}
|
||||
|
||||
@@ -603,23 +607,15 @@ static int __init dell_wmi_input_setup(void)
|
||||
|
||||
err = input_register_device(dell_wmi_input_dev);
|
||||
if (err)
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(dell_wmi_input_dev);
|
||||
err_free_dev:
|
||||
input_free_device(dell_wmi_input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void dell_wmi_input_destroy(void)
|
||||
{
|
||||
sparse_keymap_free(dell_wmi_input_dev);
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Descriptor buffer is 128 byte long and contains:
|
||||
*
|
||||
@@ -740,7 +736,7 @@ static int __init dell_wmi_init(void)
|
||||
status = wmi_install_notify_handler(DELL_EVENT_GUID,
|
||||
dell_wmi_notify, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dell_wmi_input_destroy();
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
pr_err("Unable to register notify handler - %d\n", status);
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -752,7 +748,7 @@ static int __init dell_wmi_init(void)
|
||||
if (err) {
|
||||
pr_err("Failed to enable WMI events\n");
|
||||
wmi_remove_notify_handler(DELL_EVENT_GUID);
|
||||
dell_wmi_input_destroy();
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -766,6 +762,6 @@ static void __exit dell_wmi_exit(void)
|
||||
if (wmi_requires_smbios_request)
|
||||
dell_wmi_events_set_enabled(false);
|
||||
wmi_remove_notify_handler(DELL_EVENT_GUID);
|
||||
dell_wmi_input_destroy();
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
}
|
||||
module_exit(dell_wmi_exit);
|
||||
|
||||
@@ -150,6 +150,8 @@ static const struct key_entry eeepc_keymap[] = {
|
||||
{ KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
|
||||
{ KE_KEY, 0x38, { KEY_F14 } },
|
||||
{ KE_IGNORE, 0x50, { KEY_RESERVED } }, /* AC plugged */
|
||||
{ KE_IGNORE, 0x51, { KEY_RESERVED } }, /* AC unplugged */
|
||||
{ KE_END, 0 },
|
||||
};
|
||||
|
||||
@@ -1205,14 +1207,12 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
pr_err("Unable to register input device\n");
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
eeepc->inputdev = input;
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(input);
|
||||
err_free_dev:
|
||||
input_free_device(input);
|
||||
return error;
|
||||
@@ -1220,10 +1220,8 @@ err_free_dev:
|
||||
|
||||
static void eeepc_input_exit(struct eeepc_laptop *eeepc)
|
||||
{
|
||||
if (eeepc->inputdev) {
|
||||
sparse_keymap_free(eeepc->inputdev);
|
||||
if (eeepc->inputdev)
|
||||
input_unregister_device(eeepc->inputdev);
|
||||
}
|
||||
eeepc->inputdev = NULL;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* hp-wireless button for Windows 8
|
||||
* Airplane mode button for HP & Xiaomi laptops
|
||||
*
|
||||
* Copyright (C) 2014 Alex Hung <alex.hung@canonical.com>
|
||||
* Copyright (C) 2014-2017 Alex Hung <alex.hung@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,11 +29,13 @@
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Alex Hung");
|
||||
MODULE_ALIAS("acpi*:HPQ6001:*");
|
||||
MODULE_ALIAS("acpi*:WSTADEF:*");
|
||||
|
||||
static struct input_dev *hpwl_input_dev;
|
||||
|
||||
static const struct acpi_device_id hpwl_ids[] = {
|
||||
{"HPQ6001", 0},
|
||||
{"WSTADEF", 0},
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
@@ -108,23 +110,4 @@ static struct acpi_driver hpwl_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init hpwl_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
pr_info("Initializing HPQ6001 module\n");
|
||||
err = acpi_bus_register_driver(&hpwl_driver);
|
||||
if (err)
|
||||
pr_err("Unable to register HP wireless control driver.\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit hpwl_exit(void)
|
||||
{
|
||||
pr_info("Exiting HPQ6001 module\n");
|
||||
acpi_bus_unregister_driver(&hpwl_driver);
|
||||
}
|
||||
|
||||
module_init(hpwl_init);
|
||||
module_exit(hpwl_exit);
|
||||
module_acpi_driver(hpwl_driver);
|
||||
|
||||
+199
-219
File diff suppressed because it is too large
Load Diff
@@ -604,14 +604,12 @@ static int ideapad_input_init(struct ideapad_private *priv)
|
||||
error = input_register_device(inputdev);
|
||||
if (error) {
|
||||
pr_err("Unable to register input device\n");
|
||||
goto err_free_keymap;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
priv->inputdev = inputdev;
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(inputdev);
|
||||
err_free_dev:
|
||||
input_free_device(inputdev);
|
||||
return error;
|
||||
@@ -619,7 +617,6 @@ err_free_dev:
|
||||
|
||||
static void ideapad_input_exit(struct ideapad_private *priv)
|
||||
{
|
||||
sparse_keymap_free(priv->inputdev);
|
||||
input_unregister_device(priv->inputdev);
|
||||
priv->inputdev = NULL;
|
||||
}
|
||||
@@ -871,6 +868,20 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lenovo V310-15ISK",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lenovo ideapad 310-15IKB",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lenovo ideapad Y700-15ACZ",
|
||||
.matches = {
|
||||
|
||||
@@ -77,14 +77,12 @@ struct intel_hid_priv {
|
||||
struct input_dev *array;
|
||||
};
|
||||
|
||||
static int intel_hid_set_enable(struct device *device, int enable)
|
||||
static int intel_hid_set_enable(struct device *device, bool enable)
|
||||
{
|
||||
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list args = { 1, &arg0 };
|
||||
acpi_status status;
|
||||
|
||||
arg0.integer.value = enable;
|
||||
status = acpi_evaluate_object(ACPI_HANDLE(device), "HDSM", &args, NULL);
|
||||
status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM",
|
||||
enable);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_warn(device, "failed to %sable hotkeys\n",
|
||||
enable ? "en" : "dis");
|
||||
@@ -120,7 +118,7 @@ static void intel_button_array_enable(struct device *device, bool enable)
|
||||
|
||||
static int intel_hid_pl_suspend_handler(struct device *device)
|
||||
{
|
||||
intel_hid_set_enable(device, 0);
|
||||
intel_hid_set_enable(device, false);
|
||||
intel_button_array_enable(device, false);
|
||||
|
||||
return 0;
|
||||
@@ -128,7 +126,7 @@ static int intel_hid_pl_suspend_handler(struct device *device)
|
||||
|
||||
static int intel_hid_pl_resume_handler(struct device *device)
|
||||
{
|
||||
intel_hid_set_enable(device, 1);
|
||||
intel_hid_set_enable(device, true);
|
||||
intel_button_array_enable(device, true);
|
||||
|
||||
return 0;
|
||||
@@ -136,6 +134,7 @@ static int intel_hid_pl_resume_handler(struct device *device)
|
||||
|
||||
static const struct dev_pm_ops intel_hid_pl_pm_ops = {
|
||||
.freeze = intel_hid_pl_suspend_handler,
|
||||
.thaw = intel_hid_pl_resume_handler,
|
||||
.restore = intel_hid_pl_resume_handler,
|
||||
.suspend = intel_hid_pl_suspend_handler,
|
||||
.resume = intel_hid_pl_resume_handler,
|
||||
@@ -146,28 +145,18 @@ static int intel_hid_input_setup(struct platform_device *device)
|
||||
struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
|
||||
int ret;
|
||||
|
||||
priv->input_dev = input_allocate_device();
|
||||
priv->input_dev = devm_input_allocate_device(&device->dev);
|
||||
if (!priv->input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL);
|
||||
if (ret)
|
||||
goto err_free_device;
|
||||
return ret;
|
||||
|
||||
priv->input_dev->dev.parent = &device->dev;
|
||||
priv->input_dev->name = "Intel HID events";
|
||||
priv->input_dev->id.bustype = BUS_HOST;
|
||||
set_bit(KEY_RFKILL, priv->input_dev->keybit);
|
||||
|
||||
ret = input_register_device(priv->input_dev);
|
||||
if (ret)
|
||||
goto err_free_device;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_device:
|
||||
input_free_device(priv->input_dev);
|
||||
return ret;
|
||||
return input_register_device(priv->input_dev);
|
||||
}
|
||||
|
||||
static int intel_button_array_input_setup(struct platform_device *device)
|
||||
@@ -184,20 +173,12 @@ static int intel_button_array_input_setup(struct platform_device *device)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->array->dev.parent = &device->dev;
|
||||
priv->array->name = "Intel HID 5 button array";
|
||||
priv->array->id.bustype = BUS_HOST;
|
||||
|
||||
return input_register_device(priv->array);
|
||||
}
|
||||
|
||||
static void intel_hid_input_destroy(struct platform_device *device)
|
||||
{
|
||||
struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
|
||||
|
||||
input_unregister_device(priv->input_dev);
|
||||
}
|
||||
|
||||
static void notify_handler(acpi_handle handle, u32 event, void *context)
|
||||
{
|
||||
struct platform_device *device = context;
|
||||
@@ -272,12 +253,10 @@ static int intel_hid_probe(struct platform_device *device)
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
notify_handler,
|
||||
device);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
err = -EBUSY;
|
||||
goto err_remove_input;
|
||||
}
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EBUSY;
|
||||
|
||||
err = intel_hid_set_enable(&device->dev, 1);
|
||||
err = intel_hid_set_enable(&device->dev, true);
|
||||
if (err)
|
||||
goto err_remove_notify;
|
||||
|
||||
@@ -296,9 +275,6 @@ static int intel_hid_probe(struct platform_device *device)
|
||||
err_remove_notify:
|
||||
acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
|
||||
|
||||
err_remove_input:
|
||||
intel_hid_input_destroy(device);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -307,8 +283,7 @@ static int intel_hid_remove(struct platform_device *device)
|
||||
acpi_handle handle = ACPI_HANDLE(&device->dev);
|
||||
|
||||
acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
|
||||
intel_hid_input_destroy(device);
|
||||
intel_hid_set_enable(&device->dev, 0);
|
||||
intel_hid_set_enable(&device->dev, false);
|
||||
intel_button_array_enable(&device->dev, false);
|
||||
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user