Commit 0dfaeb61 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull x86 platform driver updates from Darren Hart:
 "Introduce new bus architecture for WMI and expose BMOF data through
  sysfs. Correct several assumptions about WMI instance number from 1 to
  0. Further fujitsu-laptop cleanups, continuing to prepare for
  separation into two modules. Add support for several new ideapad
  laptops and silead-based tablets. Various minor fixes and const
  cleanups.

  Detail summary:

  sony-laptop:
   - constify attribute_group and input index array

  fujitsu-laptop:
   - rework debugging
   - do not evaluate ACPI _INI methods
   - do not update ACPI device power status
   - sanitize hotkey input device identification
   - use strcpy to set ACPI device names and classes
   - remove redundant safety checks
   - use device-specific data in remaining module code
   - use device-specific data in LED-related code
   - explicitly pass ACPI device to call_fext_func()
   - track the last instantiated FUJ02E3 ACPI device
   - allocate fujitsu_laptop in acpi_fujitsu_laptop_add()
   - use device-specific data in backlight code
   - allocate fujitsu_bl in acpi_fujitsu_bl_add()
   - distinguish current uses of device-specific data

  msi-laptop:
   - constify msipf*_attribute_group

  eeepc-laptop:
   - constify platform_attribute_group

  toshiba_haps:
   - constify haps_attr_group

  dell-wmi-led:
   - Adjust instance of wmi_evaluate_method calls to 0

  alienware-wmi:
   - Adjust instance of wmi_evaluate_method calls to 0

  intel_menlow:
   - Add const to thermal_cooling_device_ops structure

  acerhdf:
   - Add const to thermal_cooling_device_ops structure

  dell-laptop:
   - Fix bogus keyboard backlight sysfs interface

  acer-wmi:
   - Using zero as first WMI instance number
   - Detect RF Button capability

  ideapad-laptop:
   - Add Y720-15IKBN to no_hw_rfkill
   - Add Y520-15IKBN to no_hw_rfkill
   - constify rfkill_ops structure
   - Squelch ACPI event 1
   - hide unused 'touchpad_store'
   - Switch touchpad attribute to be RO
   - Add sysfs interface for touchpad state

  silead_dmi:
   - Add touchscreen info for PoV mobii wintab p800w
   - Add touchscreen info for Pipo W2S tablet
   - Add touchscreen info for GP-electronic T701

  dell-rbtn:
   - constify rfkill_ops structures
   - Improve explanation about DELLABC6

  samsung-laptop:
   - constify rfkill_ops structures

  panasonic-laptop:
   - remove unused code

  samsung-laptop:
   - Initialize loca variable

  dell-wmi:
   - Convert to the WMI bus infrastructure
   - Add a better description for "stealth mode"
   - Add a comment explaining the 0xb2 magic number

  wmi-bmof:
   - New driver to expose embedded Binary WMI MOF metadata

  wmi*:
   - Fix printing info about WDG structure
   - Add recent copyright statements
   - Require query for data blocks, rename writable to setable
   - Add an interface for subdrivers to access sibling devices
   - Bind the platform device, not the ACPI node
   - Add a new interface to read block data
   - Incorporate acpi_install_notify_handler
   - Instantiate all devices before adding them
   - Probe data objects for read and write capabilities
   - Split devices into types and add basic sysfs attributes
   - Fix error handling when creating devices
   - Turn WMI into a bus driver
   - Track wmi devices per ACPI device
   - Clean up acpi_wmi_add
   - Pass the acpi_device through to parse_wdg
   - Drop "Mapper (un)loaded" messages

  intel_cht_int33fe:
   - Set supplied-from property on max17047 dev

  intel_pmc_ipc:
   - Mark ipc_data_readb() as __maybe_unused

  topstar-laptop:
   - Add new device id

  peaq-wmi:
   - Add new peaq-wmi driver

  thinkpad_acpi:
   - Add a comment about 0 in module_param_call()
   - Join string literals back

  toshiba_acpi:
   - use memdup_user_nul"

* tag 'platform-drivers-x86-v4.13-1' of git://git.infradead.org/linux-platform-drivers-x86: (67 commits)
  platform/x86: sony-laptop: constify attribute_group and input index array
  platform/x86: fujitsu-laptop: rework debugging
  platform/x86: fujitsu-laptop: do not evaluate ACPI _INI methods
  platform/x86: fujitsu-laptop: do not update ACPI device power status
  platform/x86: fujitsu-laptop: sanitize hotkey input device identification
  platform/x86: fujitsu-laptop: use strcpy to set ACPI device names and classes
  platform/x86: fujitsu-laptop: remove redundant safety checks
  platform/x86: msi-laptop: constify msipf*_attribute_group
  platform/x86: eeepc-laptop: constify platform_attribute_group
  platform/x86: toshiba_haps: constify haps_attr_group
  platform/x86: dell-wmi-led: Adjust instance of wmi_evaluate_method calls to 0
  platform/x86: alienware-wmi: Adjust instance of wmi_evaluate_method calls to 0
  platform/x86: intel_menlow: Add const to thermal_cooling_device_ops structure
  platform/x86: acerhdf: Add const to thermal_cooling_device_ops structure
  platform/x86: dell-laptop: Fix bogus keyboard backlight sysfs interface
  platform/x86: acer-wmi: Using zero as first WMI instance number
  platform/x86: ideapad-laptop: Add Y720-15IKBN to no_hw_rfkill
  platform/x86: ideapad-laptop: Add Y520-15IKBN to no_hw_rfkill
  platform/x86: silead_dmi: Add touchscreen info for PoV mobii wintab p800w
  platform/x86: silead_dmi: Add touchscreen info for Pipo W2S tablet
  ...
parents 90311148 d791db9a
......@@ -17,3 +17,11 @@ Description:
* 2 -> Dust Cleaning
* 4 -> Efficient Thermal Dissipation Mode
What: /sys/devices/platform/ideapad/touchpad
Date: May 2017
KernelVersion: 4.13
Contact: "Ritesh Raj Sarraf <rrs@debian.org>"
Description:
Control touchpad mode.
* 1 -> Switched On
* 0 -> Switched Off
......@@ -195,16 +195,6 @@ config FUJITSU_LAPTOP
If you have a Fujitsu laptop, say Y or M here.
config FUJITSU_LAPTOP_DEBUG
bool "Verbose debug mode for Fujitsu Laptop Extras"
depends on FUJITSU_LAPTOP
default n
---help---
Enables extra debug output from the fujitsu extras driver, at the
expense of a slight increase in driver size.
If you are not sure, say N here.
config FUJITSU_TABLET
tristate "Fujitsu Tablet Extras"
depends on ACPI
......@@ -656,6 +646,18 @@ config ACPI_WMI
It is safe to enable this driver even if your DSDT doesn't define
any ACPI-WMI devices.
config WMI_BMOF
tristate "WMI embedded Binary MOF driver"
depends on ACPI_WMI
default ACPI_WMI
---help---
Say Y here if you want to be able to read a firmware-embedded
WMI Binary MOF data. Using this requires userspace tools and may be
rather tedious.
To compile this driver as a module, choose M here: the module will
be called wmi-bmof.
config MSI_WMI
tristate "MSI WMI extras"
depends on ACPI_WMI
......@@ -669,6 +671,13 @@ config MSI_WMI
To compile this driver as a module, choose M here: the module will
be called msi-wmi.
config PEAQ_WMI
tristate "PEAQ 2-in-1 WMI hotkey driver"
depends on ACPI_WMI
depends on INPUT
help
Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s.
config TOPSTAR_LAPTOP
tristate "Topstar Laptop Extras"
depends on ACPI
......
......@@ -35,8 +35,10 @@ obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ACPI_WMI) += wmi.o
obj-$(CONFIG_MSI_WMI) += msi-wmi.o
obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o
obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o
obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
# toshiba_acpi must link after wmi to ensure that wmi devices are found
# before toshiba_acpi initializes
......
......@@ -149,6 +149,8 @@ struct event_return_value {
#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
#define ACER_WMID3_GDS_RFBTN (1<<14) /* RF Button */
#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */
/* Hotkey Customized Setting and Acer Application Status.
......@@ -221,6 +223,7 @@ struct hotkey_function_type_aa {
#define ACER_CAP_BRIGHTNESS (1<<3)
#define ACER_CAP_THREEG (1<<4)
#define ACER_CAP_ACCEL (1<<5)
#define ACER_CAP_RFBTN (1<<6)
#define ACER_CAP_ANY (0xFFFFFFFF)
/*
......@@ -700,7 +703,7 @@ struct acpi_buffer *result)
input.length = sizeof(struct wmab_args);
input.pointer = (u8 *)regbuf;
status = wmi_evaluate_method(AMW0_GUID1, 1, 1, &input, result);
status = wmi_evaluate_method(AMW0_GUID1, 0, 1, &input, result);
return status;
}
......@@ -965,7 +968,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
u32 tmp = 0;
acpi_status status;
status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result);
status = wmi_evaluate_method(WMID_GUID1, 0, method_id, &input, &result);
if (ACPI_FAILURE(status))
return status;
......@@ -1264,6 +1267,10 @@ static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)
interface->capability |= ACER_CAP_THREEG;
if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
interface->capability |= ACER_CAP_BLUETOOTH;
if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN) {
interface->capability |= ACER_CAP_RFBTN;
commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN;
}
commun_fn_key_number = type_aa->commun_fn_key_number;
}
......@@ -1275,7 +1282,7 @@ static acpi_status __init WMID_set_capabilities(void)
acpi_status status;
u32 devices;
status = wmi_query_block(WMID_GUID2, 1, &out);
status = wmi_query_block(WMID_GUID2, 0, &out);
if (ACPI_FAILURE(status))
return status;
......@@ -2018,7 +2025,7 @@ static u32 get_wmid_devices(void)
acpi_status status;
u32 devices = 0;
status = wmi_query_block(WMID_GUID2, 1, &out);
status = wmi_query_block(WMID_GUID2, 0, &out);
if (ACPI_FAILURE(status))
return 0;
......
......@@ -557,7 +557,7 @@ static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev,
}
/* bind fan callbacks to fan device */
static struct thermal_cooling_device_ops acerhdf_cooling_ops = {
static const struct thermal_cooling_device_ops acerhdf_cooling_ops = {
.get_max_state = acerhdf_get_max_state,
.get_cur_state = acerhdf_get_cur_state,
.set_cur_state = acerhdf_set_cur_state,
......
......@@ -303,7 +303,7 @@ static int alienware_update_led(struct platform_zone *zone)
}
pr_debug("alienware-wmi: guid %s method %d\n", guid, method_id);
status = wmi_evaluate_method(guid, 1, method_id, &input, NULL);
status = wmi_evaluate_method(guid, 0, method_id, &input, NULL);
if (ACPI_FAILURE(status))
pr_err("alienware-wmi: zone set failure: %u\n", status);
return ACPI_FAILURE(status);
......@@ -352,7 +352,7 @@ static int wmax_brightness(int brightness)
};
input.length = (acpi_size) sizeof(args);
input.pointer = &args;
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
WMAX_METHOD_BRIGHTNESS, &input, NULL);
if (ACPI_FAILURE(status))
pr_err("alienware-wmi: brightness set failure: %u\n", status);
......@@ -506,10 +506,10 @@ static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args,
if (out_data != NULL) {
output.length = ACPI_ALLOCATE_BUFFER;
output.pointer = NULL;
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
command, &input, &output);
} else
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1,
status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
command, &input, NULL);
if (ACPI_SUCCESS(status) && out_data != NULL) {
......
......@@ -1510,7 +1510,11 @@ static void kbd_init(void)
ret = kbd_init_info();
kbd_init_tokens();
if (kbd_token_bits != 0 || ret == 0)
/*
* Only supports keyboard backlight when it has at least two modes.
*/
if ((ret == 0 && (kbd_info.levels != 0 || kbd_mode_levels_count >= 2))
|| kbd_get_valid_token_counts() >= 2)
kbd_led_present = true;
}
......
......@@ -110,7 +110,7 @@ static int rbtn_rfkill_set_block(void *data, bool blocked)
return -EINVAL;
}
static struct rfkill_ops rbtn_ops = {
static const struct rfkill_ops rbtn_ops = {
.query = rbtn_rfkill_query,
.set_block = rbtn_rfkill_set_block,
};
......@@ -221,16 +221,27 @@ static const struct acpi_device_id rbtn_ids[] = {
/*
* This driver can also handle the "DELLABC6" device that
* appears on the XPS 13 9350, but that device is disabled
* by the DSDT unless booted with acpi_osi="!Windows 2012"
* acpi_osi="!Windows 2013". Even if we boot that and bind
* the driver, we seem to have inconsistent behavior in
* which NetworkManager can get out of sync with the rfkill
* state.
* appears on the XPS 13 9350, but that device is disabled by
* the DSDT unless booted with acpi_osi="!Windows 2012"
* acpi_osi="!Windows 2013".
*
* On the XPS 13 9350 and similar laptops, we're not supposed to
* use DELLABC6 at all. Instead, we handle the rfkill button
* via the intel-hid driver.
* According to Mario at Dell:
*
* DELLABC6 is a custom interface that was created solely to
* have airplane mode support for Windows 7. For Windows 10
* the proper interface is to use that which is handled by
* intel-hid. A OEM airplane mode driver is not used.
*
* Since the kernel doesn't identify as Windows 7 it would be
* incorrect to do attempt to use that interface.
*
* Even if we override _OSI and bind to DELLABC6, we end up with
* inconsistent behavior in which userspace can get out of sync
* with the rfkill state as it conflicts with events from
* intel-hid.
*
* The upshot is that it is better to just ignore DELLABC6
* devices.
*/
{ "", 0 },
......
......@@ -68,7 +68,7 @@ static int dell_led_perform_fn(u8 length, u8 result_code, u8 device_id,
input.length = sizeof(struct bios_args);
input.pointer = &args;
status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 1, 1, &input, &output);
status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 0, 1, &input, &output);
if (ACPI_FAILURE(status))
return status;
......
......@@ -36,6 +36,7 @@
#include <linux/acpi.h>
#include <linux/string.h>
#include <linux/dmi.h>
#include <linux/wmi.h>
#include <acpi/video.h>
#include "dell-smbios.h"
......@@ -53,6 +54,10 @@ static bool wmi_requires_smbios_request;
MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID);
struct dell_wmi_priv {
struct input_dev *input_dev;
};
static int __init dmi_matched(const struct dmi_system_id *dmi)
{
wmi_requires_smbios_request = 1;
......@@ -86,7 +91,7 @@ static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
* notifications (rather than requests for change) or are also sent
* via the keyboard controller so should not be sent again.
*/
static const struct key_entry dell_wmi_keymap_type_0000[] __initconst = {
static const struct key_entry dell_wmi_keymap_type_0000[] = {
{ KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
/* Key code is followed by brightness level */
......@@ -207,7 +212,7 @@ struct dell_dmi_results {
};
/* Uninitialized entries here are KEY_RESERVED == 0. */
static const u16 bios_to_linux_keycode[256] __initconst = {
static const u16 bios_to_linux_keycode[256] = {
[0] = KEY_MEDIA,
[1] = KEY_NEXTSONG,
[2] = KEY_PLAYPAUSE,
......@@ -256,7 +261,7 @@ static const u16 bios_to_linux_keycode[256] __initconst = {
* These are applied if the 0xB2 DMI hotkey table is present and doesn't
* override them.
*/
static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = {
static const struct key_entry dell_wmi_keymap_type_0010[] = {
/* Fn-lock */
{ KE_IGNORE, 0x151, { KEY_RESERVED } },
......@@ -272,7 +277,12 @@ static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = {
/* RGB keyboard backlight control */
{ KE_IGNORE, 0x154, { KEY_RESERVED } },
/* Stealth mode toggle */
/*
* Stealth mode toggle. This will "disable all lights and sounds".
* The action is performed by the BIOS and EC; the WMI event is just
* a notification. On the XPS 13 9350, this is Fn+F7, and there's
* a BIOS setting to enable and disable the hotkey.
*/
{ KE_IGNORE, 0x155, { KEY_RESERVED } },
/* Rugged magnetic dock attach/detach events */
......@@ -289,7 +299,7 @@ static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = {
/*
* Keymap for WMI events of type 0x0011
*/
static const struct key_entry dell_wmi_keymap_type_0011[] __initconst = {
static const struct key_entry dell_wmi_keymap_type_0011[] = {
/* Battery unplugged */
{ KE_IGNORE, 0xfff0, { KEY_RESERVED } },
......@@ -304,13 +314,12 @@ static const struct key_entry dell_wmi_keymap_type_0011[] __initconst = {
{ KE_IGNORE, 0x02f6, { KEY_RESERVED } },
};
static struct input_dev *dell_wmi_input_dev;
static void dell_wmi_process_key(int type, int code)
static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
{
struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
const struct key_entry *key;
key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
key = sparse_keymap_entry_from_scancode(priv->input_dev,
(type << 16) | code);
if (!key) {
pr_info("Unknown key with type 0x%04x and code 0x%04x pressed\n",
......@@ -333,33 +342,18 @@ static void dell_wmi_process_key(int type, int code)
dell_laptop_call_notifier(
DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, NULL);
sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
sparse_keymap_report_entry(priv->input_dev, key, 1, true);
}
static void dell_wmi_notify(u32 value, void *context)
static void dell_wmi_notify(struct wmi_device *wdev,
union acpi_object *obj)
{
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
acpi_size buffer_size;
u16 *buffer_entry, *buffer_end;
acpi_size buffer_size;
int len, i;
status = wmi_get_event_data(value, &response);
if (status != AE_OK) {
pr_warn("bad event status 0x%x\n", status);
return;
}
obj = (union acpi_object *)response.pointer;
if (!obj) {
pr_warn("no response\n");
return;
}
if (obj->type != ACPI_TYPE_BUFFER) {
pr_warn("bad response type %x\n", obj->type);
kfree(obj);
return;
}
......@@ -404,13 +398,14 @@ static void dell_wmi_notify(u32 value, void *context)
switch (buffer_entry[1]) {
case 0x0000: /* One key pressed or event occurred */
if (len > 2)
dell_wmi_process_key(0x0000, buffer_entry[2]);
dell_wmi_process_key(wdev, 0x0000,
buffer_entry[2]);
/* Other entries could contain additional information */
break;
case 0x0010: /* Sequence of keys pressed */
case 0x0011: /* Sequence of events occurred */
for (i = 2; i < len; ++i)
dell_wmi_process_key(buffer_entry[1],
dell_wmi_process_key(wdev, buffer_entry[1],
buffer_entry[i]);
break;
default: /* Unknown event */
......@@ -423,7 +418,6 @@ static void dell_wmi_notify(u32 value, void *context)
}
kfree(obj);
}
static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len)
......@@ -437,9 +431,7 @@ static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len)
return false;
}
static void __init handle_dmi_entry(const struct dmi_header *dm,
void *opaque)
static void handle_dmi_entry(const struct dmi_header *dm, void *opaque)
{
struct dell_dmi_results *results = opaque;
struct dell_bios_hotkey_table *table;
......@@ -449,6 +441,7 @@ static void __init handle_dmi_entry(const struct dmi_header *dm,
if (results->err || results->keymap)
return; /* We already found the hotkey table. */
/* The Dell hotkey table is type 0xB2. Scan until we find it. */
if (dm->type != 0xb2)
return;
......@@ -509,19 +502,20 @@ static void __init handle_dmi_entry(const struct dmi_header *dm,
results->keymap_size = pos;
}
static int __init dell_wmi_input_setup(void)
static int dell_wmi_input_setup(struct wmi_device *wdev)
{
struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
struct dell_dmi_results dmi_results = {};
struct key_entry *keymap;
int err, i, pos = 0;
dell_wmi_input_dev = input_allocate_device();
if (!dell_wmi_input_dev)
priv->input_dev = input_allocate_device();
if (!priv->input_dev)
return -ENOMEM;
dell_wmi_input_dev->name = "Dell WMI hotkeys";
dell_wmi_input_dev->phys = "wmi/input0";
dell_wmi_input_dev->id.bustype = BUS_HOST;
priv->input_dev->name = "Dell WMI hotkeys";
priv->input_dev->id.bustype = BUS_HOST;
priv->input_dev->dev.parent = &wdev->dev;
if (dmi_walk(handle_dmi_entry, &dmi_results)) {
/*
......@@ -596,7 +590,7 @@ static int __init dell_wmi_input_setup(void)
keymap[pos].type = KE_END;
err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
err = sparse_keymap_setup(priv->input_dev, keymap, NULL);
/*
* Sparse keymap library makes a copy of keymap so we don't need the
* original one that was allocated.
......@@ -605,17 +599,24 @@ static int __init dell_wmi_input_setup(void)
if (err)
goto err_free_dev;
err = input_register_device(dell_wmi_input_dev);
err = input_register_device(priv->input_dev);
if (err)
goto err_free_dev;
return 0;
err_free_dev:
input_free_device(dell_wmi_input_dev);
input_free_device(priv->input_dev);
return err;
}
static void dell_wmi_input_destroy(struct wmi_device *wdev)
{
struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
input_unregister_device(priv->input_dev);
}
/*
* Descriptor buffer is 128 byte long and contains:
*
......@@ -714,46 +715,55 @@ static int dell_wmi_events_set_enabled(bool enable)
return dell_smbios_error(ret);
}
static int dell_wmi_probe(struct wmi_device *wdev)
{
struct dell_wmi_priv *priv = devm_kzalloc(
&wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL);
dev_set_drvdata(&wdev->dev, priv);
return dell_wmi_input_setup(wdev);
}
static int dell_wmi_remove(struct wmi_device *wdev)
{
dell_wmi_input_destroy(wdev);
return 0;
}
static const struct wmi_device_id dell_wmi_id_table[] = {
{ .guid_string = DELL_EVENT_GUID },
{ },
};
static struct wmi_driver dell_wmi_driver = {
.driver = {
.name = "dell-wmi",
},
.id_table = dell_wmi_id_table,
.probe = dell_wmi_probe,
.remove = dell_wmi_remove,
.notify = dell_wmi_notify,
};
static int __init dell_wmi_init(void)
{
int err;
acpi_status status;
if (!wmi_has_guid(DELL_EVENT_GUID) ||
!wmi_has_guid(DELL_DESCRIPTOR_GUID)) {
pr_warn("Dell WMI GUID were not found\n");
return -ENODEV;
}
err = dell_wmi_check_descriptor_buffer();
if (err)
return err;
err = dell_wmi_input_setup();
if (err)
return err;
status = wmi_install_notify_handler(DELL_EVENT_GUID,
dell_wmi_notify, NULL);
if (ACPI_FAILURE(status)) {
input_unregister_device(dell_wmi_input_dev);
pr_err("Unable to register notify handler - %d\n", status);
return -ENODEV;
}
dmi_check_system(dell_wmi_smbios_list);
if (wmi_requires_smbios_request) {
err = dell_wmi_events_set_enabled(true);
if (err) {
pr_err("Failed to enable WMI events\n");
wmi_remove_notify_handler(DELL_EVENT_GUID);
input_unregister_device(dell_wmi_input_dev);
return err;
}
}
return 0;
return wmi_driver_register(&dell_wmi_driver);
}
module_init(dell_wmi_init);
......@@ -761,7 +771,7 @@ static void __exit dell_wmi_exit(void)
{
if (wmi_requires_smbios_request)
dell_wmi_events_set_enabled(false);
wmi_remove_notify_handler(DELL_EVENT_GUID);
input_unregister_device(dell_wmi_input_dev);
wmi_driver_unregister(&dell_wmi_driver);
}
module_exit(dell_wmi_exit);
......@@ -445,7 +445,7 @@ static struct attribute *platform_attributes[] = {
NULL
};
static struct attribute_group platform_attribute_group = {
static const struct attribute_group platform_attribute_group = {
.attrs = platform_attributes
};
......
This diff is collapsed.
......@@ -423,9 +423,43 @@ static ssize_t store_ideapad_fan(struct device *dev,
static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
static ssize_t touchpad_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ideapad_private *priv = dev_get_drvdata(dev);
unsigned long result;
if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))
return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result);
}
/* Switch to RO for now: It might be revisited in the future */
static ssize_t __maybe_unused touchpad_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 = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
if (ret < 0)
return -EIO;
return count;
}
static DEVICE_ATTR_RO(touchpad);
static struct attribute *ideapad_attributes[] = {
&dev_attr_camera_power.attr,
&dev_attr_fan_mode.attr,
&dev_attr_touchpad.attr,
NULL
};
......@@ -478,7 +512,7 @@ static int ideapad_rfk_set(void *data, bool blocked)
return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
}
static struct rfkill_ops ideapad_rfk_ops = {
static const struct rfkill_ops ideapad_rfk_ops = {
.set_block = ideapad_rfk_set,
};
......@@ -810,7 +844,6 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
case 8:
case 7:
case 6:
case 1:
ideapad_input_report(priv, vpc_bit);
break;
case 5:
......@@ -828,6 +861,13 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
case 0:
ideapad_check_special_buttons(priv);
break;
case 1:
/* Some IdeaPads report event 1 every ~20
* seconds while on battery power; some
* report this when changing to/from tablet
* mode. Squelch this event.
*/
break;
default:
pr_info("Unknown event: %lu\n", vpc_bit);
}
......@@ -910,6 +950,20 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
},
},
{
.ident = "Lenovo Legion Y520-15IKBN",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"),
},
},
{
.ident = "Lenovo Legion Y720-15IKBN",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBN"),
},
},
{
.ident = "Lenovo Yoga 2 11 / 13 / Pro",
.matches = {
......
......@@ -34,6 +34,13 @@ struct cht_int33fe_data {
struct i2c_client *pi3usb30532;
};
static const char * const max17047_suppliers[] = { "bq24190-charger" };
static const struct property_entry max17047_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", max17047_suppliers),
{ }
};
static int cht_int33fe_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
......@@ -70,6 +77,7 @@ static int cht_int33fe_probe(struct i2c_client *client)
memset(&board_info, 0, sizeof(board_info));
strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
board_info.properties = max17047_props;
data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
if (!data->max17047)
......
......@@ -142,7 +142,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
return 0;
}
static struct thermal_cooling_device_ops memory_cooling_ops = {
static const struct thermal_cooling_device_ops memory_cooling_ops = {
.get_max_state = memory_get_max_bandwidth,
.get_cur_state = memory_get_cur_bandwidth,
.set_cur_state = memory_set_cur_bandwidth,
......
......@@ -186,7 +186,7 @@ static inline void ipc_data_writel(u32 data, u32 offset)
writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset);
}
static inline u8 ipc_data_readb(u32 offset)
static inline u8 __maybe_unused ipc_data_readb(u32 offset)
{
return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
}
......
......@@ -563,11 +563,11 @@ static struct attribute *msipf_old_attributes[] = {
NULL
};
static struct attribute_group msipf_attribute_group = {
static const struct attribute_group msipf_attribute_group = {
.attrs = msipf_attributes
};
static struct attribute_group msipf_old_attribute_group = {
static const struct attribute_group msipf_old_attribute_group = {
.attrs = msipf_old_attributes
};
......
......@@ -228,10 +228,6 @@ struct pcc_acpi {
struct backlight_device *backlight;
};
struct pcc_keyinput {
struct acpi_hotkey *hotkey;
};
/* method access functions */
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
{
......
/*
* PEAQ 2-in-1 WMI hotkey driver
* Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/acpi.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#define PEAQ_DOLBY_BUTTON_GUID "ABBC0F6F-8EA1-11D1-00A0-C90629100000"
#define PEAQ_DOLBY_BUTTON_METHOD_ID 5
#define PEAQ_POLL_INTERVAL_MS 250
#define PEAQ_POLL_IGNORE_MS 500
#define PEAQ_POLL_MAX_MS 1000
MODULE_ALIAS("wmi:"PEAQ_DOLBY_BUTTON_GUID);
static unsigned int peaq_ignore_events_counter;
static struct input_polled_dev *peaq_poll_dev;
/*
* The Dolby button (yes really a Dolby button) causes an ACPI variable to get
* set on both press and release. The WMI method checks and clears that flag.
* So for a press + release we will get back One from the WMI method either once
* (if polling after the release) or twice (polling between press and release).
* We ignore events for 0.5s after the first event to avoid reporting 2 presses.
*/
static void peaq_wmi_poll(struct input_polled_dev *dev)
{
union acpi_object obj;
acpi_status status;
u32 dummy = 0;
struct acpi_buffer input = { sizeof(dummy), &dummy };
struct acpi_buffer output = { sizeof(obj), &obj };
status = wmi_evaluate_method(PEAQ_DOLBY_BUTTON_GUID, 1,
PEAQ_DOLBY_BUTTON_METHOD_ID,
&input, &output);
if (ACPI_FAILURE(status))
return;
if (obj.type != ACPI_TYPE_INTEGER) {
dev_err(&peaq_poll_dev->input->dev,
"Error WMBC did not return an integer\n");
return;
}
if (peaq_ignore_events_counter && --peaq_ignore_events_counter > 0)
return;
if (obj.integer.value) {
input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 1);
input_sync(peaq_poll_dev->input);
input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 0);
input_sync(peaq_poll_dev->input);
peaq_ignore_events_counter = max(1u,
PEAQ_POLL_IGNORE_MS / peaq_poll_dev->poll_interval);
}
}
static int __init peaq_wmi_init(void)
{
if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
return -ENODEV;
peaq_poll_dev = input_allocate_polled_device();
if (!peaq_poll_dev)
return -ENOMEM;
peaq_poll_dev->poll = peaq_wmi_poll;
peaq_poll_dev->poll_interval = PEAQ_POLL_INTERVAL_MS;
peaq_poll_dev->poll_interval_max = PEAQ_POLL_MAX_MS;
peaq_poll_dev->input->name = "PEAQ WMI hotkeys";
peaq_poll_dev->input->phys = "wmi/input0";
peaq_poll_dev->input->id.bustype = BUS_HOST;
input_set_capability(peaq_poll_dev->input, EV_KEY, KEY_SOUND);
return input_register_polled_device(peaq_poll_dev);
}
static void __exit peaq_wmi_exit(void)
{
if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
return;
input_unregister_polled_device(peaq_poll_dev);
}
module_init(peaq_wmi_init);
module_exit(peaq_wmi_exit);
MODULE_DESCRIPTION("PEAQ 2-in-1 WMI hotkey driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL");
......@@ -591,7 +591,7 @@ static int seclinux_rfkill_set(void *data, bool blocked)
!blocked);
}
static struct rfkill_ops seclinux_rfkill_ops = {
static const struct rfkill_ops seclinux_rfkill_ops = {
.set_block = seclinux_rfkill_set,
};
......@@ -651,7 +651,7 @@ static void swsmi_rfkill_query(struct rfkill *rfkill, void *priv)
rfkill_set_sw_state(rfkill, !ret);
}
static struct rfkill_ops swsmi_rfkill_ops = {
static const struct rfkill_ops swsmi_rfkill_ops = {
.set_block = swsmi_rfkill_set,
.query = swsmi_rfkill_query,
};
......@@ -1446,9 +1446,9 @@ static int __init samsung_sabi_init(struct samsung_laptop *samsung)
const struct sabi_config *config = NULL;
const struct sabi_commands *commands;
unsigned int ifaceP;
int loca = 0xffff;
int ret = 0;
int i;
int loca;
samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff);
if (!samsung->f0000_segment) {
......
......@@ -80,6 +80,48 @@ static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
.properties = surftab_wintron70_st70416_6_props,
};
static const struct property_entry gp_electronic_t701_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl1680-gp-electronic-t701.fw"),
{ }
};
static const struct silead_ts_dmi_data gp_electronic_t701_data = {
.acpi_name = "MSSL1680:00",
.properties = gp_electronic_t701_props,
};
static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl1680-pipo-w2s.fw"),
{ }
};
static const struct silead_ts_dmi_data pipo_w2s_data = {
.acpi_name = "MSSL1680:00",
.properties = pipo_w2s_props,
};
static const struct property_entry pov_mobii_wintab_p800w_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl3692-pov-mobii-wintab-p800w.fw"),
{ }
};
static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
.acpi_name = "MSSL1680:00",
.properties = pov_mobii_wintab_p800w_props,
};
static const struct dmi_system_id silead_ts_dmi_table[] = {
{
/* CUBE iwork8 Air */
......@@ -117,6 +159,34 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
},
},
{
/* GP-electronic T701 */
.driver_data = (void *)&gp_electronic_t701_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
},
},
{
/* Pipo W2S */
.driver_data = (void *)&pipo_w2s_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
},
},
{
/* Point of View mobii wintab p800w */
.driver_data = (void *)&pov_mobii_wintab_p800w_data,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
/* Above matches are too generic, add bios-date match */
DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
},
},
{ },
};
......
......@@ -222,7 +222,7 @@ struct sony_laptop_keypress {
/* Correspondance table between sonypi events
* and input layer indexes in the keymap
*/
static int sony_laptop_input_index[] = {
static const int sony_laptop_input_index[] = {
-1, /* 0 no event */
-1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */
-1, /* 2 SONYPI_EVENT_JOGDIAL_UP */
......@@ -4032,7 +4032,7 @@ static struct attribute *spic_attributes[] = {
NULL
};
static struct attribute_group spic_attribute_group = {
static const struct attribute_group spic_attribute_group = {
.attrs = spic_attributes
};
......
This diff is collapsed.
......@@ -162,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device)
}
static const struct acpi_device_id topstar_device_ids[] = {
{ "TPS0001", 0 },
{ "TPSACPI01", 0 },
{ "", 0 },
};
......
......@@ -1502,14 +1502,9 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
int ret;
u32 video_out;
cmd = kmalloc(count + 1, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
if (copy_from_user(cmd, buf, count)) {
kfree(cmd);
return -EFAULT;
}
cmd[count] = '\0';
cmd = memdup_user_nul(buf, count);
if (IS_ERR(cmd))
return PTR_ERR(cmd);
buffer = cmd;
......
......@@ -132,7 +132,7 @@ static struct attribute *haps_attributes[] = {
NULL,
};
static struct attribute_group haps_attr_group = {
static const struct attribute_group haps_attr_group = {
.attrs = haps_attributes,
};
......
/*
* WMI embedded Binary MOF driver
*
* Copyright (c) 2015 Andrew Lutomirski
* Copyright (C) 2017 VMware, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* 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/acpi.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/wmi.h>
#define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910"
struct bmof_priv {
union acpi_object *bmofdata;
struct bin_attribute bmof_bin_attr;
};
static ssize_t
read_bmof(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct bmof_priv *priv =
container_of(attr, struct bmof_priv, bmof_bin_attr);
if (off < 0)
return -EINVAL;
if (off >= priv->bmofdata->buffer.length)
return 0;
if (count > priv->bmofdata->buffer.length - off)
count = priv->bmofdata->buffer.length - off;
memcpy(buf, priv->bmofdata->buffer.pointer + off, count);
return count;
}
static int wmi_bmof_probe(struct wmi_device *wdev)
{
struct bmof_priv *priv;
int ret;
priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
dev_set_drvdata(&wdev->dev, priv);
priv->bmofdata = wmidev_block_query(wdev, 0);
if (!priv->bmofdata) {
dev_err(&wdev->dev, "failed to read Binary MOF\n");
return -EIO;
}
if (priv->bmofdata->type != ACPI_TYPE_BUFFER) {
dev_err(&wdev->dev, "Binary MOF is not a buffer\n");
ret = -EIO;
goto err_free;
}
sysfs_bin_attr_init(&priv->bmof_bin_attr);
priv->bmof_bin_attr.attr.name = "bmof";
priv->bmof_bin_attr.attr.mode = 0400;
priv->bmof_bin_attr.read = read_bmof;
priv->bmof_bin_attr.size = priv->bmofdata->buffer.length;
ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr);
if (ret)
goto err_free;
return 0;
err_free:
kfree(priv->bmofdata);
return ret;
}
static int wmi_bmof_remove(struct wmi_device *wdev)
{
struct bmof_priv *priv = dev_get_drvdata(&wdev->dev);
sysfs_remove_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr);
kfree(priv->bmofdata);
return 0;
}
static const struct wmi_device_id wmi_bmof_id_table[] = {
{ .guid_string = WMI_BMOF_GUID },
{ },
};
static struct wmi_driver wmi_bmof_driver = {
.driver = {
.name = "wmi-bmof",
},
.probe = wmi_bmof_probe,
.remove = wmi_bmof_remove,
.id_table = wmi_bmof_id_table,
};
module_wmi_driver(wmi_bmof_driver);
MODULE_ALIAS("wmi:" WMI_BMOF_GUID);
MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>");
MODULE_DESCRIPTION("WMI embedded Binary MOF driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
/*
* wmi.h - ACPI WMI interface
*
* Copyright (c) 2015 Andrew Lutomirski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#ifndef _LINUX_WMI_H
#define _LINUX_WMI_H
#include <linux/device.h>
#include <linux/acpi.h>
struct wmi_device {
struct device dev;
/* True for data blocks implementing the Set Control Method */
bool setable;
};
/* Caller must kfree the result. */
extern union acpi_object *wmidev_block_query(struct wmi_device *wdev,
u8 instance);
/* Gets another device on the same bus. Caller must put_device the result. */
extern struct wmi_device *wmidev_get_other_guid(struct wmi_device *wdev,
const char *guid_string);
struct wmi_device_id {
const char *guid_string;
};
struct wmi_driver {
struct device_driver driver;
const struct wmi_device_id *id_table;
int (*probe)(struct wmi_device *wdev);
int (*remove)(struct wmi_device *wdev);
void (*notify)(struct wmi_device *device, union acpi_object *data);
};
extern int __must_check __wmi_driver_register(struct wmi_driver *driver,
struct module *owner);
extern void wmi_driver_unregister(struct wmi_driver *driver);
#define wmi_driver_register(driver) __wmi_driver_register((driver), THIS_MODULE)
#define module_wmi_driver(__wmi_driver) \
module_driver(__wmi_driver, wmi_driver_register, \
wmi_driver_unregister)
#endif
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