Commit f3b5020e authored by Linus Torvalds's avatar Linus Torvalds

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

Pull x86 platform driver updates from Darren Hart:
 "Several incremental improvements including new keycodes, new models,
  new quirks, and related documentation. Adds LED platform driver
  activation for Mellanox systems. Some minor optimizations and
  cleanups. Includes several bug fixes, message silencing, mostly minor

  Automated summary:

  acer-wmi:
   -  add another KEY_POWER keycode

  apple-gmux:
   -  fix gmux_get_client_id()'s return type

  asus-laptop:
   -  Simplify getting .drvdata

  asus-wireless:
   -  Fix format specifier

  dell-laptop:
   -  Fix keyboard backlight timeout on XPS 13 9370

  dell-smbios:
   -  Match on www.dell.com in OEM strings too

  dell-wmi:
   -  Ignore new rfkill and fn-lock events
   -  Set correct keycode for Fn + left arrow

  fujitsu-laptop:
   -  Simplify soft key handling

  ideapad-laptop:
   -  Add E42-80 to no_hw_rfkill
   -  Add fn-lock setting
   -  Add MIIX 720-12IKB to no_hw_rfkill

  lib/string_helpers:
   -  Add missed declaration of struct task_struct

  intel_scu_ipc:
   -  Replace mdelay with usleep_range in intel_scu_ipc_i2c_cntrl

  mlx-platform:
   -  Add LED platform driver activation

  platform/mellanox:
   -  Add new ODM system types to mlx-platform
   -  mlxreg-hotplug: add extra cycle for hotplug work queue
   -  mlxreg-hotplug: Document fixes for hotplug private data

  platform_data/mlxreg:
   -  Document fixes for hotplug device

  silead_dmi:
   -  Add entry for Chuwi Hi8 tablet touchscreen
   -  Add touchscreen info for the Onda V891w tablet
   -  Add info for the PoV mobii TAB-P800W (v2.0)
   -  Add touchscreen info for the Jumper EZpad 6 Pro

  thinkpad_acpi:
   -  silence false-positive-prone pr_warn
   -  do not report thermal sensor state for tablet mode switch
   -  silence HKEY 0x6032, 0x60f0, 0x6030"

* tag 'platform-drivers-x86-v4.18-1' of git://git.infradead.org/linux-platform-drivers-x86: (30 commits)
  platform/x86: silead_dmi: Add entry for Chuwi Hi8 tablet touchscreen
  platform/x86: dell-laptop: Fix keyboard backlight timeout on XPS 13 9370
  platform/x86: dell-wmi: Ignore new rfkill and fn-lock events
  platform/x86: mlx-platform: Add LED platform driver activation
  platform/mellanox: Add new ODM system types to mlx-platform
  platform/mellanox: mlxreg-hotplug: add extra cycle for hotplug work queue
  platform/x86: ideapad-laptop: Add E42-80 to no_hw_rfkill
  platform/x86: silead_dmi: Add touchscreen info for the Onda V891w tablet
  platform/x86: silead_dmi: Add info for the PoV mobii TAB-P800W (v2.0)
  platform/x86: silead_dmi: Add touchscreen info for the Jumper EZpad 6 Pro
  platform/x86: asus-wireless: Fix format specifier
  platform/x86: asus-wmi: Fix NULL pointer dereference
  platform/x86: dell-wmi: Set correct keycode for Fn + left arrow
  platform/x86: acer-wmi: add another KEY_POWER keycode
  platform/x86: ideapad-laptop: Add fn-lock setting
  platform/x86: ideapad-laptop: Add MIIX 720-12IKB to no_hw_rfkill
  lib/string_helpers: Add missed declaration of struct task_struct
  platform/x86: DELL_WMI use depends on instead of select for DELL_SMBIOS
  platform/mellanox: mlxreg-hotplug: Document fixes for hotplug private data
  platform_data/mlxreg: Document fixes for hotplug device
  ...
parents 4b4bb99b 26ed9d1c
...@@ -25,3 +25,16 @@ Description: ...@@ -25,3 +25,16 @@ Description:
Control touchpad mode. Control touchpad mode.
* 1 -> Switched On * 1 -> Switched On
* 0 -> Switched Off * 0 -> Switched Off
What: /sys/bus/pci/devices/<bdf>/<device>/VPC2004:00/fn_lock
Date: May 2018
KernelVersion: 4.18
Contact: "Oleg Keri <ezhi99@gmail.com>"
Description:
Control fn-lock mode.
* 1 -> Switched On
* 0 -> Switched Off
For example:
# echo "0" > \
/sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock
...@@ -540,8 +540,10 @@ Events that are propagated by the driver to userspace: ...@@ -540,8 +540,10 @@ Events that are propagated by the driver to userspace:
0x6021 ALARM: a sensor is too hot 0x6021 ALARM: a sensor is too hot
0x6022 ALARM: a sensor is extremely hot 0x6022 ALARM: a sensor is extremely hot
0x6030 System thermal table changed 0x6030 System thermal table changed
0x6032 Thermal Control command set completion (DYTC, Windows)
0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED) 0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED)
0x60C0 X1 Yoga 2016, Tablet mode status changed 0x60C0 X1 Yoga 2016, Tablet mode status changed
0x60F0 Thermal Transformation changed (GMTS, Windows)
Battery nearly empty alarms are a last resort attempt to get the Battery nearly empty alarms are a last resort attempt to get the
operating system to hibernate or shutdown cleanly (0x2313), or shutdown operating system to hibernate or shutdown cleanly (0x2313), or shutdown
......
...@@ -55,13 +55,16 @@ ...@@ -55,13 +55,16 @@
#define MLXREG_HOTPLUG_RST_CNTR 3 #define MLXREG_HOTPLUG_RST_CNTR 3
#define MLXREG_HOTPLUG_ATTRS_MAX 24 #define MLXREG_HOTPLUG_ATTRS_MAX 24
#define MLXREG_HOTPLUG_NOT_ASSERT 3
/** /**
* struct mlxreg_hotplug_priv_data - platform private data: * struct mlxreg_hotplug_priv_data - platform private data:
* @irq: platform device interrupt number; * @irq: platform device interrupt number;
* @dev: basic device;
* @pdev: platform device; * @pdev: platform device;
* @plat: platform data; * @plat: platform data;
* @dwork: delayed work template; * @regmap: register map handle;
* @dwork_irq: delayed work template;
* @lock: spin lock; * @lock: spin lock;
* @hwmon: hwmon device; * @hwmon: hwmon device;
* @mlxreg_hotplug_attr: sysfs attributes array; * @mlxreg_hotplug_attr: sysfs attributes array;
...@@ -71,6 +74,8 @@ ...@@ -71,6 +74,8 @@
* @cell: location of top aggregation interrupt register; * @cell: location of top aggregation interrupt register;
* @mask: top aggregation interrupt common mask; * @mask: top aggregation interrupt common mask;
* @aggr_cache: last value of aggregation register status; * @aggr_cache: last value of aggregation register status;
* @after_probe: flag indication probing completion;
* @not_asserted: number of entries in workqueue with no signal assertion;
*/ */
struct mlxreg_hotplug_priv_data { struct mlxreg_hotplug_priv_data {
int irq; int irq;
...@@ -79,7 +84,6 @@ struct mlxreg_hotplug_priv_data { ...@@ -79,7 +84,6 @@ struct mlxreg_hotplug_priv_data {
struct mlxreg_hotplug_platform_data *plat; struct mlxreg_hotplug_platform_data *plat;
struct regmap *regmap; struct regmap *regmap;
struct delayed_work dwork_irq; struct delayed_work dwork_irq;
struct delayed_work dwork;
spinlock_t lock; /* sync with interrupt */ spinlock_t lock; /* sync with interrupt */
struct device *hwmon; struct device *hwmon;
struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1]; struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
...@@ -91,6 +95,7 @@ struct mlxreg_hotplug_priv_data { ...@@ -91,6 +95,7 @@ struct mlxreg_hotplug_priv_data {
u32 mask; u32 mask;
u32 aggr_cache; u32 aggr_cache;
bool after_probe; bool after_probe;
u8 not_asserted;
}; };
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
...@@ -409,6 +414,18 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work) ...@@ -409,6 +414,18 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
aggr_asserted = priv->aggr_cache ^ regval; aggr_asserted = priv->aggr_cache ^ regval;
priv->aggr_cache = regval; priv->aggr_cache = regval;
/*
* Handler is invoked, but no assertion is detected at top aggregation
* status level. Set aggr_asserted to mask value to allow handler extra
* run over all relevant signals to recover any missed signal.
*/
if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) {
priv->not_asserted = 0;
aggr_asserted = pdata->mask;
}
if (!aggr_asserted)
goto unmask_event;
/* Handle topology and health configuration changes. */ /* Handle topology and health configuration changes. */
for (i = 0; i < pdata->counter; i++, item++) { for (i = 0; i < pdata->counter; i++, item++) {
if (aggr_asserted & item->aggr_mask) { if (aggr_asserted & item->aggr_mask) {
...@@ -419,27 +436,26 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work) ...@@ -419,27 +436,26 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
} }
} }
if (aggr_asserted) { spin_lock_irqsave(&priv->lock, flags);
spin_lock_irqsave(&priv->lock, flags);
/* /*
* It is possible, that some signals have been inserted, while * It is possible, that some signals have been inserted, while
* interrupt has been masked by mlxreg_hotplug_work_handler. * interrupt has been masked by mlxreg_hotplug_work_handler. In this
* In this case such signals will be missed. In order to handle * case such signals will be missed. In order to handle these signals
* these signals delayed work is canceled and work task * delayed work is canceled and work task re-scheduled for immediate
* re-scheduled for immediate execution. It allows to handle * execution. It allows to handle missed signals, if any. In other case
* missed signals, if any. In other case work handler just * work handler just validates that no new signals have been received
* validates that no new signals have been received during * during masking.
* masking. */
*/ cancel_delayed_work(&priv->dwork_irq);
cancel_delayed_work(&priv->dwork_irq); schedule_delayed_work(&priv->dwork_irq, 0);
schedule_delayed_work(&priv->dwork_irq, 0);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return; return;
}
unmask_event:
priv->not_asserted++;
/* Unmask aggregation event (no need acknowledge). */ /* Unmask aggregation event (no need acknowledge). */
ret = regmap_write(priv->regmap, pdata->cell + ret = regmap_write(priv->regmap, pdata->cell +
MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask); MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
......
...@@ -129,6 +129,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = { ...@@ -129,6 +129,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
{KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
{KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} }, {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
{KE_KEY, 0x86, {KEY_WLAN} }, {KE_KEY, 0x86, {KEY_WLAN} },
{KE_KEY, 0x87, {KEY_POWER} },
{KE_END, 0} {KE_END, 0}
}; };
......
...@@ -495,7 +495,7 @@ static int gmux_set_power_state(enum vga_switcheroo_client_id id, ...@@ -495,7 +495,7 @@ static int gmux_set_power_state(enum vga_switcheroo_client_id id,
return gmux_set_discrete_state(apple_gmux_data, state); return gmux_set_discrete_state(apple_gmux_data, state);
} }
static int gmux_get_client_id(struct pci_dev *pdev) static enum vga_switcheroo_client_id gmux_get_client_id(struct pci_dev *pdev)
{ {
/* /*
* Early Macbook Pros with switchable graphics use nvidia * Early Macbook Pros with switchable graphics use nvidia
......
...@@ -1593,8 +1593,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, ...@@ -1593,8 +1593,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
int idx) int idx)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct platform_device *pdev = to_platform_device(dev); struct asus_laptop *asus = dev_get_drvdata(dev);
struct asus_laptop *asus = platform_get_drvdata(pdev);
acpi_handle handle = asus->handle; acpi_handle handle = asus->handle;
bool supported; bool supported;
......
...@@ -72,7 +72,7 @@ static u64 asus_wireless_method(acpi_handle handle, const char *method, ...@@ -72,7 +72,7 @@ static u64 asus_wireless_method(acpi_handle handle, const char *method,
acpi_handle_err(handle, acpi_handle_err(handle,
"Failed to eval method %s, param %#x (%d)\n", "Failed to eval method %s, param %#x (%d)\n",
method, param, s); method, param, s);
acpi_handle_debug(handle, "%s returned %#x\n", method, (uint) ret); acpi_handle_debug(handle, "%s returned %#llx\n", method, ret);
return ret; return ret;
} }
......
...@@ -1875,8 +1875,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, ...@@ -1875,8 +1875,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
struct attribute *attr, int idx) struct attribute *attr, int idx)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct platform_device *pdev = to_platform_device(dev); struct asus_wmi *asus = dev_get_drvdata(dev);
struct asus_wmi *asus = platform_get_drvdata(pdev);
bool ok = true; bool ok = true;
int devid = -1; int devid = -1;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
struct quirk_entry { struct quirk_entry {
bool touchpad_led; bool touchpad_led;
bool kbd_led_levels_off_1; bool kbd_led_levels_off_1;
bool kbd_missing_ac_tag;
bool needs_kbd_timeouts; bool needs_kbd_timeouts;
/* /*
...@@ -68,6 +69,10 @@ static struct quirk_entry quirk_dell_xps13_9333 = { ...@@ -68,6 +69,10 @@ static struct quirk_entry quirk_dell_xps13_9333 = {
.kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 }, .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
}; };
static struct quirk_entry quirk_dell_xps13_9370 = {
.kbd_missing_ac_tag = true,
};
static struct quirk_entry quirk_dell_latitude_e6410 = { static struct quirk_entry quirk_dell_latitude_e6410 = {
.kbd_led_levels_off_1 = true, .kbd_led_levels_off_1 = true,
}; };
...@@ -291,6 +296,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = { ...@@ -291,6 +296,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
}, },
.driver_data = &quirk_dell_xps13_9333, .driver_data = &quirk_dell_xps13_9333,
}, },
{
.callback = dmi_matched,
.ident = "Dell XPS 13 9370",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9370"),
},
.driver_data = &quirk_dell_xps13_9370,
},
{ {
.callback = dmi_matched, .callback = dmi_matched,
.ident = "Dell Latitude E6410", .ident = "Dell Latitude E6410",
...@@ -1401,7 +1415,8 @@ static inline int kbd_init_info(void) ...@@ -1401,7 +1415,8 @@ static inline int kbd_init_info(void)
* timeout value which is shared for both battery and AC power * timeout value which is shared for both battery and AC power
* settings. So do not try to set AC values on old models. * settings. So do not try to set AC values on old models.
*/ */
if (dell_smbios_find_token(KBD_LED_AC_TOKEN)) if ((quirks && quirks->kbd_missing_ac_tag) ||
dell_smbios_find_token(KBD_LED_AC_TOKEN))
kbd_timeout_ac_supported = true; kbd_timeout_ac_supported = true;
kbd_get_state(&state); kbd_get_state(&state);
......
...@@ -555,11 +555,10 @@ static void free_group(struct platform_device *pdev) ...@@ -555,11 +555,10 @@ static void free_group(struct platform_device *pdev)
static int __init dell_smbios_init(void) static int __init dell_smbios_init(void)
{ {
const struct dmi_device *valid;
int ret, wmi, smm; int ret, wmi, smm;
valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL); if (!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL) &&
if (!valid) { !dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "www.dell.com", NULL)) {
pr_err("Unable to run on non-Dell system\n"); pr_err("Unable to run on non-Dell system\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -233,7 +233,7 @@ static const u16 bios_to_linux_keycode[256] = { ...@@ -233,7 +233,7 @@ static const u16 bios_to_linux_keycode[256] = {
[18] = KEY_PROG1, [18] = KEY_PROG1,
[19] = KEY_BRIGHTNESSDOWN, [19] = KEY_BRIGHTNESSDOWN,
[20] = KEY_BRIGHTNESSUP, [20] = KEY_BRIGHTNESSUP,
[21] = KEY_UNKNOWN, [21] = KEY_BRIGHTNESS_AUTO,
[22] = KEY_KBDILLUMTOGGLE, [22] = KEY_KBDILLUMTOGGLE,
[23] = KEY_UNKNOWN, [23] = KEY_UNKNOWN,
[24] = KEY_SWITCHVIDEOMODE, [24] = KEY_SWITCHVIDEOMODE,
...@@ -261,6 +261,12 @@ static const u16 bios_to_linux_keycode[256] = { ...@@ -261,6 +261,12 @@ static const u16 bios_to_linux_keycode[256] = {
* override them. * override them.
*/ */
static const struct key_entry dell_wmi_keymap_type_0010[] = { static const struct key_entry dell_wmi_keymap_type_0010[] = {
/* Fn-lock switched to function keys */
{ KE_IGNORE, 0x0, { KEY_RESERVED } },
/* Fn-lock switched to multimedia keys */
{ KE_IGNORE, 0x1, { KEY_RESERVED } },
/* Mic mute */ /* Mic mute */
{ KE_KEY, 0x150, { KEY_MICMUTE } }, { KE_KEY, 0x150, { KEY_MICMUTE } },
...@@ -296,6 +302,14 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { ...@@ -296,6 +302,14 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
{ KE_KEY, 0x851, { KEY_PROG2 } }, { KE_KEY, 0x851, { KEY_PROG2 } },
{ KE_KEY, 0x852, { KEY_PROG3 } }, { KE_KEY, 0x852, { KEY_PROG3 } },
/*
* Radio disable (notify only -- there is no model for which the
* WMI event is supposed to trigger an action).
*/
{ KE_IGNORE, 0xe008, { KEY_RFKILL } },
/* Fn-lock */
{ KE_IGNORE, 0xe035, { KEY_RESERVED } },
}; };
/* /*
......
...@@ -91,6 +91,9 @@ ...@@ -91,6 +91,9 @@
#define FLAG_RFKILL BIT(5) #define FLAG_RFKILL BIT(5)
#define FLAG_LID BIT(8) #define FLAG_LID BIT(8)
#define FLAG_DOCK BIT(9) #define FLAG_DOCK BIT(9)
#define FLAG_TOUCHPAD_TOGGLE BIT(26)
#define FLAG_MICMUTE BIT(29)
#define FLAG_SOFTKEYS (FLAG_RFKILL | FLAG_TOUCHPAD_TOGGLE | FLAG_MICMUTE)
/* FUNC interface - LED control */ /* FUNC interface - LED control */
#define FUNC_LED_OFF BIT(0) #define FUNC_LED_OFF BIT(0)
...@@ -456,14 +459,15 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event) ...@@ -456,14 +459,15 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
/* ACPI device for hotkey handling */ /* ACPI device for hotkey handling */
static const struct key_entry keymap_default[] = { static const struct key_entry keymap_default[] = {
{ KE_KEY, KEY1_CODE, { KEY_PROG1 } }, { KE_KEY, KEY1_CODE, { KEY_PROG1 } },
{ KE_KEY, KEY2_CODE, { KEY_PROG2 } }, { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
{ KE_KEY, KEY3_CODE, { KEY_PROG3 } }, { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
{ KE_KEY, KEY4_CODE, { KEY_PROG4 } }, { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
{ KE_KEY, KEY5_CODE, { KEY_RFKILL } }, { KE_KEY, KEY5_CODE, { KEY_RFKILL } },
{ KE_KEY, BIT(5), { KEY_RFKILL } }, /* Soft keys read from status flags */
{ KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } }, { KE_KEY, FLAG_RFKILL, { KEY_RFKILL } },
{ KE_KEY, BIT(29), { KEY_MICMUTE } }, { KE_KEY, FLAG_TOUCHPAD_TOGGLE, { KEY_TOUCHPAD_TOGGLE } },
{ KE_KEY, FLAG_MICMUTE, { KEY_MICMUTE } },
{ KE_END, 0 } { KE_END, 0 }
}; };
...@@ -903,7 +907,8 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device) ...@@ -903,7 +907,8 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device)
static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
{ {
struct fujitsu_laptop *priv = acpi_driver_data(device); struct fujitsu_laptop *priv = acpi_driver_data(device);
int scancode, i = 0, ret; unsigned long flags;
int scancode, i = 0;
unsigned int irb; unsigned int irb;
if (event != ACPI_FUJITSU_NOTIFY_CODE) { if (event != ACPI_FUJITSU_NOTIFY_CODE) {
...@@ -930,21 +935,17 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) ...@@ -930,21 +935,17 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
"Unknown GIRB result [%x]\n", irb); "Unknown GIRB result [%x]\n", irb);
} }
/* On some models (first seen on the Skylake-based Lifebook /*
* E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is * First seen on the Skylake-based Lifebook E736/E746/E756), the
* handled in software; its state is queried using FUNC_FLAGS * touchpad toggle hotkey (Fn+F4) is handled in software. Other models
* have since added additional "soft keys". These are reported in the
* status flags queried using FUNC_FLAGS.
*/ */
if (priv->flags_supported & (BIT(5) | BIT(26) | BIT(29))) { if (priv->flags_supported & (FLAG_SOFTKEYS)) {
ret = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0); flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
if (ret & BIT(5)) flags &= (FLAG_SOFTKEYS);
sparse_keymap_report_event(priv->input, for_each_set_bit(i, &flags, BITS_PER_LONG)
BIT(5), 1, true); sparse_keymap_report_event(priv->input, BIT(i), 1, true);
if (ret & BIT(26))
sparse_keymap_report_event(priv->input,
BIT(26), 1, true);
if (ret & BIT(29))
sparse_keymap_report_event(priv->input,
BIT(29), 1, true);
} }
} }
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define IDEAPAD_RFKILL_DEV_NUM (3) #define IDEAPAD_RFKILL_DEV_NUM (3)
#define BM_CONSERVATION_BIT (5) #define BM_CONSERVATION_BIT (5)
#define HA_FNLOCK_BIT (10)
#define CFG_BT_BIT (16) #define CFG_BT_BIT (16)
#define CFG_3G_BIT (17) #define CFG_3G_BIT (17)
...@@ -59,6 +60,8 @@ static const char *const ideapad_wmi_fnesc_events[] = { ...@@ -59,6 +60,8 @@ static const char *const ideapad_wmi_fnesc_events[] = {
enum { enum {
BMCMD_CONSERVATION_ON = 3, BMCMD_CONSERVATION_ON = 3,
BMCMD_CONSERVATION_OFF = 5, BMCMD_CONSERVATION_OFF = 5,
HACMD_FNLOCK_ON = 0xe,
HACMD_FNLOCK_OFF = 0xf,
}; };
enum { enum {
...@@ -139,11 +142,11 @@ static int method_gbmd(acpi_handle handle, unsigned long *ret) ...@@ -139,11 +142,11 @@ static int method_gbmd(acpi_handle handle, unsigned long *ret)
return result; return result;
} }
static int method_sbmc(acpi_handle handle, int cmd) static int method_int1(acpi_handle handle, char *method, int cmd)
{ {
acpi_status status; acpi_status status;
status = acpi_execute_simple_method(handle, "SBMC", cmd); status = acpi_execute_simple_method(handle, method, cmd);
return ACPI_FAILURE(status) ? -1 : 0; return ACPI_FAILURE(status) ? -1 : 0;
} }
...@@ -487,7 +490,7 @@ static ssize_t conservation_mode_store(struct device *dev, ...@@ -487,7 +490,7 @@ static ssize_t conservation_mode_store(struct device *dev,
if (ret) if (ret)
return ret; return ret;
ret = method_sbmc(priv->adev->handle, state ? ret = method_int1(priv->adev->handle, "SBMC", state ?
BMCMD_CONSERVATION_ON : BMCMD_CONSERVATION_ON :
BMCMD_CONSERVATION_OFF); BMCMD_CONSERVATION_OFF);
if (ret < 0) if (ret < 0)
...@@ -497,11 +500,51 @@ static ssize_t conservation_mode_store(struct device *dev, ...@@ -497,11 +500,51 @@ static ssize_t conservation_mode_store(struct device *dev,
static DEVICE_ATTR_RW(conservation_mode); static DEVICE_ATTR_RW(conservation_mode);
static ssize_t fn_lock_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ideapad_private *priv = dev_get_drvdata(dev);
unsigned long result;
int hals;
int fail = read_method_int(priv->adev->handle, "HALS", &hals);
if (fail)
return sprintf(buf, "-1\n");
result = hals;
return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
}
static ssize_t fn_lock_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ideapad_private *priv = dev_get_drvdata(dev);
bool state;
int ret;
ret = kstrtobool(buf, &state);
if (ret)
return ret;
ret = method_int1(priv->adev->handle, "SALS", state ?
HACMD_FNLOCK_ON :
HACMD_FNLOCK_OFF);
if (ret < 0)
return -EIO;
return count;
}
static DEVICE_ATTR_RW(fn_lock);
static struct attribute *ideapad_attributes[] = { static struct attribute *ideapad_attributes[] = {
&dev_attr_camera_power.attr, &dev_attr_camera_power.attr,
&dev_attr_fan_mode.attr, &dev_attr_fan_mode.attr,
&dev_attr_touchpad.attr, &dev_attr_touchpad.attr,
&dev_attr_conservation_mode.attr, &dev_attr_conservation_mode.attr,
&dev_attr_fn_lock.attr,
NULL NULL
}; };
...@@ -522,6 +565,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj, ...@@ -522,6 +565,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_conservation_mode.attr) { } else if (attr == &dev_attr_conservation_mode.attr) {
supported = acpi_has_method(priv->adev->handle, "GBMD") && supported = acpi_has_method(priv->adev->handle, "GBMD") &&
acpi_has_method(priv->adev->handle, "SBMC"); acpi_has_method(priv->adev->handle, "SBMC");
} else if (attr == &dev_attr_fn_lock.attr) {
supported = acpi_has_method(priv->adev->handle, "HALS") &&
acpi_has_method(priv->adev->handle, "SALS");
} else } else
supported = true; supported = true;
...@@ -1079,6 +1125,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { ...@@ -1079,6 +1125,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"), DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
}, },
}, },
{
.ident = "Lenovo ideapad MIIX 720-12IKB",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 720-12IKB"),
},
},
{ {
.ident = "Lenovo Legion Y520-15IKBN", .ident = "Lenovo Legion Y520-15IKBN",
.matches = { .matches = {
...@@ -1163,6 +1216,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { ...@@ -1163,6 +1216,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"), DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
}, },
}, },
{
.ident = "Lenovo Zhaoyang E42-80",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ZHAOYANG E42-80"),
},
},
{} {}
}; };
......
...@@ -584,11 +584,11 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data) ...@@ -584,11 +584,11 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
if (cmd == IPC_I2C_READ) { if (cmd == IPC_I2C_READ) {
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR); writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
/* Write not getting updated without delay */ /* Write not getting updated without delay */
mdelay(1); usleep_range(1000, 2000);
*data = readl(scu->i2c_base + I2C_DATA_ADDR); *data = readl(scu->i2c_base + I2C_DATA_ADDR);
} else if (cmd == IPC_I2C_WRITE) { } else if (cmd == IPC_I2C_WRITE) {
writel(*data, scu->i2c_base + I2C_DATA_ADDR); writel(*data, scu->i2c_base + I2C_DATA_ADDR);
mdelay(1); usleep_range(1000, 2000);
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR); writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
} else { } else {
dev_err(scu->dev, dev_err(scu->dev,
......
...@@ -47,6 +47,11 @@ ...@@ -47,6 +47,11 @@
/* LPC bus IO offsets */ /* LPC bus IO offsets */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
...@@ -84,6 +89,8 @@ ...@@ -84,6 +89,8 @@
#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
/* Default I2C parent bus number */ /* Default I2C parent bus number */
#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
...@@ -114,11 +121,13 @@ ...@@ -114,11 +121,13 @@
* @pdev_i2c - i2c controller platform device * @pdev_i2c - i2c controller platform device
* @pdev_mux - array of mux platform devices * @pdev_mux - array of mux platform devices
* @pdev_hotplug - hotplug platform devices * @pdev_hotplug - hotplug platform devices
* @pdev_led - led platform devices
*/ */
struct mlxplat_priv { struct mlxplat_priv {
struct platform_device *pdev_i2c; struct platform_device *pdev_i2c;
struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS]; struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
struct platform_device *pdev_hotplug; struct platform_device *pdev_hotplug;
struct platform_device *pdev_led;
}; };
/* Regions for LPC I2C controller and LPC base register space */ /* Regions for LPC I2C controller and LPC base register space */
...@@ -592,9 +601,227 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = { ...@@ -592,9 +601,227 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
}; };
/* Platform led default data */
static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
{
.label = "status:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "status:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
},
{
.label = "psu:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "psu:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan1:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan1:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan2:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan2:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan3:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan3:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan4:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan4:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
};
static struct mlxreg_core_platform_data mlxplat_default_led_data = {
.data = mlxplat_mlxcpld_default_led_data,
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
};
/* Platform led MSN21xx system family data */
static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
{
.label = "status:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "status:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
},
{
.label = "fan:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "psu1:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "psu1:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "psu2:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "psu2:red",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "uid:blue",
.reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
};
static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
.data = mlxplat_mlxcpld_msn21xx_led_data,
.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
};
/* Platform led for default data for 200GbE systems */
static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
{
.label = "status:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "status:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
},
{
.label = "psu:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "psu:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan1:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan1:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan2:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan2:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan3:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan3:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan4:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan4:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan5:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan5:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
{
.label = "fan6:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
{
.label = "fan6:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
},
};
static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
.data = mlxplat_mlxcpld_default_ng_led_data,
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
};
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
...@@ -611,6 +838,11 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) ...@@ -611,6 +838,11 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
...@@ -632,6 +864,11 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) ...@@ -632,6 +864,11 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
...@@ -692,6 +929,7 @@ static struct resource mlxplat_mlxcpld_resources[] = { ...@@ -692,6 +929,7 @@ static struct resource mlxplat_mlxcpld_resources[] = {
static struct platform_device *mlxplat_dev; static struct platform_device *mlxplat_dev;
static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
static struct mlxreg_core_platform_data *mlxplat_led;
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{ {
...@@ -705,6 +943,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) ...@@ -705,6 +943,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_default_data; mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_led_data;
return 1; return 1;
}; };
...@@ -721,6 +960,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) ...@@ -721,6 +960,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_msn21xx_led_data;
return 1; return 1;
}; };
...@@ -737,6 +977,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) ...@@ -737,6 +977,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_led_data;
return 1; return 1;
}; };
...@@ -753,6 +994,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) ...@@ -753,6 +994,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_ng_led_data;
return 1; return 1;
}; };
...@@ -769,6 +1011,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) ...@@ -769,6 +1011,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_msn21xx_led_data;
return 1; return 1;
}; };
...@@ -844,6 +1087,36 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { ...@@ -844,6 +1087,36 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "SN34"), DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
}, },
}, },
{
.callback = mlxplat_dmi_default_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
},
},
{
.callback = mlxplat_dmi_msn21xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
},
},
{
.callback = mlxplat_dmi_msn274x_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
},
},
{
.callback = mlxplat_dmi_msn201x_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
},
},
{
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
},
},
{ } { }
}; };
...@@ -960,14 +1233,27 @@ static int __init mlxplat_init(void) ...@@ -960,14 +1233,27 @@ static int __init mlxplat_init(void)
goto fail_platform_mux_register; goto fail_platform_mux_register;
} }
/* Add LED driver. */
mlxplat_led->regmap = mlxplat_hotplug->regmap;
priv->pdev_led = platform_device_register_resndata(
&mlxplat_dev->dev, "leds-mlxreg",
PLATFORM_DEVID_NONE, NULL, 0,
mlxplat_led, sizeof(*mlxplat_led));
if (IS_ERR(priv->pdev_led)) {
err = PTR_ERR(priv->pdev_led);
goto fail_platform_hotplug_register;
}
/* Sync registers with hardware. */ /* Sync registers with hardware. */
regcache_mark_dirty(mlxplat_hotplug->regmap); regcache_mark_dirty(mlxplat_hotplug->regmap);
err = regcache_sync(mlxplat_hotplug->regmap); err = regcache_sync(mlxplat_hotplug->regmap);
if (err) if (err)
goto fail_platform_hotplug_register; goto fail_platform_led_register;
return 0; return 0;
fail_platform_led_register:
platform_device_unregister(priv->pdev_led);
fail_platform_hotplug_register: fail_platform_hotplug_register:
platform_device_unregister(priv->pdev_hotplug); platform_device_unregister(priv->pdev_hotplug);
fail_platform_mux_register: fail_platform_mux_register:
...@@ -986,6 +1272,7 @@ static void __exit mlxplat_exit(void) ...@@ -986,6 +1272,7 @@ static void __exit mlxplat_exit(void)
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
int i; int i;
platform_device_unregister(priv->pdev_led);
platform_device_unregister(priv->pdev_hotplug); platform_device_unregister(priv->pdev_hotplug);
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--) for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
......
...@@ -1216,8 +1216,7 @@ static umode_t samsung_sysfs_is_visible(struct kobject *kobj, ...@@ -1216,8 +1216,7 @@ static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
struct attribute *attr, int idx) struct attribute *attr, int idx)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct platform_device *pdev = to_platform_device(dev); struct samsung_laptop *samsung = dev_get_drvdata(dev);
struct samsung_laptop *samsung = platform_get_drvdata(pdev);
bool ok = true; bool ok = true;
if (attr == &dev_attr_performance_level.attr) if (attr == &dev_attr_performance_level.attr)
......
...@@ -53,6 +53,20 @@ static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = { ...@@ -53,6 +53,20 @@ static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
.properties = jumper_ezpad_mini3_props, .properties = jumper_ezpad_mini3_props,
}; };
static const struct property_entry jumper_ezpad_6_pro_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct silead_ts_dmi_data jumper_ezpad_6_pro_data = {
.acpi_name = "MSSL1680:00",
.properties = jumper_ezpad_6_pro_props,
};
static const struct property_entry dexp_ursus_7w_props[] = { static const struct property_entry dexp_ursus_7w_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 890), PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
PROPERTY_ENTRY_U32("touchscreen-size-y", 630), PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
...@@ -127,7 +141,25 @@ static const struct silead_ts_dmi_data pipo_w2s_data = { ...@@ -127,7 +141,25 @@ static const struct silead_ts_dmi_data pipo_w2s_data = {
.properties = pipo_w2s_props, .properties = pipo_w2s_props,
}; };
static const struct property_entry pov_mobii_wintab_p800w_props[] = { static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl3680-pov-mobii-wintab-p800w-v20.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
.acpi_name = "MSSL1680:00",
.properties = pov_mobii_wintab_p800w_v20_props,
};
static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1800), PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
...@@ -137,9 +169,9 @@ static const struct property_entry pov_mobii_wintab_p800w_props[] = { ...@@ -137,9 +169,9 @@ static const struct property_entry pov_mobii_wintab_p800w_props[] = {
{ } { }
}; };
static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = { static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
.acpi_name = "MSSL1680:00", .acpi_name = "MSSL1680:00",
.properties = pov_mobii_wintab_p800w_props, .properties = pov_mobii_wintab_p800w_v21_props,
}; };
static const struct property_entry itworks_tw891_props[] = { static const struct property_entry itworks_tw891_props[] = {
...@@ -277,6 +309,23 @@ static const struct silead_ts_dmi_data teclast_x3_plus_data = { ...@@ -277,6 +309,23 @@ static const struct silead_ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props, .properties = teclast_x3_plus_props,
}; };
static const struct property_entry onda_v891w_v1_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl3680-onda-v891w-v1.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct silead_ts_dmi_data onda_v891w_v1_data = {
.acpi_name = "MSSL1680:00",
.properties = onda_v891w_v1_props,
};
static const struct dmi_system_id silead_ts_dmi_table[] = { static const struct dmi_system_id silead_ts_dmi_table[] = {
{ {
/* CUBE iwork8 Air */ /* CUBE iwork8 Air */
...@@ -296,6 +345,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { ...@@ -296,6 +345,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
}, },
}, },
{
/* Jumper EZpad 6 Pro */
.driver_data = (void *)&jumper_ezpad_6_pro_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
/* Above matches are too generic, add bios-date match */
DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
},
},
{ {
/* DEXP Ursus 7W */ /* DEXP Ursus 7W */
.driver_data = (void *)&dexp_ursus_7w_data, .driver_data = (void *)&dexp_ursus_7w_data,
...@@ -361,8 +421,19 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { ...@@ -361,8 +421,19 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
}, },
}, },
{ {
/* Point of View mobii wintab p800w */ /* Point of View mobii wintab p800w (v2.0) */
.driver_data = (void *)&pov_mobii_wintab_p800w_data, .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
/* Above matches are too generic, add bios-date match */
DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
},
},
{
/* Point of View mobii wintab p800w (v2.1) */
.driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
...@@ -412,6 +483,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { ...@@ -412,6 +483,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "S806"), DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
}, },
}, },
{
/* Chuwi Hi8 (H1D_S806_206) */
.driver_data = (void *)&chuwi_hi8_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
},
},
{ {
/* Chuwi Vi8 (CWI506) */ /* Chuwi Vi8 (CWI506) */
.driver_data = (void *)&chuwi_vi8_data, .driver_data = (void *)&chuwi_vi8_data,
...@@ -463,6 +543,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { ...@@ -463,6 +543,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"), DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
}, },
}, },
{
/* ONDA V891w revision P891WBEBV1B00 aka v1 */
.driver_data = (void *)&onda_v891w_v1_data,
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
/* Exact match, different versions need different fw */
DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
},
},
{ }, { },
}; };
......
...@@ -212,7 +212,12 @@ enum tpacpi_hkey_event_t { ...@@ -212,7 +212,12 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */ TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */
TP_HKEY_EV_ALARM_SENSOR_HOT = 0x6021, /* sensor too hot */ TP_HKEY_EV_ALARM_SENSOR_HOT = 0x6021, /* sensor too hot */
TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */ TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */
TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */ TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* windows; thermal table changed */
TP_HKEY_EV_THM_CSM_COMPLETED = 0x6032, /* windows; thermal control set
* command completed. Related to
* AML DYTC */
TP_HKEY_EV_THM_TRANSFM_CHANGED = 0x60F0, /* windows; thermal transformation
* changed. Related to AML GMTS */
/* AC-related events */ /* AC-related events */
TP_HKEY_EV_AC_CHANGED = 0x6040, /* AC status changed */ TP_HKEY_EV_AC_CHANGED = 0x6040, /* AC status changed */
...@@ -4034,15 +4039,23 @@ static bool hotkey_notify_6xxx(const u32 hkey, ...@@ -4034,15 +4039,23 @@ static bool hotkey_notify_6xxx(const u32 hkey,
bool *send_acpi_ev, bool *send_acpi_ev,
bool *ignore_acpi_ev) bool *ignore_acpi_ev)
{ {
bool known = true;
/* 0x6000-0x6FFF: thermal alarms/notices and keyboard events */ /* 0x6000-0x6FFF: thermal alarms/notices and keyboard events */
*send_acpi_ev = true; *send_acpi_ev = true;
*ignore_acpi_ev = false; *ignore_acpi_ev = false;
switch (hkey) { switch (hkey) {
case TP_HKEY_EV_THM_TABLE_CHANGED: case TP_HKEY_EV_THM_TABLE_CHANGED:
pr_info("EC reports that Thermal Table has changed\n"); pr_debug("EC reports: Thermal Table has changed\n");
/* recommended action: do nothing, we don't have
* Lenovo ATM information */
return true;
case TP_HKEY_EV_THM_CSM_COMPLETED:
pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
/* recommended action: do nothing, we don't have
* Lenovo ATM information */
return true;
case TP_HKEY_EV_THM_TRANSFM_CHANGED:
pr_debug("EC reports: Thermal Transformation changed (GMTS)\n");
/* recommended action: do nothing, we don't have /* recommended action: do nothing, we don't have
* Lenovo ATM information */ * Lenovo ATM information */
return true; return true;
...@@ -4083,7 +4096,7 @@ static bool hotkey_notify_6xxx(const u32 hkey, ...@@ -4083,7 +4096,7 @@ static bool hotkey_notify_6xxx(const u32 hkey,
tpacpi_input_send_tabletsw(); tpacpi_input_send_tabletsw();
hotkey_tablet_mode_notify_change(); hotkey_tablet_mode_notify_change();
*send_acpi_ev = false; *send_acpi_ev = false;
break; return true;
case TP_HKEY_EV_PALM_DETECTED: case TP_HKEY_EV_PALM_DETECTED:
case TP_HKEY_EV_PALM_UNDETECTED: case TP_HKEY_EV_PALM_UNDETECTED:
...@@ -4092,13 +4105,12 @@ static bool hotkey_notify_6xxx(const u32 hkey, ...@@ -4092,13 +4105,12 @@ static bool hotkey_notify_6xxx(const u32 hkey,
return true; return true;
default: default:
pr_warn("unknown possible thermal alarm or keyboard event received\n"); /* report simply as unknown, no sensor dump */
known = false; return false;
} }
thermal_dump_all_sensors(); thermal_dump_all_sensors();
return true;
return known;
} }
static void hotkey_notify(struct ibm_struct *ibm, u32 event) static void hotkey_notify(struct ibm_struct *ibm, u32 event)
......
...@@ -58,11 +58,10 @@ struct mlxreg_hotplug_device { ...@@ -58,11 +58,10 @@ struct mlxreg_hotplug_device {
* struct mlxreg_core_data - attributes control data: * struct mlxreg_core_data - attributes control data:
* *
* @label: attribute label; * @label: attribute label;
* @label: attribute register offset;
* @reg: attribute register; * @reg: attribute register;
* @mask: attribute access mask; * @mask: attribute access mask;
* @mode: access mode;
* @bit: attribute effective bit; * @bit: attribute effective bit;
* @mode: access mode;
* @np - pointer to node platform associated with attribute; * @np - pointer to node platform associated with attribute;
* @hpdev - hotplug device data; * @hpdev - hotplug device data;
* @health_cntr: dynamic device health indication counter; * @health_cntr: dynamic device health indication counter;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/types.h> #include <linux/types.h>
struct file; struct file;
struct task_struct;
/* Descriptions of the types of units to /* Descriptions of the types of units to
* print in */ * print in */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment