diff options
Diffstat (limited to 'drivers/platform')
29 files changed, 1266 insertions, 520 deletions
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 7f1a2e2711bd..d866db80b4fd 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -37,6 +37,8 @@ #define ISL_ALS_I2C_ADDR 0x44 #define TAOS_ALS_I2C_ADDR 0x29 +#define MAX_I2C_DEVICE_DEFERRALS 5 + static struct i2c_client *als; static struct i2c_client *tp; static struct i2c_client *ts; @@ -45,6 +47,8 @@ static const char *i2c_adapter_names[] = { "SMBus I801 adapter", "i915 gmbus vga", "i915 gmbus panel", + "i2c-designware-pci", + "i2c-designware-pci", }; /* Keep this enum consistent with i2c_adapter_names */ @@ -52,11 +56,21 @@ enum i2c_adapter_type { I2C_ADAPTER_SMBUS = 0, I2C_ADAPTER_VGADDC, I2C_ADAPTER_PANEL, + I2C_ADAPTER_DESIGNWARE_0, + I2C_ADAPTER_DESIGNWARE_1, +}; + +enum i2c_peripheral_state { + UNPROBED = 0, + PROBED, + TIMEDOUT, }; struct i2c_peripheral { int (*add)(enum i2c_adapter_type type); enum i2c_adapter_type type; + enum i2c_peripheral_state state; + int tries; }; #define MAX_I2C_PERIPHERALS 3 @@ -97,8 +111,6 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), .t19_keymap = mxt_t19_keys, - .config = NULL, - .config_length = 0, }; static struct i2c_board_info atmel_224s_tp_device = { @@ -109,8 +121,6 @@ static struct i2c_board_info atmel_224s_tp_device = { static struct mxt_platform_data atmel_1664s_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, - .config = NULL, - .config_length = 0, }; static struct i2c_board_info atmel_1664s_device = { @@ -162,8 +172,8 @@ static struct i2c_client *__add_probed_i2c_device( /* add the i2c device */ client = i2c_new_probed_device(adapter, info, addrs, NULL); if (!client) - pr_err("%s failed to register device %d-%02x\n", - __func__, bus, info->addr); + pr_notice("%s failed to register device %d-%02x\n", + __func__, bus, info->addr); else pr_debug("%s added i2c device %d-%02x\n", __func__, bus, info->addr); @@ -172,29 +182,43 @@ static struct i2c_client *__add_probed_i2c_device( return client; } +struct i2c_lookup { + const char *name; + int instance; + int n; +}; + static int __find_i2c_adap(struct device *dev, void *data) { - const char *name = data; + struct i2c_lookup *lookup = data; static const char *prefix = "i2c-"; struct i2c_adapter *adapter; + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) return 0; adapter = to_i2c_adapter(dev); - return (strncmp(adapter->name, name, strlen(name)) == 0); + if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 && + lookup->n++ == lookup->instance) + return 1; + return 0; } static int find_i2c_adapter_num(enum i2c_adapter_type type) { struct device *dev = NULL; struct i2c_adapter *adapter; - const char *name = i2c_adapter_names[type]; + struct i2c_lookup lookup; + + memset(&lookup, 0, sizeof(lookup)); + lookup.name = i2c_adapter_names[type]; + lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0; + /* find the adapter by name */ - dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, - __find_i2c_adap); + dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap); if (!dev) { /* Adapters may appear later. Deferred probing will retry */ pr_notice("%s: i2c adapter %s not found on system.\n", __func__, - name); + lookup.name); return -ENODEV; } adapter = to_i2c_adapter(dev); @@ -231,6 +255,7 @@ static struct i2c_client *add_i2c_device(const char *name, struct i2c_board_info *info) { const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; + return __add_probed_i2c_device(name, find_i2c_adapter_num(type), info, @@ -328,9 +353,36 @@ static int chromeos_laptop_probe(struct platform_device *pdev) if (i2c_dev->add == NULL) break; - /* Add the device. Set -EPROBE_DEFER on any failure */ - if (i2c_dev->add(i2c_dev->type)) + if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED) + continue; + + /* + * Check that the i2c adapter is present. + * -EPROBE_DEFER if missing as the adapter may appear much + * later. + */ + if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) { ret = -EPROBE_DEFER; + continue; + } + + /* Add the device. */ + if (i2c_dev->add(i2c_dev->type) == -EAGAIN) { + /* + * Set -EPROBE_DEFER a limited num of times + * if device is not successfully added. + */ + if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) { + ret = -EPROBE_DEFER; + } else { + /* Ran out of tries. */ + pr_notice("%s: Ran out of tries for device.\n", + __func__); + i2c_dev->state = TIMEDOUT; + } + } else { + i2c_dev->state = PROBED; + } } return ret; @@ -363,6 +415,27 @@ static struct chromeos_laptop chromebook_pixel = { }, }; +static struct chromeos_laptop hp_chromebook_14 = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + }, +}; + +static struct chromeos_laptop dell_chromebook_11 = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + }, +}; + +static struct chromeos_laptop toshiba_cb35 = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + }, +}; + static struct chromeos_laptop acer_c7_chromebook = { .i2c_peripherals = { /* Touchpad. */ @@ -377,6 +450,17 @@ static struct chromeos_laptop acer_ac700 = { }, }; +static struct chromeos_laptop acer_c720 = { + .i2c_peripherals = { + /* Touchscreen. */ + { .add = setup_atmel_1664s_ts, I2C_ADAPTER_DESIGNWARE_1 }, + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 }, + }, +}; + static struct chromeos_laptop hp_pavilion_14_chromebook = { .i2c_peripherals = { /* Touchpad. */ @@ -420,6 +504,30 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = { _CBDD(chromebook_pixel), }, { + .ident = "Wolf", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"), + }, + _CBDD(dell_chromebook_11), + }, + { + .ident = "HP Chromebook 14", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + DMI_MATCH(DMI_PRODUCT_NAME, "Falco"), + }, + _CBDD(hp_chromebook_14), + }, + { + .ident = "Toshiba CB35", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + DMI_MATCH(DMI_PRODUCT_NAME, "Leon"), + }, + _CBDD(toshiba_cb35), + }, + { .ident = "Acer C7 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), @@ -434,6 +542,13 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = { _CBDD(acer_ac700), }, { + .ident = "Acer C720", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"), + }, + _CBDD(acer_c720), + }, + { .ident = "HP Pavilion 14 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), @@ -464,6 +579,7 @@ static struct platform_driver cros_platform_driver = { static int __init chromeos_laptop_init(void) { int ret; + if (!dmi_check_system(chromeos_laptop_dmi_table)) { pr_debug("%s unsupported system.\n", __func__); return -ENODEV; diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c index e0e0e65cf442..34749200e4ab 100644 --- a/drivers/platform/chrome/chromeos_pstore.c +++ b/drivers/platform/chrome/chromeos_pstore.c @@ -16,23 +16,13 @@ static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = { { /* - * Today all Chromebooks/boxes ship with GOOGLE as vendor and + * Today all Chromebooks/boxes ship with Google_* as version and * coreboot as bios vendor. No other systems with this * combination are known to date. */ .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), - }, - }, - { - /* - * The first Samsung Chromebox and Chromebook Series 5 550 use - * coreboot but with Samsung as the system vendor. - */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + DMI_MATCH(DMI_BIOS_VERSION, "Google_"), }, }, { diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index aa19a8a7066a..a2eabe6ff9ad 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -202,6 +202,7 @@ config TC1100_WMI config HP_ACCEL tristate "HP laptop accelerometer" depends on INPUT && ACPI + depends on SERIO_I8042 select SENSORS_LIS3LV02D select NEW_LEDS select LEDS_CLASS @@ -652,6 +653,25 @@ config TOSHIBA_BT_RFKILL If you have a modern Toshiba laptop with a Bluetooth and an RFKill switch (such as the Portege R500), say Y. +config TOSHIBA_HAPS + tristate "Toshiba HDD Active Protection Sensor" + depends on ACPI + ---help--- + This driver adds support for the built-in accelerometer + found on recent Toshiba laptops equiped with HID TOS620A + device. + + This driver receives ACPI notify events 0x80 when the sensor + detects a sudden move or a harsh vibration, as well as an + ACPI notify event 0x81 whenever the movement or vibration has + been stabilized. + + Also provides sysfs entries to get/set the desired protection + level and reseting the HDD protection interface. + + If you have a recent Toshiba laptop with a built-in accelerometer + device, say Y. + config ACPI_CMPC tristate "CMPC Laptop Extras" depends on X86 && ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c4ca428fd3db..f82232b1fc4d 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o +obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index bbf78b2d6d93..26c4fd1394da 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -96,7 +96,7 @@ enum acer_wmi_event_ids { WMID_ACCEL_EVENT = 0x5, }; -static const struct key_entry acer_wmi_keymap[] = { +static const struct key_entry acer_wmi_keymap[] __initconst = { {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ @@ -294,7 +294,7 @@ struct quirk_entry { static struct quirk_entry *quirks; -static void set_quirks(void) +static void __init set_quirks(void) { if (!interface) return; @@ -306,7 +306,7 @@ static void set_quirks(void) interface->capability |= ACER_CAP_BRIGHTNESS; } -static int dmi_matched(const struct dmi_system_id *dmi) +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; @@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = { }; /* The Aspire One has a dummy ACPI-WMI interface - disable it */ -static struct dmi_system_id acer_blacklist[] = { +static const struct dmi_system_id acer_blacklist[] __initconst = { { .ident = "Acer Aspire One (SSD)", .matches = { @@ -355,7 +355,7 @@ static struct dmi_system_id acer_blacklist[] = { {} }; -static struct dmi_system_id acer_quirks[] = { +static const struct dmi_system_id acer_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Acer Aspire 1360", @@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[] = { {} }; -static int video_set_backlight_video_vendor(const struct dmi_system_id *d) +static int __init +video_set_backlight_video_vendor(const struct dmi_system_id *d) { interface->capability &= ~ACER_CAP_BRIGHTNESS; pr_info("Brightness must be controlled by generic video driver\n"); return 0; } -static const struct dmi_system_id video_vendor_dmi_table[] = { +static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { { .callback = video_set_backlight_video_vendor, .ident = "Acer TravelMate 4750", @@ -578,11 +579,22 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), }, }, + { + /* + * Note no video_set_backlight_video_vendor, we must use the + * acer interface, as there is no native backlight interface. + */ + .ident = "Acer KAV80", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), + }, + }, {} }; /* Find which quirks are needed for a particular vendor/ model pair */ -static void find_quirks(void) +static void __init find_quirks(void) { if (!force_series) { dmi_check_system(acer_quirks); @@ -749,7 +761,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap) return wmab_execute(&args, NULL); } -static acpi_status AMW0_find_mailled(void) +static acpi_status __init AMW0_find_mailled(void) { struct wmab_args args; struct wmab_ret ret; @@ -781,16 +793,16 @@ static acpi_status AMW0_find_mailled(void) return AE_OK; } -static int AMW0_set_cap_acpi_check_device_found; +static int AMW0_set_cap_acpi_check_device_found __initdata; -static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, +static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, u32 level, void *context, void **retval) { AMW0_set_cap_acpi_check_device_found = 1; return AE_OK; } -static const struct acpi_device_id norfkill_ids[] = { +static const struct acpi_device_id norfkill_ids[] __initconst = { { "VPC2004", 0}, { "IBM0068", 0}, { "LEN0068", 0}, @@ -798,7 +810,7 @@ static const struct acpi_device_id norfkill_ids[] = { { "", 0}, }; -static int AMW0_set_cap_acpi_check_device(void) +static int __init AMW0_set_cap_acpi_check_device(void) { const struct acpi_device_id *id; @@ -808,7 +820,7 @@ static int AMW0_set_cap_acpi_check_device(void) return AMW0_set_cap_acpi_check_device_found; } -static acpi_status AMW0_set_capabilities(void) +static acpi_status __init AMW0_set_capabilities(void) { struct wmab_args args; struct wmab_ret ret; @@ -1184,7 +1196,7 @@ static acpi_status wmid_v2_set_u32(u32 value, u32 cap) return wmid3_set_device_status(value, device); } -static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) +static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) { struct hotkey_function_type_aa *type_aa; @@ -1209,7 +1221,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) commun_fn_key_number = type_aa->commun_fn_key_number; } -static acpi_status WMID_set_capabilities(void) +static acpi_status __init WMID_set_capabilities(void) { struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; @@ -1658,7 +1670,7 @@ static ssize_t show_bool_threeg(struct device *dev, u32 result; \ acpi_status status; - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", current->comm); status = get_u32(&result, ACER_CAP_THREEG); if (ACPI_SUCCESS(status)) @@ -1671,7 +1683,7 @@ static ssize_t set_bool_threeg(struct device *dev, { u32 tmp = simple_strtoul(buf, NULL, 10); acpi_status status = set_u32(tmp, ACER_CAP_THREEG); - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", current->comm); if (ACPI_FAILURE(status)) return -EINVAL; @@ -1683,7 +1695,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, static ssize_t show_interface(struct device *dev, struct device_attribute *attr, char *buf) { - pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", + pr_info("This interface sysfs will be removed in 2014 - used by: %s\n", current->comm); switch (interface->type) { case ACER_AMW0: @@ -1777,7 +1789,7 @@ static void acer_wmi_notify(u32 value, void *context) } } -static acpi_status +static acpi_status __init wmid3_set_lm_mode(struct lm_input_params *params, struct lm_return_value *return_value) { @@ -1811,7 +1823,7 @@ wmid3_set_lm_mode(struct lm_input_params *params, return status; } -static int acer_wmi_enable_ec_raw(void) +static int __init acer_wmi_enable_ec_raw(void) { struct lm_return_value return_value; acpi_status status; @@ -1834,7 +1846,7 @@ static int acer_wmi_enable_ec_raw(void) return status; } -static int acer_wmi_enable_lm(void) +static int __init acer_wmi_enable_lm(void) { struct lm_return_value return_value; acpi_status status; @@ -2043,6 +2055,7 @@ static int acer_platform_remove(struct platform_device *device) return 0; } +#ifdef CONFIG_PM_SLEEP static int acer_suspend(struct device *dev) { u32 value; @@ -2083,6 +2096,10 @@ static int acer_resume(struct device *dev) return 0; } +#else +#define acer_suspend NULL +#define acer_resume NULL +#endif static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); @@ -2120,7 +2137,7 @@ static int remove_sysfs(struct platform_device *device) return 0; } -static int create_sysfs(void) +static int __init create_sysfs(void) { int retval = -ENOMEM; @@ -2149,7 +2166,7 @@ static void remove_debugfs(void) debugfs_remove(interface->debug.root); } -static int create_debugfs(void) +static int __init create_debugfs(void) { interface->debug.root = debugfs_create_dir("acer-wmi", NULL); if (!interface->debug.root) { diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 297b6640213f..c5af23b64438 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES { struct quirk_entry { u8 num_zones; + u8 hdmi_mux; }; static struct quirk_entry *quirks; static struct quirk_entry quirk_unknown = { .num_zones = 2, + .hdmi_mux = 0, }; static struct quirk_entry quirk_x51_family = { .num_zones = 3, + .hdmi_mux = 0. }; -static int dmi_matched(const struct dmi_system_id *dmi) +static struct quirk_entry quirk_asm100 = { + .num_zones = 2, + .hdmi_mux = 1, +}; + +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; } -static struct dmi_system_id alienware_quirks[] = { +static const struct dmi_system_id alienware_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Alienware X51 R1", @@ -96,6 +104,15 @@ static struct dmi_system_id alienware_quirks[] = { }, .driver_data = &quirk_x51_family, }, + { + .callback = dmi_matched, + .ident = "Alienware ASM100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), + }, + .driver_data = &quirk_asm100, + }, {} }; @@ -537,7 +554,8 @@ static struct attribute_group hdmi_attribute_group = { static void remove_hdmi(struct platform_device *dev) { - sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); + if (quirks->hdmi_mux > 0) + sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); } static int create_hdmi(struct platform_device *dev) @@ -583,7 +601,7 @@ static int __init alienware_wmi_init(void) if (ret) goto fail_platform_device2; - if (interface == WMAX) { + if (quirks->hdmi_mux > 0) { ret = create_hdmi(platform_device); if (ret) goto fail_prep_hdmi; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index ddf0eefd862c..c1a6cd66af42 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55u = { .no_display_toggle = true, }; -static struct quirk_entry quirk_asus_x401u = { +static struct quirk_entry quirk_asus_wapf4 = { .wapf = 4, }; +static struct quirk_entry quirk_asus_x200ca = { + .wapf = 2, +}; + static int dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; } -static struct dmi_system_id asus_quirks[] = { +static const struct dmi_system_id asus_quirks[] = { + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. U32U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), + }, + /* + * Note this machine has a Brazos APU, and most Brazos Asus + * machines need quirk_asus_x55u / wmi_backlight_power but + * here acpi-video seems to work fine for backlight control. + */ + .driver_data = &quirk_asus_wapf4, + }, { .callback = dmi_matched, .ident = "ASUSTeK COMPUTER INC. X401U", @@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -142,7 +160,34 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550CC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), + }, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550CL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), + }, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550VB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"), + }, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -151,7 +196,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -160,7 +205,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -178,7 +223,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -187,7 +232,16 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X75VBP", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), + }, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -196,7 +250,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -205,7 +259,16 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X200CA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), + }, + .driver_data = &quirk_asus_x200ca, }, {}, }; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3c6ccedc82b6..21fc932da3a1 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -46,6 +46,7 @@ #include <linux/platform_device.h> #include <linux/thermal.h> #include <linux/acpi.h> +#include <linux/dmi.h> #include <acpi/video.h> #include "asus-wmi.h" @@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { + if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_wmi *asus, return -EINVAL; if ((dev_id == ASUS_WMI_DEVID_WLAN) && - (asus->driver->quirks->wapf == 4)) + (asus->driver->quirks->wapf > 0)) rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); rfkill_init_sw_state(*rfkill, !result); @@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) int power; max = read_brightness_max(asus); - - if (max == -ENODEV) - max = 0; - else if (max < 0) + if (max < 0) return max; power = read_backlight_power(asus); @@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_device *pdev) struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); struct asus_wmi *asus; + const char *chassis_type; acpi_status status; int err; u32 result; @@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_rfkill; + /* Some Asus desktop boards export an acpi-video backlight interface, + stop this from showing up */ + chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); + if (chassis_type && !strcmp(chassis_type, "3")) + acpi_video_dmi_promote_vendor(); if (asus->driver->quirks->wmi_backlight_power) acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 7297df2ebf50..26bfd7bb5c13 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_device *pdev) return err; hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, - DRIVER_NAME, data, + "compal", data, compal_hwmon_groups); if (IS_ERR(hwmon_dev)) { err = PTR_ERR(hwmon_dev); diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index fed4111ac31a..233d2ee598a6 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vostro_v130 = { .touchpad_led = 1, }; -static int dmi_matched(const struct dmi_system_id *dmi) +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; @@ -123,7 +123,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, dell_device_table); -static struct dmi_system_id dell_quirks[] = { +static const struct dmi_system_id dell_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Dell Vostro V130", @@ -780,7 +780,7 @@ static struct led_classdev touchpad_led = { .flags = LED_CORE_SUSPENDRESUME, }; -static int touchpad_led_init(struct device *dev) +static int __init touchpad_led_init(struct device *dev) { return led_classdev_register(dev, &touchpad_led); } diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 390e8e33d5e3..25721bf20092 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -163,18 +163,24 @@ static void dell_wmi_notify(u32 value, void *context) const struct key_entry *key; int reported_key; u16 *buffer_entry = (u16 *)obj->buffer.pointer; + int buffer_size = obj->buffer.length/2; - if (dell_new_hk_type && (buffer_entry[1] != 0x10)) { + if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) { pr_info("Received unknown WMI event (0x%x)\n", buffer_entry[1]); kfree(obj); return; } - if (dell_new_hk_type || buffer_entry[1] == 0x0) + if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0)) reported_key = (int)buffer_entry[2]; - else + else if (buffer_size >= 2) reported_key = (int)buffer_entry[1] & 0xffff; + else { + pr_info("Received unknown WMI event\n"); + kfree(obj); + return; + } key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev, reported_key); diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9b0c57cd1d4a..db79902c4a8e 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -263,13 +263,11 @@ static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm, /* * Sys helpers */ -static int parse_arg(const char *buf, unsigned long count, int *val) +static int parse_arg(const char *buf, int *val) { - if (!count) - return 0; if (sscanf(buf, "%i", val) != 1) return -EINVAL; - return count; + return 0; } static ssize_t store_sys_acpi(struct device *dev, int cm, @@ -278,12 +276,13 @@ static ssize_t store_sys_acpi(struct device *dev, int cm, struct eeepc_laptop *eeepc = dev_get_drvdata(dev); int rv, value; - rv = parse_arg(buf, count, &value); - if (rv > 0) - value = set_acpi(eeepc, cm, value); - if (value < 0) + rv = parse_arg(buf, &value); + if (rv < 0) + return rv; + rv = set_acpi(eeepc, cm, value); + if (rv < 0) return -EIO; - return rv; + return count; } static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf) @@ -296,30 +295,34 @@ static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf) return sprintf(buf, "%d\n", value); } -#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \ - static ssize_t show_##_name(struct device *dev, \ +#define EEEPC_ACPI_SHOW_FUNC(_name, _cm) \ + static ssize_t _name##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ return show_sys_acpi(dev, _cm, buf); \ - } \ - static ssize_t store_##_name(struct device *dev, \ + } + +#define EEEPC_ACPI_STORE_FUNC(_name, _cm) \ + static ssize_t _name##_store(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t count) \ { \ return store_sys_acpi(dev, _cm, buf, count); \ - } \ - static struct device_attribute dev_attr_##_name = { \ - .attr = { \ - .name = __stringify(_name), \ - .mode = _mode }, \ - .show = show_##_name, \ - .store = store_##_name, \ } -EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA); -EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER); -EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH); +#define EEEPC_CREATE_DEVICE_ATTR_RW(_name, _cm) \ + EEEPC_ACPI_SHOW_FUNC(_name, _cm) \ + EEEPC_ACPI_STORE_FUNC(_name, _cm) \ + static DEVICE_ATTR_RW(_name) + +#define EEEPC_CREATE_DEVICE_ATTR_WO(_name, _cm) \ + EEEPC_ACPI_STORE_FUNC(_name, _cm) \ + static DEVICE_ATTR_WO(_name) + +EEEPC_CREATE_DEVICE_ATTR_RW(camera, CM_ASL_CAMERA); +EEEPC_CREATE_DEVICE_ATTR_RW(cardr, CM_ASL_CARDREADER); +EEEPC_CREATE_DEVICE_ATTR_WO(disp, CM_ASL_DISPLAYSWITCH); struct eeepc_cpufv { int num; @@ -329,14 +332,17 @@ struct eeepc_cpufv { static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c) { c->cur = get_acpi(eeepc, CM_ASL_CPUFV); + if (c->cur < 0) + return -ENODEV; + c->num = (c->cur >> 8) & 0xff; c->cur &= 0xff; - if (c->cur < 0 || c->num <= 0 || c->num > 12) + if (c->num == 0 || c->num > 12) return -ENODEV; return 0; } -static ssize_t show_available_cpufv(struct device *dev, +static ssize_t available_cpufv_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -353,7 +359,7 @@ static ssize_t show_available_cpufv(struct device *dev, return len; } -static ssize_t show_cpufv(struct device *dev, +static ssize_t cpufv_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -365,7 +371,7 @@ static ssize_t show_cpufv(struct device *dev, return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); } -static ssize_t store_cpufv(struct device *dev, +static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -377,16 +383,18 @@ static ssize_t store_cpufv(struct device *dev, return -EPERM; if (get_cpufv(eeepc, &c)) return -ENODEV; - rv = parse_arg(buf, count, &value); + rv = parse_arg(buf, &value); if (rv < 0) return rv; - if (!rv || value < 0 || value >= c.num) + if (value < 0 || value >= c.num) return -EINVAL; - set_acpi(eeepc, CM_ASL_CPUFV, value); - return rv; + rv = set_acpi(eeepc, CM_ASL_CPUFV, value); + if (rv) + return rv; + return count; } -static ssize_t show_cpufv_disabled(struct device *dev, +static ssize_t cpufv_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -395,14 +403,14 @@ static ssize_t show_cpufv_disabled(struct device *dev, return sprintf(buf, "%d\n", eeepc->cpufv_disabled); } -static ssize_t store_cpufv_disabled(struct device *dev, +static ssize_t cpufv_disabled_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct eeepc_laptop *eeepc = dev_get_drvdata(dev); int rv, value; - rv = parse_arg(buf, count, &value); + rv = parse_arg(buf, &value); if (rv < 0) return rv; @@ -412,7 +420,7 @@ static ssize_t store_cpufv_disabled(struct device *dev, pr_warn("cpufv enabled (not officially supported " "on this model)\n"); eeepc->cpufv_disabled = false; - return rv; + return count; case 1: return -EPERM; default: @@ -421,29 +429,9 @@ static ssize_t store_cpufv_disabled(struct device *dev, } -static struct device_attribute dev_attr_cpufv = { - .attr = { - .name = "cpufv", - .mode = 0644 }, - .show = show_cpufv, - .store = store_cpufv -}; - -static struct device_attribute dev_attr_available_cpufv = { - .attr = { - .name = "available_cpufv", - .mode = 0444 }, - .show = show_available_cpufv -}; - -static struct device_attribute dev_attr_cpufv_disabled = { - .attr = { - .name = "cpufv_disabled", - .mode = 0644 }, - .show = show_cpufv_disabled, - .store = store_cpufv_disabled -}; - +static DEVICE_ATTR_RW(cpufv); +static DEVICE_ATTR_RO(available_cpufv); +static DEVICE_ATTR_RW(cpufv_disabled); static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, @@ -545,7 +533,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc) eeepc->tpd_led.name = "eeepc::touchpad"; eeepc->tpd_led.brightness_set = tpd_led_set; if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */ - eeepc->tpd_led.brightness_get = tpd_led_get; + eeepc->tpd_led.brightness_get = tpd_led_get; eeepc->tpd_led.max_brightness = 1; rv = led_classdev_register(&eeepc->platform_device->dev, @@ -680,22 +668,21 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, status = acpi_get_handle(NULL, node, &handle); - if (ACPI_SUCCESS(status)) { - status = acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - eeepc_rfkill_notify, - eeepc); - if (ACPI_FAILURE(status)) - pr_warn("Failed to register notify on %s\n", node); - - /* - * Refresh pci hotplug in case the rfkill state was - * changed during setup. - */ - eeepc_rfkill_hotplug(eeepc, handle); - } else + if (ACPI_FAILURE(status)) return -ENODEV; + status = acpi_install_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + eeepc_rfkill_notify, + eeepc); + if (ACPI_FAILURE(status)) + pr_warn("Failed to register notify on %s\n", node); + + /* + * Refresh pci hotplug in case the rfkill state was + * changed during setup. + */ + eeepc_rfkill_hotplug(eeepc, handle); return 0; } @@ -707,20 +694,21 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc, status = acpi_get_handle(NULL, node, &handle); - if (ACPI_SUCCESS(status)) { - status = acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - eeepc_rfkill_notify); - if (ACPI_FAILURE(status)) - pr_err("Error removing rfkill notify handler %s\n", - node); - /* - * Refresh pci hotplug in case the rfkill - * state was changed after - * eeepc_unregister_rfkill_notifier() - */ - eeepc_rfkill_hotplug(eeepc, handle); - } + if (ACPI_FAILURE(status)) + return; + + status = acpi_remove_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + eeepc_rfkill_notify); + if (ACPI_FAILURE(status)) + pr_err("Error removing rfkill notify handler %s\n", + node); + /* + * Refresh pci hotplug in case the rfkill + * state was changed after + * eeepc_unregister_rfkill_notifier() + */ + eeepc_rfkill_hotplug(eeepc, handle); } static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, @@ -1042,10 +1030,11 @@ static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) { int rv, value; - rv = parse_arg(buf, count, &value); - if (rv > 0) - set(value); - return rv; + rv = parse_arg(buf, &value); + if (rv < 0) + return rv; + set(value); + return count; } static ssize_t show_sys_hwmon(int (*get)(void), char *buf) @@ -1053,26 +1042,36 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) return sprintf(buf, "%d\n", get()); } -#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ - static ssize_t show_##_name(struct device *dev, \ +#define EEEPC_SENSOR_SHOW_FUNC(_name, _get) \ + static ssize_t _name##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return show_sys_hwmon(_set, buf); \ - } \ - static ssize_t store_##_name(struct device *dev, \ + return show_sys_hwmon(_get, buf); \ + } + +#define EEEPC_SENSOR_STORE_FUNC(_name, _set) \ + static ssize_t _name##_store(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - return store_sys_hwmon(_get, buf, count); \ - } \ - static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); + return store_sys_hwmon(_set, buf, count); \ + } + +#define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set) \ + EEEPC_SENSOR_SHOW_FUNC(_name, _get) \ + EEEPC_SENSOR_STORE_FUNC(_name, _set) \ + static DEVICE_ATTR_RW(_name) -EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); -EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, - eeepc_get_fan_pwm, eeepc_set_fan_pwm); -EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, - eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); +#define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get) \ + EEEPC_SENSOR_SHOW_FUNC(_name, _get) \ + static DEVICE_ATTR_RO(_name) + +EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm); +EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm, + eeepc_set_fan_pwm); +EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl, + eeepc_set_fan_ctrl); static struct attribute *hwmon_attrs[] = { &dev_attr_pwm1.attr, @@ -1424,8 +1423,9 @@ static int eeepc_acpi_add(struct acpi_device *device) result = eeepc_backlight_init(eeepc); if (result) goto fail_backlight; - } else + } else { pr_info("Backlight controlled by ACPI video driver\n"); + } result = eeepc_input_init(eeepc); if (result) diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 6112933f6278..14fd2ecb06a1 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_system_id *dmi) return 1; } -static struct dmi_system_id asus_quirks[] = { +static const struct dmi_system_id asus_quirks[] = { { .callback = dmi_matched, .ident = "ASUSTeK Computer INC. 1000H", diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index e6f336270c21..2655d4a988f3 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -129,15 +129,14 @@ #define FUJLAPTOP_DBG_INFO 0x0004 #define FUJLAPTOP_DBG_TRACE 0x0008 -#define dbg_printk(a_dbg_level, format, arg...) \ +#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG +#define vdbg_printk(a_dbg_level, format, arg...) \ do { if (dbg_level & a_dbg_level) \ printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ } while (0) -#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG -#define vdbg_printk(a_dbg_level, format, arg...) \ - dbg_printk(a_dbg_level, format, ## arg) #else -#define vdbg_printk(a_dbg_level, format, arg...) +#define vdbg_printk(a_dbg_level, format, arg...) \ + do { } while (0) #endif /* Device controlling the backlight and associated keys */ @@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_driver = { } }; -static void dmi_check_cb_common(const struct dmi_system_id *id) +static void __init dmi_check_cb_common(const struct dmi_system_id *id) { pr_info("Identified laptop model '%s'\n", id->ident); if (use_alt_lcd_levels == -1) { @@ -578,7 +577,7 @@ static void dmi_check_cb_common(const struct dmi_system_id *id) } } -static int dmi_check_cb_s6410(const struct dmi_system_id *id) +static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ @@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) return 1; } -static int dmi_check_cb_s6420(const struct dmi_system_id *id) +static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ @@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id) return 1; } -static int dmi_check_cb_p8010(const struct dmi_system_id *id) +static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_HELP; /* "Support" */ @@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) return 1; } -static struct dmi_system_id fujitsu_dmi_table[] = { +static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { { .ident = "Fujitsu Siemens S6410", .matches = { @@ -1051,6 +1050,13 @@ static struct acpi_driver acpi_fujitsu_hotkey_driver = { }, }; +static const struct acpi_device_id fujitsu_ids[] __used = { + {ACPI_FUJITSU_HID, 0}, + {ACPI_FUJITSU_HOTKEY_HID, 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, fujitsu_ids); + static int __init fujitsu_init(void) { int ret, result, max_brightness; @@ -1209,12 +1215,3 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*"); MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); - -static struct pnp_device_id pnp_ids[] __used = { - {.id = "FUJ02bf"}, - {.id = "FUJ02B1"}, - {.id = "FUJ02E3"}, - {.id = ""} -}; - -MODULE_DEVICE_TABLE(pnp, pnp_ids); diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index c3784baceae3..53bdbb01bd3f 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void fujitsu_dmi_common(const struct dmi_system_id *dmi) +static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) { pr_info("%s\n", dmi->ident); memcpy(fujitsu.config.keymap, dmi->driver_data, sizeof(fujitsu.config.keymap)); } -static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) +static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) { fujitsu_dmi_common(dmi); fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } -static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) +static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) { fujitsu_dmi_common(dmi); fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 484a8673b835..4c559640dcba 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void) return (state & 0x4) ? 1 : 0; } -static int hp_wmi_bios_2009_later(void) +static int __init hp_wmi_bios_2009_later(void) { int state = 0; int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, @@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_postcode); } -static int hp_wmi_rfkill_setup(struct platform_device *device) +static int __init hp_wmi_rfkill_setup(struct platform_device *device) { int err; int wireless = 0; @@ -806,7 +806,7 @@ register_wifi_error: return err; } -static int hp_wmi_rfkill2_setup(struct platform_device *device) +static int __init hp_wmi_rfkill2_setup(struct platform_device *device) { int err, i; struct bios_rfkill2_state state; diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 3dc934438c28..6bec745b6b92 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -37,6 +37,8 @@ #include <linux/leds.h> #include <linux/atomic.h> #include <linux/acpi.h> +#include <linux/i8042.h> +#include <linux/serio.h> #include "../../misc/lis3lv02d/lis3lv02d.h" #define DRIVER_NAME "hp_accel" @@ -73,8 +75,15 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, /* HP-specific accelerometer driver ------------------------------------ */ +/* e0 25, e0 26, e0 27, e0 28 are scan codes that the accelerometer with acpi id + * HPQ6000 sends through the keyboard bus */ +#define ACCEL_1 0x25 +#define ACCEL_2 0x26 +#define ACCEL_3 0x27 +#define ACCEL_4 0x28 + /* For automatic insertion of the module */ -static struct acpi_device_id lis3lv02d_device_ids[] = { +static const struct acpi_device_id lis3lv02d_device_ids[] = { {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ @@ -192,7 +201,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3); }, \ .driver_data = &lis3lv02d_axis_##_axis \ } -static struct dmi_system_id lis3lv02d_dmi_ids[] = { +static const struct dmi_system_id lis3lv02d_dmi_ids[] = { /* product names are truncated to match all kinds of a same model */ AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), @@ -294,6 +303,35 @@ static void lis3lv02d_enum_resources(struct acpi_device *device) printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); } +static bool hp_accel_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & I8042_STR_AUXDATA) + return false; + + if (data == 0xe0) { + extended = true; + return true; + } else if (unlikely(extended)) { + extended = false; + + switch (data) { + case ACCEL_1: + case ACCEL_2: + case ACCEL_3: + case ACCEL_4: + return true; + default: + serio_interrupt(port, 0xe0, 0); + return false; + } + } + + return false; +} + static int lis3lv02d_add(struct acpi_device *device) { int ret; @@ -326,6 +364,11 @@ static int lis3lv02d_add(struct acpi_device *device) if (ret) return ret; + /* filter to remove HPQ6000 accelerometer data + * from keyboard bus stream */ + if (strstr(dev_name(&device->dev), "HPQ6000")) + i8042_install_filter(hp_accel_i8042_filter); + INIT_WORK(&hpled_led.work, delayed_set_status_worker); ret = led_classdev_register(NULL, &hpled_led.led_classdev); if (ret) { @@ -343,6 +386,7 @@ static int lis3lv02d_remove(struct acpi_device *device) if (!device) return -EINVAL; + i8042_remove_filter(hp_accel_i8042_filter); lis3lv02d_joystick_disable(&lis3_dev); lis3lv02d_poweroff(&lis3_dev); diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b4c495a62eec..ed494f37c40f 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -87,6 +87,7 @@ struct ideapad_private { struct backlight_device *blightdev; struct dentry *debug; unsigned long cfg; + bool has_hw_rfkill_switch; }; static bool no_bt_rfkill; @@ -439,7 +440,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj, return supported ? attr->mode : 0; } -static struct attribute_group ideapad_attribute_group = { +static const struct attribute_group ideapad_attribute_group = { .is_visible = ideapad_is_visible, .attrs = ideapad_attributes }; @@ -454,7 +455,7 @@ struct ideapad_rfk_data { int type; }; -const struct ideapad_rfk_data ideapad_rfk_data[] = { +static const struct ideapad_rfk_data ideapad_rfk_data[] = { { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, @@ -473,12 +474,14 @@ static struct rfkill_ops ideapad_rfk_ops = { static void ideapad_sync_rfk_state(struct ideapad_private *priv) { - unsigned long hw_blocked; + unsigned long hw_blocked = 0; int i; - if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) - return; - hw_blocked = !hw_blocked; + if (priv->has_hw_rfkill_switch) { + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) + return; + hw_blocked = !hw_blocked; + } for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) if (priv->rfk[i]) @@ -821,14 +824,24 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) } } -/* Blacklist for devices where the ideapad rfkill interface does not work */ -static struct dmi_system_id rfkill_blacklist[] = { - /* The Lenovo Yoga 2 11 always reports everything as blocked */ +/* + * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF + * always results in 0 on these models, causing ideapad_laptop to wrongly + * report all radios as hardware-blocked. + */ +static const struct dmi_system_id no_hw_rfkill_list[] = { { - .ident = "Lenovo Yoga 2 11", + .ident = "Lenovo Yoga 2 11 / 13 / Pro", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), + }, + }, + { + .ident = "Lenovo Yoga 3 Pro 1370", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3 Pro-1370"), }, }, {} @@ -856,6 +869,7 @@ static int ideapad_acpi_add(struct platform_device *pdev) priv->cfg = cfg; priv->adev = adev; priv->platform_device = pdev; + priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); ret = ideapad_sysfs_init(priv); if (ret) @@ -869,11 +883,17 @@ static int ideapad_acpi_add(struct platform_device *pdev) if (ret) goto input_failed; - if (!dmi_check_system(rfkill_blacklist)) { - for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) - ideapad_register_rfkill(priv, i); - } + /* + * On some models without a hw-switch (the yoga 2 13 at least) + * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. + */ + if (!priv->has_hw_rfkill_switch) + write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); + + for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) + if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) + ideapad_register_rfkill(priv, i); + ideapad_sync_rfk_state(priv); ideapad_sync_touchpad_state(priv); diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c index d45bca34bf1b..7344d841f4d9 100644 --- a/drivers/platform/x86/intel-rst.c +++ b/drivers/platform/x86/intel-rst.c @@ -35,7 +35,7 @@ static ssize_t irst_show_wakeup_events(struct device *dev, acpi = to_acpi_device(dev); status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return -EINVAL; return sprintf(buf, "%lld\n", value); @@ -59,7 +59,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev, status = acpi_execute_simple_method(acpi->handle, "SFFS", value); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return -EINVAL; return count; @@ -81,7 +81,7 @@ static ssize_t irst_show_wakeup_time(struct device *dev, acpi = to_acpi_device(dev); status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return -EINVAL; return sprintf(buf, "%lld\n", value); @@ -105,7 +105,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev, status = acpi_execute_simple_method(acpi->handle, "SFTV", value); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return -EINVAL; return count; @@ -119,21 +119,16 @@ static struct device_attribute irst_timeout_attr = { static int irst_add(struct acpi_device *acpi) { - int error = 0; + int error; error = device_create_file(&acpi->dev, &irst_timeout_attr); - if (error) - goto out; + if (unlikely(error)) + return error; error = device_create_file(&acpi->dev, &irst_wakeup_attr); - if (error) - goto out_timeout; + if (unlikely(error)) + device_remove_file(&acpi->dev, &irst_timeout_attr); - return 0; - -out_timeout: - device_remove_file(&acpi->dev, &irst_timeout_attr); -out: return error; } diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 18dcb58ba965..c0242ed13d9e 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -269,7 +269,7 @@ struct ips_mcp_limits { /* Max temps are -10 degrees C to avoid PROCHOT# */ -struct ips_mcp_limits ips_sv_limits = { +static struct ips_mcp_limits ips_sv_limits = { .mcp_power_limit = 35000, .core_power_limit = 29000, .mch_power_limit = 20000, @@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = { .mch_temp_limit = 90 }; -struct ips_mcp_limits ips_lv_limits = { +static struct ips_mcp_limits ips_lv_limits = { .mcp_power_limit = 25000, .core_power_limit = 21000, .mch_power_limit = 13000, @@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = { .mch_temp_limit = 90 }; -struct ips_mcp_limits ips_ulv_limits = { +static struct ips_mcp_limits ips_ulv_limits = { .mcp_power_limit = 18000, .core_power_limit = 14000, .mch_power_limit = 11000, @@ -1478,7 +1478,7 @@ ips_link_to_i915_driver(void) } EXPORT_SYMBOL_GPL(ips_link_to_i915_driver); -static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { +static const struct pci_device_id ips_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, { 0, } diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 40929e4f7ad7..04fed00b88e9 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -301,8 +301,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) return 0; fail_request_irq: - if (gpiochip_remove(&pg->chip)) - pr_err("gpiochip_remove failed\n"); + gpiochip_remove(&pg->chip); err: iounmap(pg->gpiointr); err2: diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 76ca094ed012..66a4d3284aab 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -640,7 +640,7 @@ static void ipc_remove(struct pci_dev *pdev) intel_scu_devices_destroy(); } -static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { +static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index 5a5966512277..ff765d8e1a09 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -1561,6 +1561,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, { .callback = samsung_dmi_matched, + .ident = "NC210", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), + DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), + }, + .driver_data = &samsung_broken_acpi_video, + }, + { + .callback = samsung_dmi_matched, .ident = "730U3E/740U3E", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c index 5413f62d2e61..28d12bda3ac1 100644 --- a/drivers/platform/x86/samsung-q10.c +++ b/drivers/platform/x86/samsung-q10.c @@ -46,13 +46,7 @@ static int samsungq10_bl_set_intensity(struct backlight_device *bd) return 0; } -static int samsungq10_bl_get_intensity(struct backlight_device *bd) -{ - return bd->props.brightness; -} - static const struct backlight_ops samsungq10_bl_ops = { - .get_brightness = samsungq10_bl_get_intensity, .update_status = samsungq10_bl_set_intensity, }; diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9c5a07417b2b..26ad9ff12ac5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd, lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; } for (i = 0; i < LID_RESUME_MAX && - lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { + lid_ctl->attrs[i].attr.name; i++) { result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); if (result) goto liderror; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d82f196e3cfe..cf0f89364d44 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* Extra keys in use since the X240 / T440 / T540 */ - KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, + KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, }, }; @@ -3440,7 +3440,7 @@ err_exit: delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); hotkey_dev_attributes = NULL; - return (res < 0)? res : 1; + return (res < 0) ? res : 1; } /* Thinkpad X1 Carbon support 5 modes including Home mode, Web browser @@ -4576,7 +4576,7 @@ static int __init video_init(struct ibm_init_struct *iibm) str_supported(video_supported != TPACPI_VIDEO_NONE), video_supported); - return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1; + return (video_supported != TPACPI_VIDEO_NONE) ? 0 : 1; } static void video_exit(void) @@ -4669,7 +4669,7 @@ static int video_outputsw_set(int status) return -ENOSYS; } - return (res)? 0 : -EIO; + return (res) ? 0 : -EIO; } static int video_autosw_get(void) @@ -4695,7 +4695,7 @@ static int video_autosw_get(void) static int video_autosw_set(int enable) { - if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0)) + if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable) ? 1 : 0)) return -EIO; return 0; } @@ -4730,20 +4730,20 @@ static int video_outputsw_cycle(void) return -EIO; } - return (res)? 0 : -EIO; + return (res) ? 0 : -EIO; } static int video_expand_toggle(void) { switch (video_supported) { case TPACPI_VIDEO_570: - return acpi_evalf(ec_handle, NULL, "_Q17", "v")? + return acpi_evalf(ec_handle, NULL, "_Q17", "v") ? 0 : -EIO; case TPACPI_VIDEO_770: - return acpi_evalf(vid_handle, NULL, "VEXP", "v")? + return acpi_evalf(vid_handle, NULL, "VEXP", "v") ? 0 : -EIO; case TPACPI_VIDEO_NEW: - return acpi_evalf(NULL, NULL, "\\VEXP", "v")? + return acpi_evalf(NULL, NULL, "\\VEXP", "v") ? 0 : -EIO; default: return -ENOSYS; @@ -4887,14 +4887,14 @@ static int light_set_status(int status) if (tp_features.light) { if (cmos_handle) { rc = acpi_evalf(cmos_handle, NULL, NULL, "vd", - (status)? + (status) ? TP_CMOS_THINKLIGHT_ON : TP_CMOS_THINKLIGHT_OFF); } else { rc = acpi_evalf(lght_handle, NULL, NULL, "vd", - (status)? 1 : 0); + (status) ? 1 : 0); } - return (rc)? 0 : -EIO; + return (rc) ? 0 : -EIO; } return -ENXIO; @@ -4923,7 +4923,7 @@ static void light_sysfs_set(struct led_classdev *led_cdev, static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) { - return (light_get_status() == 1)? LED_FULL : LED_OFF; + return (light_get_status() == 1) ? LED_FULL : LED_OFF; } static struct tpacpi_led_classdev tpacpi_led_thinklight = { @@ -5045,7 +5045,7 @@ static ssize_t cmos_command_store(struct device *dev, return -EINVAL; res = issue_thinkpad_cmos_command(cmos_cmd); - return (res)? res : count; + return (res) ? res : count; } static struct device_attribute dev_attr_cmos_command = @@ -5069,7 +5069,7 @@ static int __init cmos_init(struct ibm_init_struct *iibm) if (res) return res; - return (cmos_handle)? 0 : 1; + return (cmos_handle) ? 0 : 1; } static void cmos_exit(void) @@ -5179,9 +5179,9 @@ static int led_get_status(const unsigned int led) if (!acpi_evalf(ec_handle, &status, "GLED", "dd", 1 << led)) return -EIO; - led_s = (status == 0)? + led_s = (status == 0) ? TPACPI_LED_OFF : - ((status == 1)? + ((status == 1) ? TPACPI_LED_ON : TPACPI_LED_BLINK); tpacpi_led_state_cache[led] = led_s; @@ -5578,7 +5578,7 @@ static int __init beep_init(struct ibm_init_struct *iibm) tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1); - return (beep_handle)? 0 : 1; + return (beep_handle) ? 0 : 1; } static int beep_read(struct seq_file *m) @@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int value) { int res; - if (value > bright_maxlvl || value < 0) + if (value > bright_maxlvl) return -EINVAL; vdbg_printk(TPACPI_DBG_BRGHT, @@ -6527,7 +6527,7 @@ static int brightness_write(char *buf) if (!rc && ibm_backlight_device) backlight_force_update(ibm_backlight_device, BACKLIGHT_UPDATE_SYSFS); - return (rc == -EINTR)? -ERESTARTSYS : rc; + return (rc == -EINTR) ? -ERESTARTSYS : rc; } static struct ibm_struct brightness_driver_data = { @@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); } -static struct snd_kcontrol_new volume_alsa_control_vol = { +static struct snd_kcontrol_new volume_alsa_control_vol __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Console Playback Volume", .index = 0, @@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol = { .get = volume_alsa_vol_get, }; -static struct snd_kcontrol_new volume_alsa_control_mute = { +static struct snd_kcontrol_new volume_alsa_control_mute __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Console Playback Switch", .index = 0, @@ -7984,7 +7984,7 @@ static ssize_t fan_pwm1_store(struct device *dev, } mutex_unlock(&fan_mutex); - return (rc)? rc : count; + return (rc) ? rc : count; } static struct device_attribute dev_attr_fan_pwm1 = @@ -8662,7 +8662,7 @@ static const char * __init str_supported(int is_supported) { static char text_unsupported[] __initdata = "not supported"; - return (is_supported)? &text_unsupported[4] : &text_unsupported[0]; + return (is_supported) ? &text_unsupported[4] : &text_unsupported[0]; } #endif /* CONFIG_THINKPAD_ACPI_DEBUG */ @@ -8783,7 +8783,7 @@ err_out: ibm->name, ret); ibm_exit(ibm); - return (ret < 0)? ret : 0; + return (ret < 0) ? ret : 0; } /* Probing */ @@ -8794,7 +8794,7 @@ static bool __pure __init tpacpi_is_fw_digit(const char c) } /* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */ -static bool __pure __init tpacpi_is_valid_fw_id(const char* const s, +static bool __pure __init tpacpi_is_valid_fw_id(const char * const s, const char t) { return s && strlen(s) >= 8 && @@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data( } s = dmi_get_system_info(DMI_PRODUCT_VERSION); - if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) { + if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) { tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; } else { s = dmi_get_system_info(DMI_BIOS_VENDOR); - if (s && !(strnicmp(s, "Lenovo", 6))) { + if (s && !(strncasecmp(s, "Lenovo", 6))) { tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 76441dcbe5ff..ab6151f05420 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -71,7 +71,8 @@ MODULE_LICENSE("GPL"); /* Toshiba ACPI method paths */ #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" -/* Toshiba HCI interface definitions +/* The Toshiba configuration interface is composed of the HCI and the SCI, + * which are defined as follows: * * HCI is Toshiba's "Hardware Control Interface" which is supposed to * be uniform across all their models. Ideally we would just call @@ -84,7 +85,7 @@ MODULE_LICENSE("GPL"); * conceal differences in hardware between different models. */ -#define HCI_WORDS 6 +#define TCI_WORDS 6 /* operations */ #define HCI_SET 0xff00 @@ -95,17 +96,18 @@ MODULE_LICENSE("GPL"); #define SCI_SET 0xf400 /* return codes */ -#define HCI_SUCCESS 0x0000 -#define HCI_FAILURE 0x1000 -#define HCI_NOT_SUPPORTED 0x8000 -#define HCI_EMPTY 0x8c00 -#define HCI_DATA_NOT_AVAILABLE 0x8d20 -#define HCI_NOT_INITIALIZED 0x8d50 -#define SCI_OPEN_CLOSE_OK 0x0044 -#define SCI_ALREADY_OPEN 0x8100 -#define SCI_NOT_OPENED 0x8200 -#define SCI_INPUT_DATA_ERROR 0x8300 -#define SCI_NOT_PRESENT 0x8600 +#define TOS_SUCCESS 0x0000 +#define TOS_OPEN_CLOSE_OK 0x0044 +#define TOS_FAILURE 0x1000 +#define TOS_NOT_SUPPORTED 0x8000 +#define TOS_ALREADY_OPEN 0x8100 +#define TOS_NOT_OPENED 0x8200 +#define TOS_INPUT_DATA_ERROR 0x8300 +#define TOS_WRITE_PROTECTED 0x8400 +#define TOS_NOT_PRESENT 0x8600 +#define TOS_FIFO_EMPTY 0x8c00 +#define TOS_DATA_NOT_AVAILABLE 0x8d20 +#define TOS_NOT_INITIALIZED 0x8d50 /* registers */ #define HCI_FAN 0x0004 @@ -138,8 +140,12 @@ MODULE_LICENSE("GPL"); #define HCI_WIRELESS_BT_PRESENT 0x0f #define HCI_WIRELESS_BT_ATTACH 0x40 #define HCI_WIRELESS_BT_POWER 0x80 +#define SCI_KBD_MODE_MASK 0x1f #define SCI_KBD_MODE_FNZ 0x1 #define SCI_KBD_MODE_AUTO 0x2 +#define SCI_KBD_MODE_ON 0x8 +#define SCI_KBD_MODE_OFF 0x10 +#define SCI_KBD_TIME_MAX 0x3c001a struct toshiba_acpi_dev { struct acpi_device *acpi_dev; @@ -155,6 +161,7 @@ struct toshiba_acpi_dev { int force_fan; int last_key_event; int key_event_valid; + int kbd_type; int kbd_mode; int kbd_time; @@ -190,6 +197,7 @@ static const struct key_entry toshiba_acpi_keymap[] = { { KE_KEY, 0x101, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, { KE_KEY, 0x103, { KEY_ZOOMIN } }, + { KE_KEY, 0x10f, { KEY_TAB } }, { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, { KE_KEY, 0x139, { KEY_ZOOMRESET } }, { KE_KEY, 0x13b, { KEY_COFFEE } }, @@ -210,7 +218,11 @@ static const struct key_entry toshiba_acpi_keymap[] = { { KE_KEY, 0xb32, { KEY_NEXTSONG } }, { KE_KEY, 0xb33, { KEY_PLAYPAUSE } }, { KE_KEY, 0xb5a, { KEY_MEDIA } }, - { KE_IGNORE, 0x1430, { KEY_RESERVED } }, + { KE_IGNORE, 0x1430, { KEY_RESERVED } }, /* Wake from sleep */ + { KE_IGNORE, 0x1501, { KEY_RESERVED } }, /* Output changed */ + { KE_IGNORE, 0x1502, { KEY_RESERVED } }, /* HDMI plugged/unplugged */ + { KE_IGNORE, 0x1ABE, { KEY_RESERVED } }, /* Protection level set */ + { KE_IGNORE, 0x1ABF, { KEY_RESERVED } }, /* Protection level off */ { KE_END, 0 }, }; @@ -222,6 +234,18 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A50-A"), + }, + }, {} }; @@ -229,6 +253,7 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { { KE_KEY, 0x157, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, { KE_KEY, 0x103, { KEY_ZOOMIN } }, + { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, { KE_KEY, 0x139, { KEY_ZOOMRESET } }, { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, @@ -257,22 +282,22 @@ static int write_acpi_int(const char *methodName, int val) return (status == AE_OK) ? 0 : -EIO; } -/* Perform a raw HCI call. Here we don't care about input or output buffer - * format. +/* Perform a raw configuration call. Here we don't care about input or output + * buffer format. */ -static acpi_status hci_raw(struct toshiba_acpi_dev *dev, - const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) +static acpi_status tci_raw(struct toshiba_acpi_dev *dev, + const u32 in[TCI_WORDS], u32 out[TCI_WORDS]) { struct acpi_object_list params; - union acpi_object in_objs[HCI_WORDS]; + union acpi_object in_objs[TCI_WORDS]; struct acpi_buffer results; - union acpi_object out_objs[HCI_WORDS + 1]; + union acpi_object out_objs[TCI_WORDS + 1]; acpi_status status; int i; - params.count = HCI_WORDS; + params.count = TCI_WORDS; params.pointer = in_objs; - for (i = 0; i < HCI_WORDS; ++i) { + for (i = 0; i < TCI_WORDS; ++i) { in_objs[i].type = ACPI_TYPE_INTEGER; in_objs[i].integer.value = in[i]; } @@ -283,7 +308,7 @@ static acpi_status hci_raw(struct toshiba_acpi_dev *dev, status = acpi_evaluate_object(dev->acpi_dev->handle, (char *)dev->method_hci, ¶ms, &results); - if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { + if ((status == AE_OK) && (out_objs->package.count <= TCI_WORDS)) { for (i = 0; i < out_objs->package.count; ++i) { out[i] = out_objs->package.elements[i].integer.value; } @@ -298,47 +323,49 @@ static acpi_status hci_raw(struct toshiba_acpi_dev *dev, * may be useful (such as "not supported"). */ -static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg, - u32 in1, u32 *result) +static u32 hci_write1(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) { - u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); - *result = (status == AE_OK) ? out[0] : HCI_FAILURE; - return status; + u32 in[TCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + + return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE; } -static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg, - u32 *out1, u32 *result) +static u32 hci_read1(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1) { - u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); + u32 in[TCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) + return TOS_FAILURE; + *out1 = out[2]; - *result = (status == AE_OK) ? out[0] : HCI_FAILURE; - return status; + + return out[0]; } -static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg, - u32 in1, u32 in2, u32 *result) +static u32 hci_write2(struct toshiba_acpi_dev *dev, u32 reg, u32 in1, u32 in2) { - u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); - *result = (status == AE_OK) ? out[0] : HCI_FAILURE; - return status; + u32 in[TCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + + return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE; } -static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg, - u32 *out1, u32 *out2, u32 *result) +static u32 hci_read2(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1, u32 *out2) { - u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); + u32 in[TCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) + return TOS_FAILURE; + *out1 = out[2]; *out2 = out[3]; - *result = (status == AE_OK) ? out[0] : HCI_FAILURE; - return status; + + return out[0]; } /* common sci tasks @@ -346,22 +373,22 @@ static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg, static int sci_open(struct toshiba_acpi_dev *dev) { - u32 in[HCI_WORDS] = { SCI_OPEN, 0, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { SCI_OPEN, 0, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { pr_err("ACPI call to open SCI failed\n"); return 0; } - if (out[0] == SCI_OPEN_CLOSE_OK) { + if (out[0] == TOS_OPEN_CLOSE_OK) { return 1; - } else if (out[0] == SCI_ALREADY_OPEN) { + } else if (out[0] == TOS_ALREADY_OPEN) { pr_info("Toshiba SCI already opened\n"); return 1; - } else if (out[0] == SCI_NOT_PRESENT) { + } else if (out[0] == TOS_NOT_PRESENT) { pr_info("Toshiba SCI is not present\n"); } @@ -370,61 +397,62 @@ static int sci_open(struct toshiba_acpi_dev *dev) static void sci_close(struct toshiba_acpi_dev *dev) { - u32 in[HCI_WORDS] = { SCI_CLOSE, 0, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { SCI_CLOSE, 0, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { pr_err("ACPI call to close SCI failed\n"); return; } - if (out[0] == SCI_OPEN_CLOSE_OK) + if (out[0] == TOS_OPEN_CLOSE_OK) return; - else if (out[0] == SCI_NOT_OPENED) + else if (out[0] == TOS_NOT_OPENED) pr_info("Toshiba SCI not opened\n"); - else if (out[0] == SCI_NOT_PRESENT) + else if (out[0] == TOS_NOT_PRESENT) pr_info("Toshiba SCI is not present\n"); } -static acpi_status sci_read(struct toshiba_acpi_dev *dev, u32 reg, - u32 *out1, u32 *result) +static u32 sci_read(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1) { - u32 in[HCI_WORDS] = { SCI_GET, reg, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); + u32 in[TCI_WORDS] = { SCI_GET, reg, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status)) + return TOS_FAILURE; + *out1 = out[2]; - *result = (ACPI_SUCCESS(status)) ? out[0] : HCI_FAILURE; - return status; + + return out[0]; } -static acpi_status sci_write(struct toshiba_acpi_dev *dev, u32 reg, - u32 in1, u32 *result) +static u32 sci_write(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) { - u32 in[HCI_WORDS] = { SCI_SET, reg, in1, 0, 0, 0 }; - u32 out[HCI_WORDS]; - acpi_status status = hci_raw(dev, in, out); - *result = (ACPI_SUCCESS(status)) ? out[0] : HCI_FAILURE; - return status; + u32 in[TCI_WORDS] = { SCI_SET, reg, in1, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status = tci_raw(dev, in, out); + + return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE; } /* Illumination support */ static int toshiba_illumination_available(struct toshiba_acpi_dev *dev) { - u32 in[HCI_WORDS] = { SCI_GET, SCI_ILLUMINATION, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { SCI_GET, SCI_ILLUMINATION, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; if (!sci_open(dev)) return 0; - status = hci_raw(dev, in, out); + status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { + if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { pr_err("ACPI call to query Illumination support failed\n"); return 0; - } else if (out[0] == HCI_NOT_SUPPORTED || out[1] != 1) { + } else if (out[0] == TOS_NOT_SUPPORTED) { pr_info("Illumination device not available\n"); return 0; } @@ -438,7 +466,6 @@ static void toshiba_illumination_set(struct led_classdev *cdev, struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, led_dev); u32 state, result; - acpi_status status; /* First request : initialize communication. */ if (!sci_open(dev)) @@ -446,12 +473,12 @@ static void toshiba_illumination_set(struct led_classdev *cdev, /* Switch the illumination on/off */ state = brightness ? 1 : 0; - status = sci_write(dev, SCI_ILLUMINATION, state, &result); + result = sci_write(dev, SCI_ILLUMINATION, state); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (result == TOS_FAILURE) { pr_err("ACPI call for illumination failed\n"); return; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Illumination not supported\n"); return; } @@ -462,19 +489,18 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, led_dev); u32 state, result; - acpi_status status; /* First request : initialize communication. */ if (!sci_open(dev)) return LED_OFF; /* Check the illumination */ - status = sci_read(dev, SCI_ILLUMINATION, &state, &result); + result = sci_read(dev, SCI_ILLUMINATION, &state); sci_close(dev); - if (ACPI_FAILURE(status) || result == SCI_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call for illumination failed\n"); return LED_OFF; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Illumination not supported\n"); return LED_OFF; } @@ -483,20 +509,55 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) } /* KBD Illumination */ +static int toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev) +{ + u32 in[TCI_WORDS] = { SCI_GET, SCI_KBD_ILLUM_STATUS, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status; + + if (!sci_open(dev)) + return 0; + + status = tci_raw(dev, in, out); + sci_close(dev); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + pr_err("ACPI call to query kbd illumination support failed\n"); + return 0; + } else if (out[0] == TOS_NOT_SUPPORTED) { + pr_info("Keyboard illumination not available\n"); + return 0; + } + + /* Check for keyboard backlight timeout max value, + * previous kbd backlight implementation set this to + * 0x3c0003, and now the new implementation set this + * to 0x3c001a, use this to distinguish between them + */ + if (out[3] == SCI_KBD_TIME_MAX) + dev->kbd_type = 2; + else + dev->kbd_type = 1; + /* Get the current keyboard backlight mode */ + dev->kbd_mode = out[2] & SCI_KBD_MODE_MASK; + /* Get the current time (1-60 seconds) */ + dev->kbd_time = out[2] >> HCI_MISC_SHIFT; + + return 1; +} + static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) { u32 result; - acpi_status status; if (!sci_open(dev)) return -EIO; - status = sci_write(dev, SCI_KBD_ILLUM_STATUS, time, &result); + result = sci_write(dev, SCI_KBD_ILLUM_STATUS, time); sci_close(dev); - if (ACPI_FAILURE(status) || result == SCI_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to set KBD backlight status failed\n"); return -EIO; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Keyboard backlight status not supported\n"); return -ENODEV; } @@ -507,17 +568,16 @@ static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time) { u32 result; - acpi_status status; if (!sci_open(dev)) return -EIO; - status = sci_read(dev, SCI_KBD_ILLUM_STATUS, time, &result); + result = sci_read(dev, SCI_KBD_ILLUM_STATUS, time); sci_close(dev); - if (ACPI_FAILURE(status) || result == SCI_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get KBD backlight status failed\n"); return -EIO; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Keyboard backlight status not supported\n"); return -ENODEV; } @@ -530,14 +590,13 @@ static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev) struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, kbd_led); u32 state, result; - acpi_status status; /* Check the keyboard backlight state */ - status = hci_read1(dev, HCI_KBD_ILLUMINATION, &state, &result); - if (ACPI_FAILURE(status) || result == SCI_INPUT_DATA_ERROR) { + result = hci_read1(dev, HCI_KBD_ILLUMINATION, &state); + if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get the keyboard backlight failed\n"); return LED_OFF; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Keyboard backlight not supported\n"); return LED_OFF; } @@ -551,15 +610,14 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, kbd_led); u32 state, result; - acpi_status status; /* Set the keyboard backlight state */ state = brightness ? 1 : 0; - status = hci_write1(dev, HCI_KBD_ILLUMINATION, state, &result); - if (ACPI_FAILURE(status) || result == SCI_INPUT_DATA_ERROR) { + result = hci_write1(dev, HCI_KBD_ILLUMINATION, state); + if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to set KBD Illumination mode failed\n"); return; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { pr_info("Keyboard backlight not supported\n"); return; } @@ -569,17 +627,16 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state) { u32 result; - acpi_status status; if (!sci_open(dev)) return -EIO; - status = sci_write(dev, SCI_TOUCHPAD, state, &result); + result = sci_write(dev, SCI_TOUCHPAD, state); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (result == TOS_FAILURE) { pr_err("ACPI call to set the touchpad failed\n"); return -EIO; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { return -ENODEV; } @@ -589,17 +646,16 @@ static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state) static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) { u32 result; - acpi_status status; if (!sci_open(dev)) return -EIO; - status = sci_read(dev, SCI_TOUCHPAD, state, &result); + result = sci_read(dev, SCI_TOUCHPAD, state); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (result == TOS_FAILURE) { pr_err("ACPI call to query the touchpad failed\n"); return -EIO; - } else if (result == HCI_NOT_SUPPORTED) { + } else if (result == TOS_NOT_SUPPORTED) { return -ENODEV; } @@ -610,11 +666,11 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) { acpi_status status; - u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; + u32 out[TCI_WORDS]; - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_info("ACPI call to get ECO led failed\n"); return 0; } @@ -626,12 +682,12 @@ static enum led_brightness toshiba_eco_mode_get_status(struct led_classdev *cdev { struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, eco_led); - u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get ECO led failed\n"); return LED_OFF; } @@ -644,14 +700,14 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev, { struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, eco_led); - u32 in[HCI_WORDS] = { HCI_SET, HCI_ECO_MODE, 0, 1, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { HCI_SET, HCI_ECO_MODE, 0, 1, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; /* Switch the Eco Mode led on/off */ in[2] = (brightness) ? 1 : 0; - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to set ECO led failed\n"); return; } @@ -660,22 +716,22 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev, /* Accelerometer support */ static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev) { - u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; /* Check if the accelerometer call exists, * this call also serves as initialization */ - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to query the accelerometer failed\n"); return -EIO; - } else if (out[0] == HCI_DATA_NOT_AVAILABLE || - out[0] == HCI_NOT_INITIALIZED) { + } else if (out[0] == TOS_DATA_NOT_AVAILABLE || + out[0] == TOS_NOT_INITIALIZED) { pr_err("Accelerometer not initialized\n"); return -EIO; - } else if (out[0] == HCI_NOT_SUPPORTED) { + } else if (out[0] == TOS_NOT_SUPPORTED) { pr_info("Accelerometer not supported\n"); return -ENODEV; } @@ -686,13 +742,13 @@ static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev) static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, u32 *xy, u32 *z) { - u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 }; - u32 out[HCI_WORDS]; + u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 }; + u32 out[TCI_WORDS]; acpi_status status; /* Check the Accelerometer status */ - status = hci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to query the accelerometer failed\n"); return -EIO; } @@ -712,8 +768,8 @@ static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) value = 0; value2 = 0; - hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result); - if (hci_result == HCI_SUCCESS) + hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2); + if (hci_result == TOS_SUCCESS) *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false; return hci_result; @@ -726,7 +782,7 @@ static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state) value = 0; value2 = 0x0001; - hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result); + hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2); *radio_state = value & HCI_WIRELESS_KILL_SWITCH; return hci_result; @@ -743,7 +799,7 @@ static int bt_rfkill_set_block(void *data, bool blocked) value = (blocked == false); mutex_lock(&dev->mutex); - if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) { + if (hci_get_radio_state(dev, &radio_state) != TOS_SUCCESS) { err = -EIO; goto out; } @@ -753,10 +809,10 @@ static int bt_rfkill_set_block(void *data, bool blocked) goto out; } - hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); - hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); + result1 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER); + result2 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH); - if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) + if (result1 != TOS_SUCCESS || result2 != TOS_SUCCESS) err = -EIO; else err = 0; @@ -775,7 +831,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data) mutex_lock(&dev->mutex); hci_result = hci_get_radio_state(dev, &value); - if (hci_result != HCI_SUCCESS) { + if (hci_result != TOS_SUCCESS) { /* Can't do anything useful */ mutex_unlock(&dev->mutex); return; @@ -799,9 +855,9 @@ static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled) u32 hci_result; u32 status; - hci_read1(dev, HCI_TR_BACKLIGHT, &status, &hci_result); + hci_result = hci_read1(dev, HCI_TR_BACKLIGHT, &status); *enabled = !status; - return hci_result == HCI_SUCCESS ? 0 : -EIO; + return hci_result == TOS_SUCCESS ? 0 : -EIO; } static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable) @@ -809,8 +865,8 @@ static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable) u32 hci_result; u32 value = !enable; - hci_write1(dev, HCI_TR_BACKLIGHT, value, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; + hci_result = hci_write1(dev, HCI_TR_BACKLIGHT, value); + return hci_result == TOS_SUCCESS ? 0 : -EIO; } static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; @@ -831,8 +887,8 @@ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) brightness++; } - hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result); - if (hci_result == HCI_SUCCESS) + hci_result = hci_read1(dev, HCI_LCD_BRIGHTNESS, &value); + if (hci_result == TOS_SUCCESS) return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT); return -EIO; @@ -872,7 +928,9 @@ static int lcd_proc_open(struct inode *inode, struct file *file) static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) { - u32 hci_result; + u32 in[TCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; + u32 out[TCI_WORDS]; + acpi_status status; if (dev->tr_backlight_supported) { bool enable = !value; @@ -883,9 +941,20 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) value--; } - value = value << HCI_LCD_BRIGHTNESS_SHIFT; - hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; + in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; + status = tci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { + pr_err("ACPI call to set brightness failed"); + return -EIO; + } + /* Extra check for "incomplete" backlight method, where the AML code + * doesn't check for HCI_SET or HCI_GET and returns TOS_SUCCESS, + * the actual brightness, and in some cases the max brightness. + */ + if (out[2] > 0 || out[3] == 0xE000) + return -ENODEV; + + return out[0] == TOS_SUCCESS ? 0 : -EIO; } static int set_lcd_status(struct backlight_device *bd) @@ -933,8 +1002,8 @@ static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status) { u32 hci_result; - hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; + hci_result = hci_read1(dev, HCI_VIDEO_OUT, status); + return hci_result == TOS_SUCCESS ? 0 : -EIO; } static int video_proc_show(struct seq_file *m, void *v) @@ -1037,8 +1106,8 @@ static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) { u32 hci_result; - hci_read1(dev, HCI_FAN, status, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; + hci_result = hci_read1(dev, HCI_FAN, status); + return hci_result == TOS_SUCCESS ? 0 : -EIO; } static int fan_proc_show(struct seq_file *m, void *v) @@ -1077,8 +1146,8 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf, if (sscanf(cmd, " force_on : %i", &value) == 1 && value >= 0 && value <= 1) { - hci_write1(dev, HCI_FAN, value, &hci_result); - if (hci_result != HCI_SUCCESS) + hci_result = hci_write1(dev, HCI_FAN, value); + if (hci_result != TOS_SUCCESS) return -EIO; else dev->force_fan = value; @@ -1105,17 +1174,17 @@ static int keys_proc_show(struct seq_file *m, void *v) u32 value; if (!dev->key_event_valid && dev->system_event_supported) { - hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); - if (hci_result == HCI_SUCCESS) { + hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value); + if (hci_result == TOS_SUCCESS) { dev->key_event_valid = 1; dev->last_key_event = value; - } else if (hci_result == HCI_EMPTY) { + } else if (hci_result == TOS_FIFO_EMPTY) { /* better luck next time */ - } else if (hci_result == HCI_NOT_SUPPORTED) { + } else if (hci_result == TOS_NOT_SUPPORTED) { /* This is a workaround for an unresolved issue on * some machines where system events sporadically * become disabled. */ - hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); + hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1); pr_notice("Re-enabled hotkeys\n"); } else { pr_err("Error reading hotkey status\n"); @@ -1229,28 +1298,120 @@ static const struct backlight_ops toshiba_backlight_data = { /* * Sysfs files */ +static ssize_t toshiba_kbd_bl_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static ssize_t toshiba_kbd_bl_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t toshiba_kbd_type_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t toshiba_available_kbd_modes_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t toshiba_touchpad_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static ssize_t toshiba_touchpad_show(struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t toshiba_position_show(struct device *dev, + struct device_attribute *attr, + char *buf); + +static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR, + toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store); +static DEVICE_ATTR(kbd_type, S_IRUGO, toshiba_kbd_type_show, NULL); +static DEVICE_ATTR(available_kbd_modes, S_IRUGO, + toshiba_available_kbd_modes_show, NULL); +static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR, + toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store); +static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR, + toshiba_touchpad_show, toshiba_touchpad_store); +static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL); + +static struct attribute *toshiba_attributes[] = { + &dev_attr_kbd_backlight_mode.attr, + &dev_attr_kbd_type.attr, + &dev_attr_available_kbd_modes.attr, + &dev_attr_kbd_backlight_timeout.attr, + &dev_attr_touchpad.attr, + &dev_attr_position.attr, + NULL, +}; + +static umode_t toshiba_sysfs_is_visible(struct kobject *, + struct attribute *, int); + +static struct attribute_group toshiba_attr_group = { + .is_visible = toshiba_sysfs_is_visible, + .attrs = toshiba_attributes, +}; static ssize_t toshiba_kbd_bl_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); - int mode = -1; - int time = -1; + int mode; + int time; + int ret; - if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1)) - return -EINVAL; + + ret = kstrtoint(buf, 0, &mode); + if (ret) + return ret; + + /* Check for supported modes depending on keyboard backlight type */ + if (toshiba->kbd_type == 1) { + /* Type 1 supports SCI_KBD_MODE_FNZ and SCI_KBD_MODE_AUTO */ + if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO) + return -EINVAL; + } else if (toshiba->kbd_type == 2) { + /* Type 2 doesn't support SCI_KBD_MODE_FNZ */ + if (mode != SCI_KBD_MODE_AUTO && mode != SCI_KBD_MODE_ON && + mode != SCI_KBD_MODE_OFF) + return -EINVAL; + } /* Set the Keyboard Backlight Mode where: - * Mode - Auto (2) | FN-Z (1) * Auto - KBD backlight turns off automatically in given time * FN-Z - KBD backlight "toggles" when hotkey pressed + * ON - KBD backlight is always on + * OFF - KBD backlight is always off */ - if (mode != -1 && toshiba->kbd_mode != mode) { + + /* Only make a change if the actual mode has changed */ + if (toshiba->kbd_mode != mode) { + /* Shift the time to "base time" (0x3c0000 == 60 seconds) */ time = toshiba->kbd_time << HCI_MISC_SHIFT; - time = time + toshiba->kbd_mode; - if (toshiba_kbd_illum_status_set(toshiba, time) < 0) - return -EIO; + + /* OR the "base time" to the actual method format */ + if (toshiba->kbd_type == 1) { + /* Type 1 requires the current mode */ + time |= toshiba->kbd_mode; + } else if (toshiba->kbd_type == 2) { + /* Type 2 requires the desired mode */ + time |= mode; + } + + ret = toshiba_kbd_illum_status_set(toshiba, time); + if (ret) + return ret; + + /* Update sysfs entries on successful mode change*/ + ret = sysfs_update_group(&toshiba->acpi_dev->dev.kobj, + &toshiba_attr_group); + if (ret) + return ret; + toshiba->kbd_mode = mode; } @@ -1267,7 +1428,30 @@ static ssize_t toshiba_kbd_bl_mode_show(struct device *dev, if (toshiba_kbd_illum_status_get(toshiba, &time) < 0) return -EIO; - return sprintf(buf, "%i\n", time & 0x07); + return sprintf(buf, "%i\n", time & SCI_KBD_MODE_MASK); +} + +static ssize_t toshiba_kbd_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", toshiba->kbd_type); +} + +static ssize_t toshiba_available_kbd_modes_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); + + if (toshiba->kbd_type == 1) + return sprintf(buf, "%x %x\n", + SCI_KBD_MODE_FNZ, SCI_KBD_MODE_AUTO); + + return sprintf(buf, "%x %x %x\n", + SCI_KBD_MODE_AUTO, SCI_KBD_MODE_ON, SCI_KBD_MODE_OFF); } static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev, @@ -1275,18 +1459,38 @@ static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev, const char *buf, size_t count) { struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); - int time = -1; + int time; + int ret; - if (sscanf(buf, "%i", &time) != 1 && (time < 0 || time > 60)) - return -EINVAL; + ret = kstrtoint(buf, 0, &time); + if (ret) + return ret; + + /* Check for supported values depending on kbd_type */ + if (toshiba->kbd_type == 1) { + if (time < 0 || time > 60) + return -EINVAL; + } else if (toshiba->kbd_type == 2) { + if (time < 1 || time > 60) + return -EINVAL; + } + + /* Set the Keyboard Backlight Timeout */ - /* Set the Keyboard Backlight Timeout: 0-60 seconds */ - if (time != -1 && toshiba->kbd_time != time) { + /* Only make a change if the actual timeout has changed */ + if (toshiba->kbd_time != time) { + /* Shift the time to "base time" (0x3c0000 == 60 seconds) */ time = time << HCI_MISC_SHIFT; - time = (toshiba->kbd_mode == SCI_KBD_MODE_AUTO) ? - time + 1 : time + 2; - if (toshiba_kbd_illum_status_set(toshiba, time) < 0) - return -EIO; + /* OR the "base time" to the actual method format */ + if (toshiba->kbd_type == 1) + time |= SCI_KBD_MODE_FNZ; + else if (toshiba->kbd_type == 2) + time |= SCI_KBD_MODE_AUTO; + + ret = toshiba_kbd_illum_status_set(toshiba, time); + if (ret) + return ret; + toshiba->kbd_time = time >> HCI_MISC_SHIFT; } @@ -1312,12 +1516,18 @@ static ssize_t toshiba_touchpad_store(struct device *dev, { struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); int state; + int ret; /* Set the TouchPad on/off, 0 - Disable | 1 - Enable */ - if (sscanf(buf, "%i", &state) == 1 && (state == 0 || state == 1)) { - if (toshiba_touchpad_set(toshiba, state) < 0) - return -EIO; - } + ret = kstrtoint(buf, 0, &state); + if (ret) + return ret; + if (state != 0 && state != 1) + return -EINVAL; + + ret = toshiba_touchpad_set(toshiba, state); + if (ret) + return ret; return count; } @@ -1357,22 +1567,6 @@ static ssize_t toshiba_position_show(struct device *dev, return sprintf(buf, "%d %d %d\n", x, y, z); } -static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR, - toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store); -static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR, - toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store); -static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR, - toshiba_touchpad_show, toshiba_touchpad_store); -static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL); - -static struct attribute *toshiba_attributes[] = { - &dev_attr_kbd_backlight_mode.attr, - &dev_attr_kbd_backlight_timeout.attr, - &dev_attr_touchpad.attr, - &dev_attr_position.attr, - NULL, -}; - static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, struct attribute *attr, int idx) { @@ -1392,11 +1586,6 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, return exists ? attr->mode : 0; } -static struct attribute_group toshiba_attr_group = { - .is_visible = toshiba_sysfs_is_visible, - .attrs = toshiba_attributes, -}; - static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, struct serio *port) { @@ -1509,8 +1698,8 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) if (acpi_has_method(dev->acpi_dev->handle, "INFO")) dev->info_supported = 1; else { - hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); - if (hci_result == HCI_SUCCESS) + hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1); + if (hci_result == TOS_SUCCESS) dev->system_event_supported = 1; } @@ -1532,7 +1721,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) goto err_remove_filter; } - hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &hci_result); + hci_result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE); return 0; err_remove_filter: @@ -1690,7 +1879,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) goto error; /* Register rfkill switch for Bluetooth */ - if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) { + if (hci_get_bt_present(dev, &bt_present) == TOS_SUCCESS && bt_present) { dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth", &acpi_dev->dev, RFKILL_TYPE_BLUETOOTH, @@ -1728,12 +1917,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) dev->eco_supported = 1; } - ret = toshiba_kbd_illum_status_get(dev, &dummy); - if (!ret) { - dev->kbd_time = dummy >> HCI_MISC_SHIFT; - dev->kbd_mode = dummy & 0x07; - } - dev->kbd_illum_supported = !ret; + dev->kbd_illum_supported = toshiba_kbd_illum_available(dev); /* * Only register the LED if KBD illumination is supported * and the keyboard backlight operation mode is set to FN-Z @@ -1798,26 +1982,26 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) toshiba_acpi_report_hotkey(dev, scancode); } else if (dev->system_event_supported) { do { - hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); + hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value); switch (hci_result) { - case HCI_SUCCESS: + case TOS_SUCCESS: toshiba_acpi_report_hotkey(dev, (int)value); break; - case HCI_NOT_SUPPORTED: + case TOS_NOT_SUPPORTED: /* * This is a workaround for an unresolved * issue on some machines where system events * sporadically become disabled. */ - hci_write1(dev, HCI_SYSTEM_EVENT, 1, - &hci_result); + hci_result = + hci_write1(dev, HCI_SYSTEM_EVENT, 1); pr_notice("Re-enabled hotkeys\n"); /* fall through */ default: retries--; break; } - } while (retries && hci_result != HCI_EMPTY); + } while (retries && hci_result != TOS_FIFO_EMPTY); } } @@ -1828,7 +2012,7 @@ static int toshiba_acpi_suspend(struct device *device) u32 result; if (dev->hotkey_dev) - hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE, &result); + result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE); return 0; } @@ -1837,9 +2021,16 @@ static int toshiba_acpi_resume(struct device *device) { struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); u32 result; + acpi_status status; - if (dev->hotkey_dev) - hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result); + if (dev->hotkey_dev) { + status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", + NULL, NULL); + if (ACPI_FAILURE(status)) + pr_info("Unable to re-enable hotkeys\n"); + + result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE); + } return 0; } diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c new file mode 100644 index 000000000000..65300b6a84b9 --- /dev/null +++ b/drivers/platform/x86/toshiba_haps.c @@ -0,0 +1,265 @@ +/* + * Toshiba HDD Active Protection Sensor (HAPS) driver + * + * Copyright (C) 2014 Azael Avalos <coproscefalo@gmail.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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/acpi.h> + +MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>"); +MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor"); +MODULE_LICENSE("GPL"); + +struct toshiba_haps_dev { + struct acpi_device *acpi_dev; + + int protection_level; +}; + +static struct toshiba_haps_dev *toshiba_haps; + +/* HAPS functions */ +static int toshiba_haps_reset_protection(acpi_handle handle) +{ + acpi_status status; + + status = acpi_evaluate_object(handle, "RSSS", NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_err("Unable to reset the HDD protection\n"); + return -EIO; + } + + return 0; +} + +static int toshiba_haps_protection_level(acpi_handle handle, int level) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "PTLV", level); + if (ACPI_FAILURE(status)) { + pr_err("Error while setting the protection level\n"); + return -EIO; + } + + pr_info("HDD protection level set to: %d\n", level); + + return 0; +} + +/* sysfs files */ +static ssize_t protection_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + + return sprintf(buf, "%i\n", haps->protection_level); +} + +static ssize_t protection_level_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + int level, ret; + + if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3) + return -EINVAL; + + /* Set the sensor level. + * Acceptable levels are: + * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High + */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level); + if (ret != 0) + return ret; + + haps->protection_level = level; + + return count; +} + +static ssize_t reset_protection_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + int reset, ret; + + if (sscanf(buf, "%d", &reset) != 1 || reset != 1) + return -EINVAL; + + /* Reset the protection interface */ + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); + if (ret != 0) + return ret; + + return count; +} + +static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR, + protection_level_show, protection_level_store); +static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store); + +static struct attribute *haps_attributes[] = { + &dev_attr_protection_level.attr, + &dev_attr_reset_protection.attr, + NULL, +}; + +static struct attribute_group haps_attr_group = { + .attrs = haps_attributes, +}; + +/* + * ACPI stuff + */ +static void toshiba_haps_notify(struct acpi_device *device, u32 event) +{ + pr_info("Received event: 0x%x", event); + + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), + event, 0); +} + +static int toshiba_haps_remove(struct acpi_device *device) +{ + sysfs_remove_group(&device->dev.kobj, &haps_attr_group); + + if (toshiba_haps) + toshiba_haps = NULL; + + return 0; +} + +/* Helper function */ +static int toshiba_haps_available(acpi_handle handle) +{ + acpi_status status; + u64 hdd_present; + + /* + * A non existent device as well as having (only) + * Solid State Drives can cause the call to fail. + */ + status = acpi_evaluate_integer(handle, "_STA", NULL, + &hdd_present); + if (ACPI_FAILURE(status) || !hdd_present) { + pr_info("HDD protection not available or using SSD\n"); + return 0; + } + + return 1; +} + +static int toshiba_haps_add(struct acpi_device *acpi_dev) +{ + struct toshiba_haps_dev *haps; + int ret; + + if (toshiba_haps) + return -EBUSY; + + if (!toshiba_haps_available(acpi_dev->handle)) + return -ENODEV; + + pr_info("Toshiba HDD Active Protection Sensor device\n"); + + haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); + if (!haps) + return -ENOMEM; + + haps->acpi_dev = acpi_dev; + haps->protection_level = 2; + acpi_dev->driver_data = haps; + dev_set_drvdata(&acpi_dev->dev, haps); + + /* Set the protection level, currently at level 2 (Medium) */ + ret = toshiba_haps_protection_level(acpi_dev->handle, 2); + if (ret != 0) + return ret; + + ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group); + if (ret) + return ret; + + toshiba_haps = haps; + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int toshiba_haps_suspend(struct device *device) +{ + struct toshiba_haps_dev *haps; + int ret; + + haps = acpi_driver_data(to_acpi_device(device)); + + /* Deactivate the protection on suspend */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0); + + return ret; +} + +static int toshiba_haps_resume(struct device *device) +{ + struct toshiba_haps_dev *haps; + int ret; + + haps = acpi_driver_data(to_acpi_device(device)); + + /* Set the stored protection level */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, + haps->protection_level); + + /* Reset the protection on resume */ + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); + if (ret != 0) + return ret; + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(toshiba_haps_pm, + toshiba_haps_suspend, toshiba_haps_resume); + +static const struct acpi_device_id haps_device_ids[] = { + {"TOS620A", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, haps_device_ids); + +static struct acpi_driver toshiba_haps_driver = { + .name = "Toshiba HAPS", + .owner = THIS_MODULE, + .ids = haps_device_ids, + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, + .ops = { + .add = toshiba_haps_add, + .remove = toshiba_haps_remove, + .notify = toshiba_haps_notify, + }, + .drv.pm = &toshiba_haps_pm, +}; + +module_acpi_driver(toshiba_haps_driver); diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 43d13295e63d..737e56d46f61 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) block = &wblock->gblock; handle = wblock->handle; - if (!block) - return AE_NOT_EXIST; - - snprintf(method, 5, "WE%02X", block->notify_id); status = acpi_execute_simple_method(handle, method, enable); |