summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-20 12:02:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-20 12:02:24 -0700
commitda6b5aae84beb0917ecb0c9fbc71169d145397ff (patch)
tree20d39405eb2d710a2beae5a51ff9d4c92009a554 /drivers
parentb69e478512080f9bb03ed3e812b759bb73e2837b (diff)
parent344bf523d441d44c75c429ea6cdcfa8f12efde4d (diff)
Merge tag 'platform-drivers-x86-v7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Ilpo Järvinen: "asus-wmi: - Retain battery charge threshold during boot which avoids unsolicited change to 100%. Return -ENODATA when the limit is not yet known - Improve screenpad power/brightness handling consistency - Fix screenpad brightness range barco-p50-gpio: - Normalize gpio_get return values bitland-mifs-wmi: - Add driver for Bitland laptops (supports platform profile, hwmon, kbd backlight, gpu mode, hotkeys, and fan boost) dell_rbu: - Fix using uninitialized value in sysfs write function dell-wmi-sysman: - Respect destination length when constructing enum strings hp-wmi: - Propagate fan setting apply failures and log an error - Fix sysfs write vs work handler cancel_delayed_work_sync() deadlock - Correct keepalive schedule_delayed_work() to mod_delayed_work() - Fix u8 underflows in GPU delta calculation - Use mutex to protect fan pwm/mode - Ignore kbd backlight and FnLock key events that are handled by FW - Fix fan table parsing (use correct field) - Add support for Omen 14-fb0xxx, 16-n0xxx, 16-wf1xxx, and Omen MAX 16-ak0xxxx input: trackpoint & thinkpad_acpi: - Enable doubletap by default and add sysfs enable/disable int3472: - Add support for GPIO type 0x02 (IR flood LED) intel-speed-select: (updated to v1.26) - Avoid using current base frequency as maximum - Fix CPU extended family ID decoding - Fix exit code - Improve error reporting intel/vsec: - Refactor to support ACPI-enumerated PMT endpoints. pcengines-apuv2: - Attach software node to the gpiochip uniwill: - Refactor hwmon to smaller parts to accomodate HW diversity - Support USB-C power/performance priority switch through sysfs - Add another XMG Fusion 15 (L19) DMI vendor - Enable fine-grained features to device lineup mapping wmi: - Perform output size check within WMI core to allow simpler WMI drivers misc: - acpi_driver -> platform driver conversions (a large number of changes from Rafael J. Wysocki) - cleanups / refactoring / improvements" * tag 'platform-drivers-x86-v7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (106 commits) platform/x86: hp-wmi: Add support for Omen 16-wf1xxx (8C77) platform/x86: hp-wmi: Add support for Omen 16-n0xxx (8A44) platform/x86: hp-wmi: Add support for OMEN MAX 16-ak0xxx (8D87) platform/x86: hp-wmi: fix fan table parsing platform/x86: hp-wmi: add Omen 14-fb0xxx (board 8C58) support platform/wmi: Replace .no_notify_data with .min_event_size platform/wmi: Extend wmidev_query_block() to reject undersized data platform/wmi: Extend wmidev_invoke_method() to reject undersized data platform/wmi: Prepare to reject undersized unmarshalling results platform/wmi: Convert drivers to use wmidev_invoke_procedure() platform/wmi: Add wmidev_invoke_procedure() platform/x86: int3472: Add support for GPIO type 0x02 (IR flood LED) platform/x86: int3472: Parameterize LED con_id in registration platform/x86: int3472: Rename pled to led in LED registration code platform/x86: int3472: Use local variable for LED struct access platform/x86: thinkpad_acpi: remove obsolete TODO comment platform/x86: dell-wmi-sysman: bound enumeration string aggregation platform/x86: hp-wmi: Ignore backlight and FnLock events platform/x86: uniwill-laptop: Fix signedness bug platform/x86: dell_rbu: avoid uninit value usage in packet_size_write() ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/xe/xe_debugfs.c2
-rw-r--r--drivers/gpu/drm/xe/xe_hwmon.c2
-rw-r--r--drivers/gpu/drm/xe/xe_vsec.c7
-rw-r--r--drivers/gpu/drm/xe/xe_vsec.h4
-rw-r--r--drivers/input/mouse/trackpoint.c46
-rw-r--r--drivers/input/mouse/trackpoint.h5
-rw-r--r--drivers/platform/mellanox/nvsw-sn2201.c1
-rw-r--r--drivers/platform/surface/surface_hotplug.c2
-rw-r--r--drivers/platform/surface/surfacepro3_button.c71
-rw-r--r--drivers/platform/wmi/core.c89
-rw-r--r--drivers/platform/wmi/internal.h3
-rw-r--r--drivers/platform/wmi/marshalling.c6
-rw-r--r--drivers/platform/wmi/tests/marshalling_kunit.c24
-rw-r--r--drivers/platform/x86/Kconfig18
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wireless.c48
-rw-r--r--drivers/platform/x86/asus-laptop.c44
-rw-r--r--drivers/platform/x86/asus-wireless.c55
-rw-r--r--drivers/platform/x86/asus-wmi.c77
-rw-r--r--drivers/platform/x86/barco-p50-gpio.c23
-rw-r--r--drivers/platform/x86/bitland-mifs-wmi.c837
-rw-r--r--drivers/platform/x86/dell/dell-rbtn.c142
-rw-r--r--drivers/platform/x86/dell/dell-wmi-base.c1
-rw-r--r--drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h4
-rw-r--r--drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c34
-rw-r--r--drivers/platform/x86/dell/dell-wmi-sysman/sysman.c68
-rw-r--r--drivers/platform/x86/dell/dell_rbu.c6
-rw-r--r--drivers/platform/x86/eeepc-laptop.c45
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c489
-rw-r--r--drivers/platform/x86/fujitsu-tablet.c30
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c125
-rw-r--r--drivers/platform/x86/intel/int3472/discrete.c13
-rw-r--r--drivers/platform/x86/intel/int3472/led.c55
-rw-r--r--drivers/platform/x86/intel/pmc/core.c4
-rw-r--r--drivers/platform/x86/intel/pmc/ssram_telemetry.c2
-rw-r--r--drivers/platform/x86/intel/pmt/class.c8
-rw-r--r--drivers/platform/x86/intel/pmt/class.h5
-rw-r--r--drivers/platform/x86/intel/pmt/discovery.c4
-rw-r--r--drivers/platform/x86/intel/pmt/telemetry.c13
-rw-r--r--drivers/platform/x86/intel/pmt/telemetry.h12
-rw-r--r--drivers/platform/x86/intel/rst.c23
-rw-r--r--drivers/platform/x86/intel/sdsi.c5
-rw-r--r--drivers/platform/x86/intel/smartconnect.c23
-rw-r--r--drivers/platform/x86/intel/vsec.c121
-rw-r--r--drivers/platform/x86/intel/vsec_tpmi.c12
-rw-r--r--drivers/platform/x86/intel/wmi/sbl-fw-update.c7
-rw-r--r--drivers/platform/x86/intel/wmi/thunderbolt.c2
-rw-r--r--drivers/platform/x86/lenovo/ideapad-laptop.c1
-rw-r--r--drivers/platform/x86/lenovo/thinkpad_acpi.c193
-rw-r--r--drivers/platform/x86/lenovo/wmi-camera.c1
-rw-r--r--drivers/platform/x86/lenovo/wmi-events.c1
-rw-r--r--drivers/platform/x86/lenovo/ymc.c1
-rw-r--r--drivers/platform/x86/lenovo/yogabook.c2
-rw-r--r--drivers/platform/x86/lg-laptop.c51
-rw-r--r--drivers/platform/x86/mxm-wmi.c12
-rw-r--r--drivers/platform/x86/panasonic-laptop.c79
-rw-r--r--drivers/platform/x86/pcengines-apuv2.c3
-rw-r--r--drivers/platform/x86/redmi-wmi.c1
-rw-r--r--drivers/platform/x86/sony-laptop.c122
-rw-r--r--drivers/platform/x86/system76_acpi.c63
-rw-r--r--drivers/platform/x86/topstar-laptop.c43
-rw-r--r--drivers/platform/x86/toshiba_acpi.c182
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c74
-rw-r--r--drivers/platform/x86/toshiba_haps.c57
-rw-r--r--drivers/platform/x86/uniwill/uniwill-acpi.c440
-rw-r--r--drivers/platform/x86/uniwill/uniwill-wmi.c1
-rw-r--r--drivers/platform/x86/wireless-hotkey.c49
-rw-r--r--drivers/platform/x86/wmi-bmof.c2
-rw-r--r--drivers/platform/x86/xiaomi-wmi.c1
69 files changed, 2727 insertions, 1270 deletions
diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 844cfafe1ec7..ad2d8f179eb6 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -45,7 +45,7 @@ static void read_residency_counter(struct xe_device *xe, struct xe_mmio *mmio,
u64 residency = 0;
int ret;
- ret = xe_pmt_telem_read(to_pci_dev(xe->drm.dev),
+ ret = xe_pmt_telem_read(xe->drm.dev,
xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID),
&residency, offset, sizeof(residency));
if (ret != sizeof(residency)) {
diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
index 0fd4d4f1014a..92e423a339f1 100644
--- a/drivers/gpu/drm/xe/xe_hwmon.c
+++ b/drivers/gpu/drm/xe/xe_hwmon.c
@@ -506,7 +506,7 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy)
if (hwmon->xe->info.platform == XE_BATTLEMAGE) {
u64 pmt_val;
- ret = xe_pmt_telem_read(to_pci_dev(hwmon->xe->drm.dev),
+ ret = xe_pmt_telem_read(hwmon->xe->drm.dev,
xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID),
&pmt_val, BMG_ENERGY_STATUS_PMT_OFFSET, sizeof(pmt_val));
if (ret != sizeof(pmt_val)) {
diff --git a/drivers/gpu/drm/xe/xe_vsec.c b/drivers/gpu/drm/xe/xe_vsec.c
index 4ebb4dbe1c9b..a9baf0bfe572 100644
--- a/drivers/gpu/drm/xe/xe_vsec.c
+++ b/drivers/gpu/drm/xe/xe_vsec.c
@@ -140,10 +140,10 @@ static int xe_guid_decode(u32 guid, int *index, u32 *offset)
return 0;
}
-int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset,
+int xe_pmt_telem_read(struct device *dev, u32 guid, u64 *data, loff_t user_offset,
u32 count)
{
- struct xe_device *xe = pdev_to_xe_device(pdev);
+ struct xe_device *xe = kdev_to_xe_device(dev);
void __iomem *telem_addr = xe->mmio.regs + BMG_TELEMETRY_OFFSET;
u32 mem_region;
u32 offset;
@@ -198,7 +198,6 @@ void xe_vsec_init(struct xe_device *xe)
{
struct intel_vsec_platform_info *info;
struct device *dev = xe->drm.dev;
- struct pci_dev *pdev = to_pci_dev(dev);
enum xe_vsec platform;
platform = get_platform_info(xe);
@@ -221,6 +220,6 @@ void xe_vsec_init(struct xe_device *xe)
* Register a VSEC. Cleanup is handled using device managed
* resources.
*/
- intel_vsec_register(pdev, info);
+ intel_vsec_register(dev, info);
}
MODULE_IMPORT_NS("INTEL_VSEC");
diff --git a/drivers/gpu/drm/xe/xe_vsec.h b/drivers/gpu/drm/xe/xe_vsec.h
index dabfb4e02d70..a25b4e6e681b 100644
--- a/drivers/gpu/drm/xe/xe_vsec.h
+++ b/drivers/gpu/drm/xe/xe_vsec.h
@@ -6,10 +6,10 @@
#include <linux/types.h>
-struct pci_dev;
+struct device;
struct xe_device;
void xe_vsec_init(struct xe_device *xe);
-int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset, u32 count);
+int xe_pmt_telem_read(struct device *dev, u32 guid, u64 *data, loff_t user_offset, u32 count);
#endif
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index b06c7ad721fe..3bd8fdf56cd3 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -5,6 +5,7 @@
* Trademarks are the property of their respective owners.
*/
+#include <linux/array_size.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/serio.h>
@@ -12,6 +13,7 @@
#include <linux/input.h>
#include <linux/libps2.h>
#include <linux/proc_fs.h>
+#include <linux/string.h>
#include <linux/uaccess.h>
#include "psmouse.h"
#include "trackpoint.h"
@@ -393,6 +395,44 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
return 0;
}
+/* List of known incapable device PNP IDs */
+static const char * const dt_incompatible_devices[] = {
+ "LEN0304",
+ "LEN0306",
+ "LEN0317",
+ "LEN031A",
+ "LEN031B",
+ "LEN031C",
+ "LEN031D",
+};
+
+/*
+ * Checks if it's a doubletap capable device.
+ * The PNP ID format is "PNP: LEN030d PNP0f13".
+ */
+static bool trackpoint_is_dt_capable(const char *pnp_id)
+{
+ size_t i;
+
+ if (!pnp_id)
+ return false;
+
+ /* Must start with "PNP: LEN03" */
+ if (!strstarts(pnp_id, "PNP: LEN03"))
+ return false;
+
+ /* Ensure enough length before comparing */
+ if (strlen(pnp_id) < 12)
+ return false;
+
+ /* Check deny-list */
+ for (i = 0; i < ARRAY_SIZE(dt_incompatible_devices); i++) {
+ if (!strncmp(pnp_id + 5, dt_incompatible_devices[i], 7))
+ return false;
+ }
+ return true;
+}
+
int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -470,6 +510,12 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse->vendor, firmware_id,
(button_info & 0xf0) >> 4, button_info & 0x0f);
+ if (trackpoint_is_dt_capable(ps2dev->serio->firmware_id)) {
+ error = trackpoint_write(ps2dev, TP_DOUBLETAP, TP_DOUBLETAP_ENABLE);
+ if (error)
+ psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error);
+ }
+
return 0;
}
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index eb5412904fe0..3e03cdb39449 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -69,6 +69,8 @@
/* (how hard it is to drag */
/* with Z-axis pressed) */
+#define TP_DOUBLETAP 0x58 /* TrackPoint doubletap register */
+
#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
/* to trigger dragging */
@@ -110,6 +112,9 @@
external device will be forced to 1 */
#define TP_MASK_EXT_TAG 0x04
+/* Doubletap register values */
+#define TP_DOUBLETAP_ENABLE 0xFF /* Enable value */
+#define TP_DOUBLETAP_DISABLE 0xFE /* Disable value */
/* Power on Self Test Results */
#define TP_POR_SUCCESS 0x3B
diff --git a/drivers/platform/mellanox/nvsw-sn2201.c b/drivers/platform/mellanox/nvsw-sn2201.c
index 51504113c17e..92b58ba8f97b 100644
--- a/drivers/platform/mellanox/nvsw-sn2201.c
+++ b/drivers/platform/mellanox/nvsw-sn2201.c
@@ -10,7 +10,6 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/platform_data/mlxcpld.h>
#include <linux/platform_data/mlxreg.h>
diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
index c0d83ed5a208..33a8a9d41900 100644
--- a/drivers/platform/surface/surface_hotplug.c
+++ b/drivers/platform/surface/surface_hotplug.c
@@ -14,7 +14,7 @@
*/
#include <linux/acpi.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/platform/surface/surfacepro3_button.c b/drivers/platform/surface/surfacepro3_button.c
index 9bd39f09c7db..0293bc517b54 100644
--- a/drivers/platform/surface/surfacepro3_button.c
+++ b/drivers/platform/surface/surfacepro3_button.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/input.h>
#include <linux/acpi.h>
+#include <linux/platform_device.h>
#include <acpi/button.h>
#define SURFACE_PRO3_BUTTON_HID "MSHW0028"
@@ -72,9 +73,10 @@ struct surface_button {
bool suspended;
};
-static void surface_button_notify(struct acpi_device *device, u32 event)
+static void surface_button_notify(acpi_handle handle, u32 event, void *data)
{
- struct surface_button *button = acpi_driver_data(device);
+ struct device *dev = data;
+ struct surface_button *button = dev_get_drvdata(dev);
struct input_dev *input;
int key_code = KEY_RESERVED;
bool pressed = false;
@@ -109,18 +111,17 @@ static void surface_button_notify(struct acpi_device *device, u32 event)
key_code = KEY_VOLUMEDOWN;
break;
case SURFACE_BUTTON_NOTIFY_TABLET_MODE:
- dev_warn_once(&device->dev, "Tablet mode is not supported\n");
+ dev_warn_once(dev, "Tablet mode is not supported\n");
break;
default:
- dev_info_ratelimited(&device->dev,
- "Unsupported event [0x%x]\n", event);
+ dev_info_ratelimited(dev, "Unsupported event [0x%x]\n", event);
break;
}
input = button->input;
if (key_code == KEY_RESERVED)
return;
if (pressed)
- pm_wakeup_dev_event(&device->dev, 0, button->suspended);
+ pm_wakeup_dev_event(dev, 0, button->suspended);
if (button->suspended)
return;
input_report_key(input, key_code, pressed?1:0);
@@ -130,8 +131,7 @@ static void surface_button_notify(struct acpi_device *device, u32 event)
#ifdef CONFIG_PM_SLEEP
static int surface_button_suspend(struct device *dev)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct surface_button *button = acpi_driver_data(device);
+ struct surface_button *button = dev_get_drvdata(dev);
button->suspended = true;
return 0;
@@ -139,8 +139,7 @@ static int surface_button_suspend(struct device *dev)
static int surface_button_resume(struct device *dev)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct surface_button *button = acpi_driver_data(device);
+ struct surface_button *button = dev_get_drvdata(dev);
button->suspended = false;
return 0;
@@ -155,9 +154,8 @@ static int surface_button_resume(struct device *dev)
* Returns true if the driver should bind to this device, i.e. the device is
* either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
*/
-static bool surface_button_check_MSHW0040(struct acpi_device *dev)
+static bool surface_button_check_MSHW0040(struct device *dev, acpi_handle handle)
{
- acpi_handle handle = dev->handle;
union acpi_object *result;
u64 oem_platform_rev = 0; // valid revisions are nonzero
@@ -179,14 +177,15 @@ static bool surface_button_check_MSHW0040(struct acpi_device *dev)
ACPI_FREE(result);
}
- dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
+ dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
return oem_platform_rev == 0;
}
-static int surface_button_add(struct acpi_device *device)
+static int surface_button_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct surface_button *button;
struct input_dev *input;
const char *hid = acpi_device_hid(device);
@@ -196,14 +195,14 @@ static int surface_button_add(struct acpi_device *device)
strlen(SURFACE_BUTTON_OBJ_NAME)))
return -ENODEV;
- if (!surface_button_check_MSHW0040(device))
+ if (!surface_button_check_MSHW0040(&pdev->dev, device->handle))
return -ENODEV;
button = kzalloc_obj(struct surface_button);
if (!button)
return -ENOMEM;
- device->driver_data = button;
+ platform_set_drvdata(pdev, button);
button->input = input = input_allocate_device();
if (!input) {
error = -ENOMEM;
@@ -216,7 +215,7 @@ static int surface_button_add(struct acpi_device *device)
input->name = acpi_device_name(device);
input->phys = button->phys;
input->id.bustype = BUS_HOST;
- input->dev.parent = &device->dev;
+ input->dev.parent = &pdev->dev;
input_set_capability(input, EV_KEY, KEY_POWER);
input_set_capability(input, EV_KEY, KEY_LEFTMETA);
input_set_capability(input, EV_KEY, KEY_VOLUMEUP);
@@ -226,8 +225,17 @@ static int surface_button_add(struct acpi_device *device)
if (error)
goto err_free_input;
- device_init_wakeup(&device->dev, true);
- dev_info(&device->dev, "%s [%s]\n", acpi_device_name(device),
+ device_init_wakeup(&pdev->dev, true);
+
+ error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ surface_button_notify, &pdev->dev);
+ if (error) {
+ device_init_wakeup(&pdev->dev, false);
+ input_unregister_device(input);
+ goto err_free_button;
+ }
+
+ dev_info(&pdev->dev, "%s [%s]\n", acpi_device_name(device),
acpi_device_bid(device));
return 0;
@@ -238,10 +246,13 @@ static int surface_button_add(struct acpi_device *device)
return error;
}
-static void surface_button_remove(struct acpi_device *device)
+static void surface_button_remove(struct platform_device *pdev)
{
- struct surface_button *button = acpi_driver_data(device);
+ struct surface_button *button = platform_get_drvdata(pdev);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, surface_button_notify);
+ device_init_wakeup(&pdev->dev, false);
input_unregister_device(button->input);
kfree(button);
}
@@ -249,16 +260,14 @@ static void surface_button_remove(struct acpi_device *device)
static SIMPLE_DEV_PM_OPS(surface_button_pm,
surface_button_suspend, surface_button_resume);
-static struct acpi_driver surface_button_driver = {
- .name = "surface_pro3_button",
- .class = "SurfacePro3",
- .ids = surface_button_device_ids,
- .ops = {
- .add = surface_button_add,
- .remove = surface_button_remove,
- .notify = surface_button_notify,
+static struct platform_driver surface_button_driver = {
+ .probe = surface_button_probe,
+ .remove = surface_button_remove,
+ .driver = {
+ .name = "surface_pro3_button",
+ .acpi_match_table = surface_button_device_ids,
+ .pm = &surface_button_pm,
},
- .drv.pm = &surface_button_pm,
};
-module_acpi_driver(surface_button_driver);
+module_platform_driver(surface_button_driver);
diff --git a/drivers/platform/wmi/core.c b/drivers/platform/wmi/core.c
index 750e3619724e..7aa40dab6145 100644
--- a/drivers/platform/wmi/core.c
+++ b/drivers/platform/wmi/core.c
@@ -364,20 +364,23 @@ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 met
EXPORT_SYMBOL_GPL(wmidev_evaluate_method);
/**
- * wmidev_invoke_method - Invoke a WMI method
+ * wmidev_invoke_method - Invoke a WMI method that returns values
* @wdev: A wmi bus device from a driver
* @instance: Instance index
* @method_id: Method ID to call
* @in: Mandatory WMI buffer containing input for the method call
- * @out: Optional WMI buffer to return the method results
+ * @out: Mandatory WMI buffer to return the method results
+ * @min_size: Minimum size of the method result data in bytes
*
- * Invoke a WMI method, the caller must free the resulting data inside @out.
- * Said data is guaranteed to be aligned on a 8-byte boundary.
+ * Invoke a WMI method that returns values, the caller must free the resulting
+ * data inside @out using kfree(). Said data is guaranteed to be aligned on a
+ * 8-byte boundary. Use wmidev_invoke_procedure() for WMI methods that
+ * return no values.
*
* Return: 0 on success or negative error code on failure.
*/
int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
- const struct wmi_buffer *in, struct wmi_buffer *out)
+ const struct wmi_buffer *in, struct wmi_buffer *out, size_t min_size)
{
struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
struct acpi_buffer aout = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -398,10 +401,7 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
ain.pointer = in->data;
}
- if (out)
- status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout);
- else
- status = wmidev_evaluate_method(wdev, instance, method_id, &ain, NULL);
+ status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout);
if (wblock->gblock.flags & ACPI_WMI_STRING)
kfree(ain.pointer);
@@ -409,9 +409,6 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
if (ACPI_FAILURE(status))
return -EIO;
- if (!out)
- return 0;
-
obj = aout.pointer;
if (!obj) {
out->length = 0;
@@ -420,13 +417,57 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
return 0;
}
- ret = wmi_unmarshal_acpi_object(obj, out);
+ ret = wmi_unmarshal_acpi_object(obj, out, min_size);
kfree(obj);
return ret;
}
EXPORT_SYMBOL_GPL(wmidev_invoke_method);
+/**
+ * wmidev_invoke_procedure - Invoke a WMI method that does not return values
+ * @wdev: A wmi bus device from a driver
+ * @instance: Instance index
+ * @method_id: Method ID to call
+ * @in: Mandatory WMI buffer containing input for the method call
+ *
+ * Invoke a WMI method that does not return any values. Use wmidev_invoke_method()
+ * for WMI methods that do return values.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int wmidev_invoke_procedure(struct wmi_device *wdev, u8 instance, u32 method_id,
+ const struct wmi_buffer *in)
+{
+ struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
+ struct acpi_buffer ain;
+ acpi_status status;
+ int ret;
+
+ if (wblock->gblock.flags & ACPI_WMI_STRING) {
+ ret = wmi_marshal_string(in, &ain);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (in->length > U32_MAX)
+ return -E2BIG;
+
+ ain.length = in->length;
+ ain.pointer = in->data;
+ }
+
+ status = wmidev_evaluate_method(wdev, instance, method_id, &ain, NULL);
+
+ if (wblock->gblock.flags & ACPI_WMI_STRING)
+ kfree(ain.pointer);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wmidev_invoke_procedure);
+
static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
struct acpi_buffer *out)
{
@@ -524,13 +565,15 @@ EXPORT_SYMBOL_GPL(wmidev_block_query);
* @wdev: A wmi bus device from a driver
* @instance: Instance index
* @out: WMI buffer to fill
+ * @min_size: Minimum size of the result data in bytes
*
- * Query a WMI data block, the caller must free the resulting data inside @out.
- * Said data is guaranteed to be aligned on a 8-byte boundary.
+ * Query a WMI data block, the caller must free the resulting data inside @out
+ * using kfree(). Said data is guaranteed to be aligned on a 8-byte boundary.
*
* Return: 0 on success or a negative error code on failure.
*/
-int wmidev_query_block(struct wmi_device *wdev, u8 instance, struct wmi_buffer *out)
+int wmidev_query_block(struct wmi_device *wdev, u8 instance, struct wmi_buffer *out,
+ size_t min_size)
{
union acpi_object *obj;
int ret;
@@ -539,7 +582,7 @@ int wmidev_query_block(struct wmi_device *wdev, u8 instance, struct wmi_buffer *
if (!obj)
return -EIO;
- ret = wmi_unmarshal_acpi_object(obj, out);
+ ret = wmi_unmarshal_acpi_object(obj, out, min_size);
kfree(obj);
return ret;
@@ -970,7 +1013,7 @@ static int wmi_dev_probe(struct device *dev)
}
if (wdriver->notify || wdriver->notify_new) {
- if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && !wdriver->no_notify_data)
+ if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && wdriver->min_event_size)
return -ENODEV;
}
@@ -1329,10 +1372,14 @@ static int wmi_get_notify_data(struct wmi_block *wblock, union acpi_object **obj
static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)
{
struct wmi_driver *driver = to_wmi_driver(wblock->dev.dev.driver);
+ struct wmi_buffer dummy = {
+ .length = 0,
+ .data = ZERO_SIZE_PTR,
+ };
struct wmi_buffer buffer;
int ret;
- if (!obj && !driver->no_notify_data) {
+ if (!obj && driver->min_event_size) {
dev_warn(&wblock->dev.dev, "Event contains no event data\n");
return;
}
@@ -1342,11 +1389,11 @@ static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)
if (driver->notify_new) {
if (!obj) {
- driver->notify_new(&wblock->dev, NULL);
+ driver->notify_new(&wblock->dev, &dummy);
return;
}
- ret = wmi_unmarshal_acpi_object(obj, &buffer);
+ ret = wmi_unmarshal_acpi_object(obj, &buffer, driver->min_event_size);
if (ret < 0) {
dev_warn(&wblock->dev.dev, "Failed to unmarshal event data: %d\n", ret);
return;
diff --git a/drivers/platform/wmi/internal.h b/drivers/platform/wmi/internal.h
index 9a39ffa31ad1..c02908694563 100644
--- a/drivers/platform/wmi/internal.h
+++ b/drivers/platform/wmi/internal.h
@@ -11,7 +11,8 @@
union acpi_object;
struct wmi_buffer;
-int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer);
+int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer,
+ size_t min_size);
int wmi_marshal_string(const struct wmi_buffer *buffer, struct acpi_buffer *out);
#endif /* _WMI_INTERNAL_H_ */
diff --git a/drivers/platform/wmi/marshalling.c b/drivers/platform/wmi/marshalling.c
index 63a92c4ebab5..87091832568e 100644
--- a/drivers/platform/wmi/marshalling.c
+++ b/drivers/platform/wmi/marshalling.c
@@ -151,7 +151,8 @@ static int wmi_obj_transform(const union acpi_object *obj, u8 *buffer)
return 0;
}
-int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer)
+int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer,
+ size_t min_size)
{
size_t length, alloc_length;
u8 *data;
@@ -161,6 +162,9 @@ int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *b
if (ret < 0)
return ret;
+ if (length < min_size)
+ return -ENODATA;
+
if (ARCH_KMALLOC_MINALIGN < 8) {
/*
* kmalloc() guarantees that the alignment of the resulting memory allocation is at
diff --git a/drivers/platform/wmi/tests/marshalling_kunit.c b/drivers/platform/wmi/tests/marshalling_kunit.c
index 0c7cd8774aa3..471963076d58 100644
--- a/drivers/platform/wmi/tests/marshalling_kunit.c
+++ b/drivers/platform/wmi/tests/marshalling_kunit.c
@@ -372,7 +372,7 @@ static void wmi_unmarshal_acpi_object_test(struct kunit *test)
struct wmi_buffer result;
int ret;
- ret = wmi_unmarshal_acpi_object(&param->obj, &result);
+ ret = wmi_unmarshal_acpi_object(&param->obj, &result, param->buffer.length);
if (ret < 0)
KUNIT_FAIL_AND_ABORT(test, "Unmarshalling of ACPI object failed\n");
@@ -389,7 +389,7 @@ static void wmi_unmarshal_acpi_object_failure_test(struct kunit *test)
struct wmi_buffer result;
int ret;
- ret = wmi_unmarshal_acpi_object(&param->obj, &result);
+ ret = wmi_unmarshal_acpi_object(&param->obj, &result, 0);
if (ret < 0)
return;
@@ -427,6 +427,25 @@ static void wmi_marshal_string_failure_test(struct kunit *test)
KUNIT_FAIL(test, "Invalid string was not rejected\n");
}
+static void wmi_unmarshal_acpi_object_undersized_test(struct kunit *test)
+{
+ const union acpi_object obj = {
+ .integer = {
+ .type = ACPI_TYPE_INTEGER,
+ .value = 0xdeadbeef,
+ },
+ };
+ struct wmi_buffer result;
+ int ret;
+
+ ret = wmi_unmarshal_acpi_object(&obj, &result, sizeof(expected_single_integer) + 1);
+ if (ret < 0)
+ return;
+
+ kfree(result.data);
+ KUNIT_FAIL(test, "Undersized unmarshalling result was not rejected\n");
+}
+
static struct kunit_case wmi_marshalling_test_cases[] = {
KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_test,
wmi_unmarshal_acpi_object_gen_params),
@@ -436,6 +455,7 @@ static struct kunit_case wmi_marshalling_test_cases[] = {
wmi_unmarshal_acpi_object_failure_gen_params),
KUNIT_CASE_PARAM(wmi_marshal_string_failure_test,
wmi_marshal_string_failure_gen_params),
+ KUNIT_CASE(wmi_unmarshal_acpi_object_undersized_test),
{}
};
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 4cb7d97a9fcc..2ffa4ecf65b0 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -113,6 +113,24 @@ config GIGABYTE_WMI
To compile this driver as a module, choose M here: the module will
be called gigabyte-wmi.
+config BITLAND_MIFS_WMI
+ tristate "Bitland MIFS (MiInterface) WMI driver"
+ depends on ACPI_WMI
+ depends on HWMON
+ depends on INPUT
+ depends on POWER_SUPPLY
+ select ACPI_PLATFORM_PROFILE
+ select INPUT_SPARSEKMAP
+ help
+ This is a driver for Bitland MiInterface based laptops.
+
+ It provides the access to the temperature, fan speed, gpu
+ control, keyboard backlight brightness and platform profile
+ via hwmon and sysfs.
+
+ To compile this driver as a module, choose M here: the module will
+ be called bitland-mifs-wmi.
+
config ACERHDF
tristate "Acer Aspire One temperature and fan driver"
depends on ACPI_EC && THERMAL
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index d25762f7114f..872ac3842391 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
+obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
# Acer
obj-$(CONFIG_ACERHDF) += acerhdf.o
diff --git a/drivers/platform/x86/acer-wireless.c b/drivers/platform/x86/acer-wireless.c
index 1b5d935d085a..f464b13a58af 100644
--- a/drivers/platform/x86/acer-wireless.c
+++ b/drivers/platform/x86/acer-wireless.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
#include <linux/types.h>
static const struct acpi_device_id acer_wireless_acpi_ids[] = {
@@ -18,13 +19,14 @@ static const struct acpi_device_id acer_wireless_acpi_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, acer_wireless_acpi_ids);
-static void acer_wireless_notify(struct acpi_device *adev, u32 event)
+static void acer_wireless_notify(acpi_handle handle, u32 event, void *data)
{
- struct input_dev *idev = acpi_driver_data(adev);
+ struct device *dev = data;
+ struct input_dev *idev = dev_get_drvdata(dev);
- dev_dbg(&adev->dev, "event=%#x\n", event);
+ dev_dbg(dev, "event=%#x\n", event);
if (event != 0x80) {
- dev_notice(&adev->dev, "Unknown SMKB event: %#x\n", event);
+ dev_notice(dev, "Unknown SMKB event: %#x\n", event);
return;
}
input_report_key(idev, KEY_RFKILL, 1);
@@ -33,15 +35,16 @@ static void acer_wireless_notify(struct acpi_device *adev, u32 event)
input_sync(idev);
}
-static int acer_wireless_add(struct acpi_device *adev)
+static int acer_wireless_probe(struct platform_device *pdev)
{
struct input_dev *idev;
+ int ret;
- idev = devm_input_allocate_device(&adev->dev);
+ idev = devm_input_allocate_device(&pdev->dev);
if (!idev)
return -ENOMEM;
- adev->driver_data = idev;
+ platform_set_drvdata(pdev, idev);
idev->name = "Acer Wireless Radio Control";
idev->phys = "acer-wireless/input0";
idev->id.bustype = BUS_HOST;
@@ -50,19 +53,32 @@ static int acer_wireless_add(struct acpi_device *adev)
set_bit(EV_KEY, idev->evbit);
set_bit(KEY_RFKILL, idev->keybit);
- return input_register_device(idev);
+ ret = input_register_device(idev);
+ if (ret)
+ return ret;
+
+ return acpi_dev_install_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY,
+ acer_wireless_notify,
+ &pdev->dev);
+}
+
+static void acer_wireless_remove(struct platform_device *pdev)
+{
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY,
+ acer_wireless_notify);
}
-static struct acpi_driver acer_wireless_driver = {
- .name = "Acer Wireless Radio Control Driver",
- .class = "hotkey",
- .ids = acer_wireless_acpi_ids,
- .ops = {
- .add = acer_wireless_add,
- .notify = acer_wireless_notify,
+static struct platform_driver acer_wireless_driver = {
+ .probe = acer_wireless_probe,
+ .remove = acer_wireless_remove,
+ .driver = {
+ .name = "Acer Wireless Radio Control Driver",
+ .acpi_match_table = acer_wireless_acpi_ids,
},
};
-module_acpi_driver(acer_wireless_driver);
+module_platform_driver(acer_wireless_driver);
MODULE_DESCRIPTION("Acer Wireless Radio Control Driver");
MODULE_AUTHOR("Chris Chiu <chiu@gmail.com>");
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index d96f6af26ff7..dbbb6292cd11 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1517,9 +1517,9 @@ static void asus_input_exit(struct asus_laptop *asus)
/*
* ACPI driver
*/
-static void asus_acpi_notify(struct acpi_device *device, u32 event)
+static void asus_acpi_notify(acpi_handle handle, u32 event, void *data)
{
- struct asus_laptop *asus = acpi_driver_data(device);
+ struct asus_laptop *asus = data;
u16 count;
/* TODO Find a better way to handle events count. */
@@ -1824,8 +1824,9 @@ static void asus_dmi_check(void)
static bool asus_device_present;
-static int asus_acpi_add(struct acpi_device *device)
+static int asus_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct asus_laptop *asus;
int result;
@@ -1837,7 +1838,6 @@ static int asus_acpi_add(struct acpi_device *device)
asus->handle = device->handle;
strscpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME);
strscpy(acpi_device_class(device), ASUS_LAPTOP_CLASS);
- device->driver_data = asus;
asus->device = device;
asus_dmi_check();
@@ -1846,6 +1846,8 @@ static int asus_acpi_add(struct acpi_device *device)
if (result)
goto fail_platform;
+ platform_set_drvdata(pdev, asus);
+
/*
* Need platform type detection first, then the platform
* device. It is used as a parent for the sub-devices below.
@@ -1881,6 +1883,11 @@ static int asus_acpi_add(struct acpi_device *device)
if (result && result != -ENODEV)
goto fail_pega_rfkill;
+ result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ asus_acpi_notify, asus);
+ if (result)
+ goto fail_pega_rfkill;
+
asus_device_present = true;
return 0;
@@ -1902,10 +1909,12 @@ fail_platform:
return result;
}
-static void asus_acpi_remove(struct acpi_device *device)
+static void asus_acpi_remove(struct platform_device *pdev)
{
- struct asus_laptop *asus = acpi_driver_data(device);
+ struct asus_laptop *asus = platform_get_drvdata(pdev);
+ acpi_dev_remove_notify_handler(asus->device, ACPI_DEVICE_NOTIFY,
+ asus_acpi_notify);
asus_backlight_exit(asus);
asus_rfkill_exit(asus);
asus_led_exit(asus);
@@ -1924,16 +1933,13 @@ static const struct acpi_device_id asus_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-static struct acpi_driver asus_acpi_driver = {
- .name = ASUS_LAPTOP_NAME,
- .class = ASUS_LAPTOP_CLASS,
- .ids = asus_device_ids,
- .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
- .ops = {
- .add = asus_acpi_add,
- .remove = asus_acpi_remove,
- .notify = asus_acpi_notify,
- },
+static struct platform_driver asus_acpi_driver = {
+ .probe = asus_acpi_probe,
+ .remove = asus_acpi_remove,
+ .driver = {
+ .name = ASUS_LAPTOP_NAME,
+ .acpi_match_table = asus_device_ids,
+ },
};
static int __init asus_laptop_init(void)
@@ -1944,7 +1950,7 @@ static int __init asus_laptop_init(void)
if (result < 0)
return result;
- result = acpi_bus_register_driver(&asus_acpi_driver);
+ result = platform_driver_register(&asus_acpi_driver);
if (result < 0)
goto fail_acpi_driver;
if (!asus_device_present) {
@@ -1954,7 +1960,7 @@ static int __init asus_laptop_init(void)
return 0;
fail_no_device:
- acpi_bus_unregister_driver(&asus_acpi_driver);
+ platform_driver_unregister(&asus_acpi_driver);
fail_acpi_driver:
platform_driver_unregister(&platform_driver);
return result;
@@ -1962,7 +1968,7 @@ fail_acpi_driver:
static void __exit asus_laptop_exit(void)
{
- acpi_bus_unregister_driver(&asus_acpi_driver);
+ platform_driver_unregister(&asus_acpi_driver);
platform_driver_unregister(&platform_driver);
}
diff --git a/drivers/platform/x86/asus-wireless.c b/drivers/platform/x86/asus-wireless.c
index 41227bf95878..2b494bf3cba8 100644
--- a/drivers/platform/x86/asus-wireless.c
+++ b/drivers/platform/x86/asus-wireless.c
@@ -12,6 +12,7 @@
#include <linux/acpi.h>
#include <linux/input.h>
#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
#include <linux/leds.h>
struct hswc_params {
@@ -108,9 +109,10 @@ static void led_state_set(struct led_classdev *led, enum led_brightness value)
queue_work(data->wq, &data->led_work);
}
-static void asus_wireless_notify(struct acpi_device *adev, u32 event)
+static void asus_wireless_notify(acpi_handle handle, u32 event, void *context)
{
- struct asus_wireless_data *data = acpi_driver_data(adev);
+ struct asus_wireless_data *data = context;
+ struct acpi_device *adev = data->adev;
dev_dbg(&adev->dev, "event=%#x\n", event);
if (event != 0x88) {
@@ -123,19 +125,22 @@ static void asus_wireless_notify(struct acpi_device *adev, u32 event)
input_sync(data->idev);
}
-static int asus_wireless_add(struct acpi_device *adev)
+static int asus_wireless_probe(struct platform_device *pdev)
{
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct asus_wireless_data *data;
const struct acpi_device_id *id;
int err;
- data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- adev->driver_data = data;
+
+ platform_set_drvdata(pdev, data);
+
data->adev = adev;
- data->idev = devm_input_allocate_device(&adev->dev);
+ data->idev = devm_input_allocate_device(&pdev->dev);
if (!data->idev)
return -ENOMEM;
data->idev->name = "Asus Wireless Radio Control";
@@ -164,34 +169,44 @@ static int asus_wireless_add(struct acpi_device *adev)
data->led.flags = LED_CORE_SUSPENDRESUME;
data->led.max_brightness = 1;
data->led.default_trigger = "rfkill-none";
- err = devm_led_classdev_register(&adev->dev, &data->led);
+ err = devm_led_classdev_register(&pdev->dev, &data->led);
if (err)
- destroy_workqueue(data->wq);
+ goto err;
+
+ err = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
+ asus_wireless_notify, data);
+ if (err) {
+ devm_led_classdev_unregister(&pdev->dev, &data->led);
+ goto err;
+ }
+ return 0;
+err:
+ destroy_workqueue(data->wq);
return err;
}
-static void asus_wireless_remove(struct acpi_device *adev)
+static void asus_wireless_remove(struct platform_device *pdev)
{
- struct asus_wireless_data *data = acpi_driver_data(adev);
+ struct asus_wireless_data *data = platform_get_drvdata(pdev);
+ acpi_dev_remove_notify_handler(data->adev, ACPI_DEVICE_NOTIFY,
+ asus_wireless_notify);
if (data->wq) {
- devm_led_classdev_unregister(&adev->dev, &data->led);
+ devm_led_classdev_unregister(&pdev->dev, &data->led);
destroy_workqueue(data->wq);
}
}
-static struct acpi_driver asus_wireless_driver = {
- .name = "Asus Wireless Radio Control Driver",
- .class = "hotkey",
- .ids = device_ids,
- .ops = {
- .add = asus_wireless_add,
- .remove = asus_wireless_remove,
- .notify = asus_wireless_notify,
+static struct platform_driver asus_wireless_driver = {
+ .probe = asus_wireless_probe,
+ .remove = asus_wireless_remove,
+ .driver = {
+ .name = "Asus Wireless Radio Control Driver",
+ .acpi_match_table = device_ids,
},
};
-module_acpi_driver(asus_wireless_driver);
+module_platform_driver(asus_wireless_driver);
MODULE_DESCRIPTION("Asus Wireless Radio Control Driver");
MODULE_AUTHOR("João Paulo Rechi Vita <jprvita@gmail.com>");
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 7c0915e097ba..80144c412b90 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -125,7 +125,6 @@ module_param(fnlock_default, bool, 0444);
#define NVIDIA_TEMP_MIN 75
#define NVIDIA_TEMP_MAX 87
-#define ASUS_SCREENPAD_BRIGHT_MIN 20
#define ASUS_SCREENPAD_BRIGHT_MAX 255
#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
@@ -1557,7 +1556,10 @@ static ssize_t charge_control_end_threshold_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
- return sysfs_emit(buf, "%d\n", charge_end_threshold);
+ if ((charge_end_threshold >= 0) && (charge_end_threshold <= 100))
+ return sysfs_emit(buf, "%d\n", charge_end_threshold);
+
+ return -ENODATA;
}
static DEVICE_ATTR_RW(charge_control_end_threshold);
@@ -1580,11 +1582,11 @@ static int asus_wmi_battery_add(struct power_supply *battery, struct acpi_batter
return -ENODEV;
/* The charge threshold is only reset when the system is power cycled,
- * and we can't get the current threshold so let set it to 100% when
- * a battery is added.
+ * and we can't read the current threshold, however the majority of
+ * platforms retains it, therefore signal the threshold as unknown
+ * until user explicitly sets it to a new value.
*/
- asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, 100, NULL);
- charge_end_threshold = 100;
+ charge_end_threshold = -1;
return 0;
}
@@ -4408,43 +4410,35 @@ static int read_screenpad_brightness(struct backlight_device *bd)
return err;
/* The device brightness can only be read if powered, so return stored */
if (err == BACKLIGHT_POWER_OFF)
- return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
+ return bd->props.brightness;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval);
if (err < 0)
return err;
- return (retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK) - ASUS_SCREENPAD_BRIGHT_MIN;
+ return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
}
static int update_screenpad_bl_status(struct backlight_device *bd)
{
- struct asus_wmi *asus = bl_get_data(bd);
- int power, err = 0;
- u32 ctrl_param;
+ u32 ctrl_param = bd->props.brightness;
+ int err = 0;
- power = read_screenpad_backlight_power(asus);
- if (power < 0)
- return power;
+ if (bd->props.power) {
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 1, NULL);
+ if (err < 0)
+ return err;
- if (bd->props.power != power) {
- if (power != BACKLIGHT_POWER_ON) {
- /* Only brightness > 0 can power it back on */
- ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT,
- ctrl_param, NULL);
- } else {
- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL);
- }
- } else if (power == BACKLIGHT_POWER_ON) {
- /* Only set brightness if powered on or we get invalid/unsync state */
- ctrl_param = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL);
+ if (err < 0)
+ return err;
}
- /* Ensure brightness is stored to turn back on with */
- if (err == 0)
- asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
+ if (!bd->props.power) {
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL);
+ if (err < 0)
+ return err;
+ }
return err;
}
@@ -4462,22 +4456,19 @@ static int asus_screenpad_init(struct asus_wmi *asus)
int err, power;
int brightness = 0;
- power = read_screenpad_backlight_power(asus);
+ power = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER);
if (power < 0)
return power;
- if (power != BACKLIGHT_POWER_OFF) {
+ if (power) {
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness);
if (err < 0)
return err;
}
- /* default to an acceptable min brightness on boot if too low */
- if (brightness < ASUS_SCREENPAD_BRIGHT_MIN)
- brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT;
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */
- props.max_brightness = ASUS_SCREENPAD_BRIGHT_MAX - ASUS_SCREENPAD_BRIGHT_MIN;
+ props.max_brightness = ASUS_SCREENPAD_BRIGHT_MAX;
bd = backlight_device_register("asus_screenpad",
&asus->platform_device->dev, asus,
&asus_screenpad_bl_ops, &props);
@@ -4488,7 +4479,7 @@ static int asus_screenpad_init(struct asus_wmi *asus)
asus->screenpad_backlight_device = bd;
asus->driver->screenpad_brightness = brightness;
- bd->props.brightness = brightness - ASUS_SCREENPAD_BRIGHT_MIN;
+ bd->props.brightness = brightness;
bd->props.power = power;
backlight_update_status(bd);
@@ -5413,17 +5404,3 @@ void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
used = false;
}
EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
-
-static int __init asus_wmi_init(void)
-{
- pr_info("ASUS WMI generic driver loaded\n");
- return 0;
-}
-
-static void __exit asus_wmi_exit(void)
-{
- pr_info("ASUS WMI generic driver unloaded\n");
-}
-
-module_init(asus_wmi_init);
-module_exit(asus_wmi_exit);
diff --git a/drivers/platform/x86/barco-p50-gpio.c b/drivers/platform/x86/barco-p50-gpio.c
index 6f13e81f98fb..2a6d8607c402 100644
--- a/drivers/platform/x86/barco-p50-gpio.c
+++ b/drivers/platform/x86/barco-p50-gpio.c
@@ -272,30 +272,27 @@ static int p50_gpio_get(struct gpio_chip *gc, unsigned int offset)
struct p50_gpio *p50 = gpiochip_get_data(gc);
int ret;
- mutex_lock(&p50->lock);
+ guard(mutex)(&p50->lock);
ret = p50_send_mbox_cmd(p50, P50_MBOX_CMD_READ_GPIO, gpio_params[offset], 0);
- if (ret == 0)
- ret = p50_read_mbox_reg(p50, P50_MBOX_REG_DATA);
+ if (ret < 0)
+ return ret;
- mutex_unlock(&p50->lock);
+ ret = p50_read_mbox_reg(p50, P50_MBOX_REG_DATA);
+ if (ret < 0)
+ return ret;
- return ret;
+ return !!ret;
}
static int p50_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
struct p50_gpio *p50 = gpiochip_get_data(gc);
- int ret;
-
- mutex_lock(&p50->lock);
- ret = p50_send_mbox_cmd(p50, P50_MBOX_CMD_WRITE_GPIO,
- gpio_params[offset], value);
+ guard(mutex)(&p50->lock);
- mutex_unlock(&p50->lock);
-
- return ret;
+ return p50_send_mbox_cmd(p50, P50_MBOX_CMD_WRITE_GPIO,
+ gpio_params[offset], value);
}
static int p50_gpio_probe(struct platform_device *pdev)
diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
new file mode 100644
index 000000000000..b0d06a80e89e
--- /dev/null
+++ b/drivers/platform/x86/bitland-mifs-wmi.c
@@ -0,0 +1,837 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Linux driver for Bitland notebooks.
+ *
+ * Copyright (C) 2026 2 Mingyou Chen <qby140326@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/container_of.h>
+#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/device/devres.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/init.h>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/platform_profile.h>
+#include <linux/pm.h>
+#include <linux/power_supply.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+#include <linux/wmi.h>
+
+#define DRV_NAME "bitland-mifs-wmi"
+#define BITLAND_MIFS_GUID "B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B"
+#define BITLAND_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF"
+
+enum bitland_mifs_operation {
+ WMI_METHOD_GET = 250,
+ WMI_METHOD_SET = 251,
+};
+
+enum bitland_mifs_function {
+ WMI_FN_SYSTEM_PER_MODE = 8,
+ WMI_FN_GPU_MODE = 9,
+ WMI_FN_KBD_TYPE = 10,
+ WMI_FN_FN_LOCK = 11,
+ WMI_FN_TP_LOCK = 12,
+ WMI_FN_FAN_SPEEDS = 13,
+ WMI_FN_RGB_KB_MODE = 16,
+ WMI_FN_RGB_KB_COLOR = 17,
+ WMI_FN_RGB_KB_BRIGHTNESS = 18,
+ WMI_FN_SYSTEM_AC_TYPE = 19,
+ WMI_FN_MAX_FAN_SWITCH = 20,
+ WMI_FN_MAX_FAN_SPEED = 21,
+ WMI_FN_CPU_THERMOMETER = 22,
+ WMI_FN_CPU_POWER = 23,
+};
+
+enum bitland_system_ac_mode {
+ WMI_SYSTEM_AC_TYPEC = 1,
+ /* Unknown type, this is unused in the original driver */
+ WMI_SYSTEM_AC_CIRCULARHOLE = 2,
+};
+
+enum bitland_mifs_power_profile {
+ WMI_PP_BALANCED = 0,
+ WMI_PP_PERFORMANCE = 1,
+ WMI_PP_QUIET = 2,
+ WMI_PP_FULL_SPEED = 3,
+};
+
+enum bitland_mifs_event_id {
+ WMI_EVENT_RESERVED_1 = 1,
+ WMI_EVENT_RESERVED_2 = 2,
+ WMI_EVENT_RESERVED_3 = 3,
+ WMI_EVENT_AIRPLANE_MODE = 4,
+ WMI_EVENT_KBD_BRIGHTNESS = 5,
+ WMI_EVENT_TOUCHPAD_STATE = 6,
+ WMI_EVENT_FNLOCK_STATE = 7,
+ WMI_EVENT_KBD_MODE = 8,
+ WMI_EVENT_CAPSLOCK_STATE = 9,
+ WMI_EVENT_CALCULATOR_START = 11,
+ WMI_EVENT_BROWSER_START = 12,
+ WMI_EVENT_NUMLOCK_STATE = 13,
+ WMI_EVENT_SCROLLLOCK_STATE = 14,
+ WMI_EVENT_PERFORMANCE_PLAN = 15,
+ WMI_EVENT_FN_J = 16,
+ WMI_EVENT_FN_F = 17,
+ WMI_EVENT_FN_0 = 18,
+ WMI_EVENT_FN_1 = 19,
+ WMI_EVENT_FN_2 = 20,
+ WMI_EVENT_FN_3 = 21,
+ WMI_EVENT_FN_4 = 22,
+ WMI_EVENT_FN_5 = 24,
+ WMI_EVENT_REFRESH_RATE = 25,
+ WMI_EVENT_CPU_FAN_SPEED = 26,
+ WMI_EVENT_GPU_FAN_SPEED = 32,
+ WMI_EVENT_WIN_KEY_LOCK = 33,
+ WMI_EVENT_RESERVED_23 = 34,
+ WMI_EVENT_OPEN_APP = 35,
+};
+
+enum bitland_mifs_event_type {
+ WMI_EVENT_TYPE_HOTKEY = 1,
+};
+
+enum bitland_wmi_device_type {
+ BITLAND_WMI_CONTROL = 0,
+ BITLAND_WMI_EVENT = 1,
+};
+
+struct bitland_mifs_input {
+ u8 reserved1;
+ u8 operation;
+ u8 reserved2;
+ u8 function;
+ u8 payload[28];
+} __packed;
+
+struct bitland_mifs_output {
+ u8 reserved1;
+ u8 operation;
+ u8 reserved2;
+ u8 function;
+ u8 data[28];
+} __packed;
+
+struct bitland_mifs_event {
+ u8 event_type;
+ u8 event_id;
+ u8 value_low; /* For most events, this is the value */
+ u8 value_high; /* For fan speed events, combined with value_low */
+ u8 reserved[4];
+} __packed;
+
+static BLOCKING_NOTIFIER_HEAD(bitland_notifier_list);
+
+enum bitland_notifier_actions {
+ BITLAND_NOTIFY_KBD_BRIGHTNESS,
+ BITLAND_NOTIFY_PLATFORM_PROFILE,
+ BITLAND_NOTIFY_HWMON,
+};
+
+struct bitland_fan_notify_data {
+ int channel; /* 0 = CPU, 1 = GPU */
+ u16 speed;
+};
+
+struct bitland_mifs_wmi_data {
+ struct wmi_device *wdev;
+ struct mutex lock; /* Protects WMI calls */
+ struct led_classdev kbd_led;
+ struct notifier_block notifier;
+ struct input_dev *input_dev;
+ struct device *hwmon_dev;
+ struct device *pp_dev;
+ enum platform_profile_option saved_profile;
+};
+
+static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
+ const struct bitland_mifs_input *input,
+ struct bitland_mifs_output *output)
+{
+ struct wmi_buffer in_buf = { .length = sizeof(*input), .data = (void *)input };
+ struct wmi_buffer out_buf = { 0 };
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ if (!output)
+ return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf);
+
+ ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output));
+ if (ret)
+ return ret;
+
+ memcpy(output, out_buf.data, sizeof(*output));
+ kfree(out_buf.data);
+
+ return 0;
+}
+
+static int laptop_profile_get(struct device *dev,
+ enum platform_profile_option *profile)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_GET,
+ .reserved2 = 0,
+ .function = WMI_FN_SYSTEM_PER_MODE,
+ };
+ struct bitland_mifs_output result;
+ int ret;
+
+ ret = bitland_mifs_wmi_call(data, &input, &result);
+ if (ret)
+ return ret;
+
+ switch (result.data[0]) {
+ case WMI_PP_BALANCED:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case WMI_PP_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
+ break;
+ case WMI_PP_QUIET:
+ *profile = PLATFORM_PROFILE_LOW_POWER;
+ break;
+ case WMI_PP_FULL_SPEED:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *data)
+{
+ struct bitland_mifs_input input = {
+ .operation = WMI_METHOD_GET,
+ .function = WMI_FN_SYSTEM_AC_TYPE,
+ };
+ struct bitland_mifs_output output;
+ int ret;
+
+ /* Full-speed/performance mode requires DC power (not USB-C) */
+ if (!power_supply_is_system_supplied())
+ return -EOPNOTSUPP;
+
+ ret = bitland_mifs_wmi_call(data, &input, &output);
+ if (ret)
+ return ret;
+
+ if (output.data[0] != WMI_SYSTEM_AC_CIRCULARHOLE)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int laptop_profile_set(struct device *dev,
+ enum platform_profile_option profile)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_SET,
+ .reserved2 = 0,
+ .function = WMI_FN_SYSTEM_PER_MODE,
+ };
+ int ret;
+ u8 val;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_LOW_POWER:
+ val = WMI_PP_QUIET;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ val = WMI_PP_BALANCED;
+ break;
+ case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
+ ret = bitland_check_performance_capability(data);
+ if (ret)
+ return ret;
+ val = WMI_PP_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_PERFORMANCE:
+ ret = bitland_check_performance_capability(data);
+ if (ret)
+ return ret;
+ val = WMI_PP_FULL_SPEED;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ input.payload[0] = val;
+
+ return bitland_mifs_wmi_call(data, &input, NULL);
+}
+
+static int platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
+static int bitland_mifs_wmi_suspend(struct device *dev)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ enum platform_profile_option profile;
+ int ret;
+
+ ret = laptop_profile_get(data->pp_dev, &profile);
+ if (ret == 0)
+ data->saved_profile = profile;
+
+ return ret;
+}
+
+static int bitland_mifs_wmi_resume(struct device *dev)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "Resuming, restoring profile %d\n", data->saved_profile);
+ return laptop_profile_set(dev, data->saved_profile);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(bitland_mifs_wmi_pm_ops,
+ bitland_mifs_wmi_suspend,
+ bitland_mifs_wmi_resume);
+
+static const struct platform_profile_ops laptop_profile_ops = {
+ .probe = platform_profile_probe,
+ .profile_get = laptop_profile_get,
+ .profile_set = laptop_profile_set,
+};
+
+static const char *const fan_labels[] = {
+ "CPU", /* 0 */
+ "GPU", /* 1 */
+ "SYS", /* 2 */
+};
+
+static int laptop_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_GET,
+ .reserved2 = 0,
+ };
+ struct bitland_mifs_output res;
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ input.function = WMI_FN_CPU_THERMOMETER;
+ ret = bitland_mifs_wmi_call(data, &input, &res);
+ if (!ret)
+ *val = res.data[0] * MILLIDEGREE_PER_DEGREE;
+ return ret;
+ case hwmon_fan:
+ input.function = WMI_FN_FAN_SPEEDS;
+ ret = bitland_mifs_wmi_call(data, &input, &res);
+ if (ret)
+ return ret;
+
+ switch (channel) {
+ case 0: /* CPU */
+ *val = get_unaligned_le16(&res.data[0]);
+ return 0;
+ case 1: /* GPU */
+ *val = get_unaligned_le16(&res.data[2]);
+ return 0;
+ case 2: /* SYS */
+ *val = get_unaligned_le16(&res.data[6]);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int laptop_hwmon_read_string(struct device *dev,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **str)
+{
+ if (type == hwmon_fan && attr == hwmon_fan_label) {
+ if (channel >= 0 && channel < ARRAY_SIZE(fan_labels)) {
+ *str = fan_labels[channel];
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static const struct hwmon_channel_info *laptop_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL,
+ HWMON_F_INPUT | HWMON_F_LABEL,
+ HWMON_F_INPUT | HWMON_F_LABEL),
+ NULL
+};
+
+static const struct hwmon_ops laptop_hwmon_ops = {
+ .visible = 0444,
+ .read = laptop_hwmon_read,
+ .read_string = laptop_hwmon_read_string,
+};
+
+static const struct hwmon_chip_info laptop_chip_info = {
+ .ops = &laptop_hwmon_ops,
+ .info = laptop_hwmon_info,
+};
+
+static int laptop_kbd_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct bitland_mifs_wmi_data *data =
+ container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_SET,
+ .reserved2 = 0,
+ .function = WMI_FN_RGB_KB_BRIGHTNESS,
+ };
+
+ input.payload[0] = (u8)value;
+
+ return bitland_mifs_wmi_call(data, &input, NULL);
+}
+
+static enum led_brightness laptop_kbd_led_get(struct led_classdev *led_cdev)
+{
+ struct bitland_mifs_wmi_data *data =
+ container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_GET,
+ .reserved2 = 0,
+ .function = WMI_FN_RGB_KB_BRIGHTNESS,
+ };
+ struct bitland_mifs_output res;
+ int ret;
+
+ ret = bitland_mifs_wmi_call(data, &input, &res);
+ if (ret)
+ return ret;
+
+ return res.data[0];
+}
+
+static const char *const gpu_mode_strings[] = {
+ "hybrid",
+ "discrete",
+ "uma",
+};
+
+/* GPU Mode: 0:Hybrid, 1:Discrete, 2:UMA */
+static ssize_t gpu_mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_GET,
+ .reserved2 = 0,
+ .function = WMI_FN_GPU_MODE,
+ };
+ struct bitland_mifs_output res;
+ u8 mode_val;
+ int ret;
+
+ ret = bitland_mifs_wmi_call(data, &input, &res);
+ if (ret)
+ return ret;
+
+ mode_val = res.data[0];
+ if (mode_val >= ARRAY_SIZE(gpu_mode_strings))
+ return -EPROTO;
+
+ return sysfs_emit(buf, "%s\n", gpu_mode_strings[mode_val]);
+}
+
+static ssize_t gpu_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_SET,
+ .reserved2 = 0,
+ .function = WMI_FN_GPU_MODE,
+ };
+ int val;
+ int ret;
+
+ val = sysfs_match_string(gpu_mode_strings, buf);
+ if (val < 0)
+ return -EINVAL;
+
+ input.payload[0] = (u8)val;
+
+ ret = bitland_mifs_wmi_call(data, &input, NULL);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const char *const kb_mode_strings[] = {
+ "off", /* 0 */
+ "cyclic", /* 1 */
+ "fixed", /* 2 */
+ "custom", /* 3 */
+};
+
+static ssize_t kb_mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_GET,
+ .reserved2 = 0,
+ .function = WMI_FN_RGB_KB_MODE,
+ };
+ struct bitland_mifs_output res;
+ u8 mode_val;
+ int ret;
+
+ ret = bitland_mifs_wmi_call(data, &input, &res);
+ if (ret)
+ return ret;
+
+ mode_val = res.data[0];
+ if (mode_val >= ARRAY_SIZE(kb_mode_strings))
+ return -EPROTO;
+
+ return sysfs_emit(buf, "%s\n", kb_mode_strings[mode_val]);
+}
+
+static ssize_t kb_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_SET,
+ .reserved2 = 0,
+ .function = WMI_FN_RGB_KB_MODE,
+ };
+ // the wmi value (0, 1, 2 or 3)
+ int val;
+ int ret;
+
+ val = sysfs_match_string(kb_mode_strings, buf);
+ if (val < 0)
+ return -EINVAL;
+
+ input.payload[0] = (u8)val;
+
+ ret = bitland_mifs_wmi_call(data, &input, NULL);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+/* Fan Boost: 0:Normal, 1:Max Speed */
+static ssize_t fan_boost_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ struct bitland_mifs_input input = {
+ .reserved1 = 0,
+ .operation = WMI_METHOD_SET,
+ .reserved2 = 0,
+ .function = WMI_FN_MAX_FAN_SWITCH,
+ };
+ bool val;
+ int ret;
+
+ if (kstrtobool(buf, &val))
+ return -EINVAL;
+
+ input.payload[0] = 0; /* CPU/GPU Fan */
+ input.payload[1] = val;
+
+ ret = bitland_mifs_wmi_call(data, &input, NULL);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const DEVICE_ATTR_RW(gpu_mode);
+static const DEVICE_ATTR_RW(kb_mode);
+static const DEVICE_ATTR_WO(fan_boost);
+
+static const struct attribute *const laptop_attrs[] = {
+ &dev_attr_gpu_mode.attr,
+ &dev_attr_kb_mode.attr,
+ &dev_attr_fan_boost.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(laptop);
+
+static const struct key_entry bitland_mifs_wmi_keymap[] = {
+ { KE_KEY, WMI_EVENT_OPEN_APP, { KEY_PROG1 } },
+ { KE_KEY, WMI_EVENT_CALCULATOR_START, { KEY_CALC } },
+ { KE_KEY, WMI_EVENT_BROWSER_START, { KEY_WWW } },
+ { KE_IGNORE, WMI_EVENT_FN_J, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_F, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_0, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_1, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_2, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_3, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_4, { KEY_RESERVED } },
+ { KE_IGNORE, WMI_EVENT_FN_5, { KEY_RESERVED } },
+ { KE_END, 0 }
+};
+
+static void bitland_notifier_unregister(void *data)
+{
+ struct notifier_block *nb = data;
+
+ blocking_notifier_chain_unregister(&bitland_notifier_list, nb);
+}
+
+static int bitland_notifier_callback(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct bitland_mifs_wmi_data *data_ctx =
+ container_of(nb, struct bitland_mifs_wmi_data, notifier);
+ struct bitland_fan_notify_data *fan_info;
+ u8 *brightness;
+
+ switch (action) {
+ case BITLAND_NOTIFY_KBD_BRIGHTNESS:
+ brightness = data;
+ led_classdev_notify_brightness_hw_changed(&data_ctx->kbd_led,
+ *brightness);
+ break;
+ case BITLAND_NOTIFY_PLATFORM_PROFILE:
+ platform_profile_notify(data_ctx->pp_dev);
+ break;
+ case BITLAND_NOTIFY_HWMON:
+ fan_info = data;
+
+ hwmon_notify_event(data_ctx->hwmon_dev, hwmon_fan,
+ hwmon_fan_input, fan_info->channel);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct bitland_mifs_wmi_data *drv_data;
+ enum bitland_wmi_device_type dev_type =
+ (enum bitland_wmi_device_type)(unsigned long)context;
+ struct led_init_data init_data = {
+ .devicename = DRV_NAME,
+ .default_label = ":" LED_FUNCTION_KBD_BACKLIGHT,
+ .devname_mandatory = true,
+ };
+ int ret;
+
+ drv_data = devm_kzalloc(&wdev->dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data)
+ return -ENOMEM;
+
+ drv_data->wdev = wdev;
+
+ ret = devm_mutex_init(&wdev->dev, &drv_data->lock);
+ if (ret)
+ return ret;
+
+ dev_set_drvdata(&wdev->dev, drv_data);
+
+ if (dev_type == BITLAND_WMI_EVENT) {
+ /* Register input device for hotkeys */
+ drv_data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (!drv_data->input_dev)
+ return -ENOMEM;
+
+ drv_data->input_dev->name = "Bitland MIFS WMI hotkeys";
+ drv_data->input_dev->phys = "wmi/input0";
+ drv_data->input_dev->id.bustype = BUS_HOST;
+ drv_data->input_dev->dev.parent = &wdev->dev;
+
+ ret = sparse_keymap_setup(drv_data->input_dev,
+ bitland_mifs_wmi_keymap, NULL);
+ if (ret)
+ return ret;
+
+ return input_register_device(drv_data->input_dev);
+ }
+
+ /* Register platform profile */
+ drv_data->pp_dev = devm_platform_profile_register(&wdev->dev, DRV_NAME, drv_data,
+ &laptop_profile_ops);
+ if (IS_ERR(drv_data->pp_dev))
+ return PTR_ERR(drv_data->pp_dev);
+
+ /* Register hwmon */
+ drv_data->hwmon_dev = devm_hwmon_device_register_with_info(&wdev->dev,
+ "bitland_mifs",
+ drv_data,
+ &laptop_chip_info,
+ NULL);
+ if (IS_ERR(drv_data->hwmon_dev))
+ return PTR_ERR(drv_data->hwmon_dev);
+
+ /* Register keyboard LED */
+ drv_data->kbd_led.max_brightness = 3;
+ drv_data->kbd_led.brightness_set_blocking = laptop_kbd_led_set;
+ drv_data->kbd_led.brightness_get = laptop_kbd_led_get;
+ drv_data->kbd_led.brightness = laptop_kbd_led_get(&drv_data->kbd_led);
+ drv_data->kbd_led.flags = LED_CORE_SUSPENDRESUME |
+ LED_BRIGHT_HW_CHANGED |
+ LED_REJECT_NAME_CONFLICT;
+ ret = devm_led_classdev_register_ext(&wdev->dev, &drv_data->kbd_led, &init_data);
+ if (ret)
+ return ret;
+
+ drv_data->notifier.notifier_call = bitland_notifier_callback;
+ ret = blocking_notifier_chain_register(&bitland_notifier_list, &drv_data->notifier);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&wdev->dev,
+ bitland_notifier_unregister,
+ &drv_data->notifier);
+}
+
+static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
+ const struct wmi_buffer *buffer)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev);
+ const struct bitland_mifs_event *event = buffer->data;
+ struct bitland_fan_notify_data fan_data;
+ u8 brightness;
+
+ /* Validate event type */
+ if (event->event_type != WMI_EVENT_TYPE_HOTKEY)
+ return;
+
+ dev_dbg(&wdev->dev,
+ "WMI event: id=0x%02x value_low=0x%02x value_high=0x%02x\n",
+ event->event_id, event->value_low, event->value_high);
+
+ switch (event->event_id) {
+ case WMI_EVENT_KBD_BRIGHTNESS:
+ brightness = event->value_low;
+ blocking_notifier_call_chain(&bitland_notifier_list,
+ BITLAND_NOTIFY_KBD_BRIGHTNESS,
+ &brightness);
+ break;
+
+ case WMI_EVENT_PERFORMANCE_PLAN:
+ blocking_notifier_call_chain(&bitland_notifier_list,
+ BITLAND_NOTIFY_PLATFORM_PROFILE,
+ NULL);
+ break;
+
+ case WMI_EVENT_OPEN_APP:
+ case WMI_EVENT_CALCULATOR_START:
+ case WMI_EVENT_BROWSER_START: {
+ guard(mutex)(&data->lock);
+ if (!sparse_keymap_report_event(data->input_dev,
+ event->event_id, 1, true))
+ dev_warn(&wdev->dev, "Unknown key pressed: 0x%02x\n",
+ event->event_id);
+ break;
+ }
+
+ /*
+ * The device has 3 fans (CPU, GPU, SYS),
+ * but there are only the CPU and GPU fan has events
+ */
+ case WMI_EVENT_CPU_FAN_SPEED:
+ case WMI_EVENT_GPU_FAN_SPEED:
+ if (event->event_id == WMI_EVENT_CPU_FAN_SPEED)
+ fan_data.channel = 0;
+ else
+ fan_data.channel = 1;
+
+ /* Fan speed is 16-bit value (value_low is LSB, value_high is MSB) */
+ fan_data.speed = (event->value_high << 8) | event->value_low;
+ blocking_notifier_call_chain(&bitland_notifier_list,
+ BITLAND_NOTIFY_HWMON,
+ &fan_data);
+ break;
+
+ case WMI_EVENT_AIRPLANE_MODE:
+ case WMI_EVENT_TOUCHPAD_STATE:
+ case WMI_EVENT_FNLOCK_STATE:
+ case WMI_EVENT_KBD_MODE:
+ case WMI_EVENT_CAPSLOCK_STATE:
+ case WMI_EVENT_NUMLOCK_STATE:
+ case WMI_EVENT_SCROLLLOCK_STATE:
+ case WMI_EVENT_REFRESH_RATE:
+ case WMI_EVENT_WIN_KEY_LOCK:
+ /* These events are informational or handled by firmware */
+ dev_dbg(&wdev->dev, "State change event: id=%d value=%d\n",
+ event->event_id, event->value_low);
+ break;
+
+ default:
+ dev_dbg(&wdev->dev, "Unknown event: id=0x%02x value=0x%02x\n",
+ event->event_id, event->value_low);
+ break;
+ }
+}
+
+static const struct wmi_device_id bitland_mifs_wmi_id_table[] = {
+ { BITLAND_MIFS_GUID, (void *)BITLAND_WMI_CONTROL },
+ { BITLAND_EVENT_GUID, (void *)BITLAND_WMI_EVENT },
+ {}
+};
+MODULE_DEVICE_TABLE(wmi, bitland_mifs_wmi_id_table);
+
+static struct wmi_driver bitland_mifs_wmi_driver = {
+ .no_singleton = true,
+ .driver = {
+ .name = DRV_NAME,
+ .dev_groups = laptop_groups,
+ .pm = pm_sleep_ptr(&bitland_mifs_wmi_pm_ops),
+ },
+ .id_table = bitland_mifs_wmi_id_table,
+ .min_event_size = sizeof(struct bitland_mifs_event),
+ .probe = bitland_mifs_wmi_probe,
+ .notify_new = bitland_mifs_wmi_notify,
+};
+
+module_wmi_driver(bitland_mifs_wmi_driver);
+
+MODULE_AUTHOR("Mingyou Chen <qby140326@gmail.com>");
+MODULE_DESCRIPTION("Bitland MIFS (MiInterface) WMI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell/dell-rbtn.c b/drivers/platform/x86/dell/dell-rbtn.c
index a415c432d4c3..34af9f4ff741 100644
--- a/drivers/platform/x86/dell/dell-rbtn.c
+++ b/drivers/platform/x86/dell/dell-rbtn.c
@@ -9,6 +9,7 @@
#include <linux/acpi.h>
#include <linux/rfkill.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include "dell-rbtn.h"
@@ -109,9 +110,9 @@ static const struct rfkill_ops rbtn_ops = {
.set_block = rbtn_rfkill_set_block,
};
-static int rbtn_rfkill_init(struct acpi_device *device)
+static int rbtn_rfkill_init(struct device *dev)
{
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
int ret;
if (rbtn_data->rfkill)
@@ -122,8 +123,8 @@ static int rbtn_rfkill_init(struct acpi_device *device)
* but rfkill interface does not support "ANY" type
* so "WLAN" type is used
*/
- rbtn_data->rfkill = rfkill_alloc("dell-rbtn", &device->dev,
- RFKILL_TYPE_WLAN, &rbtn_ops, device);
+ rbtn_data->rfkill = rfkill_alloc("dell-rbtn", dev, RFKILL_TYPE_WLAN,
+ &rbtn_ops, ACPI_COMPANION(dev));
if (!rbtn_data->rfkill)
return -ENOMEM;
@@ -137,9 +138,9 @@ static int rbtn_rfkill_init(struct acpi_device *device)
return 0;
}
-static void rbtn_rfkill_exit(struct acpi_device *device)
+static void rbtn_rfkill_exit(struct device *dev)
{
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
if (!rbtn_data->rfkill)
return;
@@ -149,12 +150,12 @@ static void rbtn_rfkill_exit(struct acpi_device *device)
rbtn_data->rfkill = NULL;
}
-static void rbtn_rfkill_event(struct acpi_device *device)
+static void rbtn_rfkill_event(struct device *dev)
{
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
if (rbtn_data->rfkill)
- rbtn_rfkill_query(rbtn_data->rfkill, device);
+ rbtn_rfkill_query(rbtn_data->rfkill, ACPI_COMPANION(dev));
}
@@ -205,9 +206,9 @@ static void rbtn_input_event(struct rbtn_data *rbtn_data)
* acpi driver
*/
-static int rbtn_add(struct acpi_device *device);
-static void rbtn_remove(struct acpi_device *device);
-static void rbtn_notify(struct acpi_device *device, u32 event);
+static int rbtn_probe(struct platform_device *pdev);
+static void rbtn_remove(struct platform_device *pdev);
+static void rbtn_notify(acpi_handle handle, u32 event, void *data);
static const struct acpi_device_id rbtn_ids[] = {
{ "DELRBTN", 0 },
@@ -251,8 +252,7 @@ static void ACPI_SYSTEM_XFACE rbtn_clear_suspended_flag(void *context)
static int rbtn_suspend(struct device *dev)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct rbtn_data *rbtn_data = acpi_driver_data(device);
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
rbtn_data->suspended = true;
@@ -261,8 +261,7 @@ static int rbtn_suspend(struct device *dev)
static int rbtn_resume(struct device *dev)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct rbtn_data *rbtn_data = acpi_driver_data(device);
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
acpi_status status;
/*
@@ -286,14 +285,13 @@ static int rbtn_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(rbtn_pm_ops, rbtn_suspend, rbtn_resume);
-static struct acpi_driver rbtn_driver = {
- .name = "dell-rbtn",
- .ids = rbtn_ids,
- .drv.pm = &rbtn_pm_ops,
- .ops = {
- .add = rbtn_add,
- .remove = rbtn_remove,
- .notify = rbtn_notify,
+static struct platform_driver rbtn_driver = {
+ .probe = rbtn_probe,
+ .remove = rbtn_remove,
+ .driver = {
+ .name = "dell-rbtn",
+ .acpi_match_table = rbtn_ids,
+ .pm = &rbtn_pm_ops,
},
};
@@ -308,8 +306,7 @@ static ATOMIC_NOTIFIER_HEAD(rbtn_chain_head);
static int rbtn_inc_count(struct device *dev, void *data)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
int *count = data;
if (rbtn_data->type == RBTN_SLIDER)
@@ -320,17 +317,16 @@ static int rbtn_inc_count(struct device *dev, void *data)
static int rbtn_switch_dev(struct device *dev, void *data)
{
- struct acpi_device *device = to_acpi_device(dev);
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
bool enable = data;
if (rbtn_data->type != RBTN_SLIDER)
return 0;
if (enable)
- rbtn_rfkill_init(device);
+ rbtn_rfkill_init(dev);
else
- rbtn_rfkill_exit(device);
+ rbtn_rfkill_exit(dev);
return 0;
}
@@ -342,7 +338,7 @@ int dell_rbtn_notifier_register(struct notifier_block *nb)
int ret;
count = 0;
- ret = driver_for_each_device(&rbtn_driver.drv, NULL, &count,
+ ret = driver_for_each_device(&rbtn_driver.driver, NULL, &count,
rbtn_inc_count);
if (ret || count == 0)
return -ENODEV;
@@ -354,7 +350,7 @@ int dell_rbtn_notifier_register(struct notifier_block *nb)
return ret;
if (auto_remove_rfkill && first)
- ret = driver_for_each_device(&rbtn_driver.drv, NULL,
+ ret = driver_for_each_device(&rbtn_driver.driver, NULL,
(void *)false, rbtn_switch_dev);
return ret;
@@ -370,7 +366,7 @@ int dell_rbtn_notifier_unregister(struct notifier_block *nb)
return ret;
if (auto_remove_rfkill && !rbtn_chain_head.head)
- ret = driver_for_each_device(&rbtn_driver.drv, NULL,
+ ret = driver_for_each_device(&rbtn_driver.driver, NULL,
(void *)true, rbtn_switch_dev);
return ret;
@@ -382,30 +378,48 @@ EXPORT_SYMBOL_GPL(dell_rbtn_notifier_unregister);
* acpi driver functions
*/
-static int rbtn_add(struct acpi_device *device)
+static void rbtn_cleanup(struct device *dev)
{
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
+
+ switch (rbtn_data->type) {
+ case RBTN_TOGGLE:
+ rbtn_input_exit(rbtn_data);
+ break;
+ case RBTN_SLIDER:
+ rbtn_rfkill_exit(dev);
+ break;
+ default:
+ break;
+ }
+}
+
+static int rbtn_probe(struct platform_device *pdev)
+{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct rbtn_data *rbtn_data;
enum rbtn_type type;
int ret = 0;
type = rbtn_check(device);
if (type == RBTN_UNKNOWN) {
- dev_info(&device->dev, "Unknown device type\n");
+ dev_info(&pdev->dev, "Unknown device type\n");
return -EINVAL;
}
- rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL);
+ rbtn_data = devm_kzalloc(&pdev->dev, sizeof(*rbtn_data), GFP_KERNEL);
if (!rbtn_data)
return -ENOMEM;
ret = rbtn_acquire(device, true);
if (ret < 0) {
- dev_err(&device->dev, "Cannot enable device\n");
+ dev_err(&pdev->dev, "Cannot enable device\n");
return ret;
}
+ platform_set_drvdata(pdev, rbtn_data);
+
rbtn_data->type = type;
- device->driver_data = rbtn_data;
switch (rbtn_data->type) {
case RBTN_TOGGLE:
@@ -415,51 +429,54 @@ static int rbtn_add(struct acpi_device *device)
if (auto_remove_rfkill && rbtn_chain_head.head)
ret = 0;
else
- ret = rbtn_rfkill_init(device);
+ ret = rbtn_rfkill_init(&pdev->dev);
break;
default:
ret = -EINVAL;
break;
}
if (ret)
- rbtn_acquire(device, false);
+ goto err;
+
+ ret = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ rbtn_notify, &pdev->dev);
+ if (ret)
+ goto err_cleanup;
+ return 0;
+
+err_cleanup:
+ rbtn_cleanup(&pdev->dev);
+err:
+ rbtn_acquire(device, false);
return ret;
}
-static void rbtn_remove(struct acpi_device *device)
+static void rbtn_remove(struct platform_device *pdev)
{
- struct rbtn_data *rbtn_data = device->driver_data;
-
- switch (rbtn_data->type) {
- case RBTN_TOGGLE:
- rbtn_input_exit(rbtn_data);
- break;
- case RBTN_SLIDER:
- rbtn_rfkill_exit(device);
- break;
- default:
- break;
- }
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, rbtn_notify);
+ rbtn_cleanup(&pdev->dev);
rbtn_acquire(device, false);
}
-static void rbtn_notify(struct acpi_device *device, u32 event)
+static void rbtn_notify(acpi_handle handle, u32 event, void *data)
{
- struct rbtn_data *rbtn_data = device->driver_data;
+ struct device *dev = data;
+ struct rbtn_data *rbtn_data = dev_get_drvdata(dev);
/*
* Some BIOSes send a notification at resume.
* Ignore it to prevent unwanted input events.
*/
if (rbtn_data->suspended) {
- dev_dbg(&device->dev, "ACPI notification ignored\n");
+ dev_dbg(dev, "ACPI notification ignored\n");
return;
}
if (event != 0x80) {
- dev_info(&device->dev, "Received unknown event (0x%x)\n",
+ dev_info(dev, "Received unknown event (0x%x)\n",
event);
return;
}
@@ -469,20 +486,15 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
rbtn_input_event(rbtn_data);
break;
case RBTN_SLIDER:
- rbtn_rfkill_event(device);
- atomic_notifier_call_chain(&rbtn_chain_head, event, device);
+ rbtn_rfkill_event(dev);
+ atomic_notifier_call_chain(&rbtn_chain_head, event, NULL);
break;
default:
break;
}
}
-
-/*
- * module functions
- */
-
-module_acpi_driver(rbtn_driver);
+module_platform_driver(rbtn_driver);
module_param(auto_remove_rfkill, bool, 0444);
diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c
index e7a411ae9ca1..2a5804efd3ea 100644
--- a/drivers/platform/x86/dell/dell-wmi-base.c
+++ b/drivers/platform/x86/dell/dell-wmi-base.c
@@ -825,6 +825,7 @@ static struct wmi_driver dell_wmi_driver = {
.name = "dell-wmi",
},
.id_table = dell_wmi_id_table,
+ .min_event_size = sizeof(u16),
.probe = dell_wmi_probe,
.remove = dell_wmi_remove,
.notify = dell_wmi_notify,
diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h b/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h
index 817ee7ba07ca..5278a93fdaf7 100644
--- a/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h
+++ b/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h
@@ -189,8 +189,8 @@ void exit_bios_attr_set_interface(void);
int init_bios_attr_set_interface(void);
int map_wmi_error(int error_code);
size_t calculate_string_buffer(const char *str);
-size_t calculate_security_buffer(char *authentication);
-void populate_security_buffer(char *buffer, char *authentication);
+size_t calculate_security_buffer(const char *authentication);
+void populate_security_buffer(char *buffer, const char *authentication);
ssize_t populate_string_buffer(char *buffer, size_t buffer_len, const char *str);
int set_new_password(const char *password_type, const char *new);
int init_bios_attr_pass_interface(void);
diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c b/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c
index 09996fbdc707..a85639d8a076 100644
--- a/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c
+++ b/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c
@@ -6,10 +6,32 @@
* Copyright (c) 2020 Dell Inc.
*/
+#include <linux/bug.h>
+
#include "dell-wmi-sysman.h"
get_instance_id(enumeration);
+static int append_enum_string(char *dest, const char *src)
+{
+ size_t dest_len = strlen(dest);
+ ssize_t copied;
+
+ if (WARN_ON_ONCE(dest_len >= MAX_BUFF))
+ return -EINVAL;
+
+ copied = strscpy(dest + dest_len, src, MAX_BUFF - dest_len);
+ if (copied < 0)
+ return -EINVAL;
+
+ dest_len += copied;
+ copied = strscpy(dest + dest_len, ";", MAX_BUFF - dest_len);
+ if (copied < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
int instance_id = get_enumeration_instance_id(kobj);
@@ -176,9 +198,9 @@ int populate_enum_data(union acpi_object *enumeration_obj, int instance_id,
return -EINVAL;
if (check_property_type(enumeration, next_obj, ACPI_TYPE_STRING))
return -EINVAL;
- strcat(wmi_priv.enumeration_data[instance_id].dell_value_modifier,
- enumeration_obj[next_obj++].string.pointer);
- strcat(wmi_priv.enumeration_data[instance_id].dell_value_modifier, ";");
+ if (append_enum_string(wmi_priv.enumeration_data[instance_id].dell_value_modifier,
+ enumeration_obj[next_obj++].string.pointer))
+ return -EINVAL;
}
if (next_obj >= enum_property_count)
@@ -193,9 +215,9 @@ int populate_enum_data(union acpi_object *enumeration_obj, int instance_id,
return -EINVAL;
if (check_property_type(enumeration, next_obj, ACPI_TYPE_STRING))
return -EINVAL;
- strcat(wmi_priv.enumeration_data[instance_id].possible_values,
- enumeration_obj[next_obj++].string.pointer);
- strcat(wmi_priv.enumeration_data[instance_id].possible_values, ";");
+ if (append_enum_string(wmi_priv.enumeration_data[instance_id].possible_values,
+ enumeration_obj[next_obj++].string.pointer))
+ return -EINVAL;
}
return sysfs_create_group(attr_name_kobj, &enumeration_attr_group);
diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
index 9dddab6c9397..51d25fdc1389 100644
--- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
+++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
@@ -7,10 +7,13 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/align.h>
#include <linux/fs.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
#include <linux/wmi.h>
#include "dell-wmi-sysman.h"
#include "../../firmware_attributes_class.h"
@@ -72,13 +75,9 @@ size_t calculate_string_buffer(const char *str)
*
* Currently only supported type is Admin password
*/
-size_t calculate_security_buffer(char *authentication)
+size_t calculate_security_buffer(const char *authentication)
{
- if (strlen(authentication) > 0) {
- return (sizeof(u32) * 2) + strlen(authentication) +
- strlen(authentication) % 2;
- }
- return sizeof(u32) * 2;
+ return sizeof(u32) * 2 + ALIGN(strlen(authentication), 2);
}
/**
@@ -88,18 +87,18 @@ size_t calculate_security_buffer(char *authentication)
*
* Currently only supported type is PLAIN TEXT
*/
-void populate_security_buffer(char *buffer, char *authentication)
+void populate_security_buffer(char *buffer, const char *authentication)
{
+ size_t seclen = strlen(authentication);
char *auth = buffer + sizeof(u32) * 2;
u32 *sectype = (u32 *) buffer;
- u32 *seclen = sectype + 1;
+ u32 *seclenp = sectype + 1;
- *sectype = strlen(authentication) > 0 ? 1 : 0;
- *seclen = strlen(authentication);
+ *sectype = !!seclen;
+ *seclenp = seclen;
/* plain text */
- if (strlen(authentication) > 0)
- memcpy(auth, authentication, *seclen);
+ memcpy(auth, authentication, seclen);
}
/**
@@ -143,17 +142,17 @@ int map_wmi_error(int error_code)
*/
static ssize_t reset_bios_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
- char *start = buf;
+ ssize_t len = 0;
int i;
for (i = 0; i < MAX_TYPES; i++) {
if (i == reset_option)
- buf += sprintf(buf, "[%s] ", reset_types[i]);
+ len += sysfs_emit_at(buf, len, "[%s] ", reset_types[i]);
else
- buf += sprintf(buf, "%s ", reset_types[i]);
+ len += sysfs_emit_at(buf, len, "%s ", reset_types[i]);
}
- buf += sprintf(buf, "\n");
- return buf-start;
+ len += sysfs_emit_at(buf, len, "\n");
+ return len;
}
/**
@@ -194,7 +193,7 @@ static ssize_t reset_bios_store(struct kobject *kobj,
static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", wmi_priv.pending_changes);
+ return sysfs_emit(buf, "%d\n", wmi_priv.pending_changes);
}
static struct kobj_attribute reset_bios = __ATTR_RW(reset_bios);
@@ -220,35 +219,6 @@ static int create_attributes_level_sysfs_files(void)
return 0;
}
-static ssize_t wmi_sysman_attr_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct kobj_attribute *kattr;
- ssize_t ret = -EIO;
-
- kattr = container_of(attr, struct kobj_attribute, attr);
- if (kattr->show)
- ret = kattr->show(kobj, kattr, buf);
- return ret;
-}
-
-static ssize_t wmi_sysman_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
-{
- struct kobj_attribute *kattr;
- ssize_t ret = -EIO;
-
- kattr = container_of(attr, struct kobj_attribute, attr);
- if (kattr->store)
- ret = kattr->store(kobj, kattr, buf, count);
- return ret;
-}
-
-static const struct sysfs_ops wmi_sysman_kobj_sysfs_ops = {
- .show = wmi_sysman_attr_show,
- .store = wmi_sysman_attr_store,
-};
-
static void attr_name_release(struct kobject *kobj)
{
kfree(kobj);
@@ -256,7 +226,7 @@ static void attr_name_release(struct kobject *kobj)
static const struct kobj_type attr_name_ktype = {
.release = attr_name_release,
- .sysfs_ops = &wmi_sysman_kobj_sysfs_ops,
+ .sysfs_ops = &kobj_sysfs_ops,
};
/**
@@ -343,7 +313,7 @@ static int alloc_attributes_data(int attr_type)
* destroy_attribute_objs() - Free a kset of kobjects
* @kset: The kset to destroy
*
- * Fress kobjects created for each attribute_name under attribute type kset
+ * Frees kobjects created for each attribute_name under attribute type kset.
*/
static void destroy_attribute_objs(struct kset *kset)
{
diff --git a/drivers/platform/x86/dell/dell_rbu.c b/drivers/platform/x86/dell/dell_rbu.c
index eb50f1d75d0c..3fa9de9aa47b 100644
--- a/drivers/platform/x86/dell/dell_rbu.c
+++ b/drivers/platform/x86/dell/dell_rbu.c
@@ -30,6 +30,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
+#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -619,9 +620,12 @@ static ssize_t packet_size_write(struct file *filp, struct kobject *kobj,
char *buffer, loff_t pos, size_t count)
{
unsigned long temp;
+
+ if (kstrtoul(buffer, 10, &temp))
+ return -EINVAL;
+
spin_lock(&rbu_data.lock);
packet_empty_list();
- sscanf(buffer, "%lu", &temp);
if (temp < 0xffffffff)
rbu_data.packetsize = temp;
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 974f55e0b36f..02a71095920e 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1204,9 +1204,10 @@ static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
pr_info("Unknown key %x pressed\n", event);
}
-static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
+static void eeepc_acpi_notify(acpi_handle handle, u32 event, void *data)
{
- struct eeepc_laptop *eeepc = acpi_driver_data(device);
+ struct eeepc_laptop *eeepc = data;
+ struct acpi_device *device = eeepc->device;
int old_brightness, new_brightness;
u16 count;
@@ -1360,8 +1361,9 @@ static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
static bool eeepc_device_present;
-static int eeepc_acpi_add(struct acpi_device *device)
+static int eeepc_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct eeepc_laptop *eeepc;
int result;
@@ -1372,9 +1374,10 @@ static int eeepc_acpi_add(struct acpi_device *device)
eeepc->handle = device->handle;
strscpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
strscpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
- device->driver_data = eeepc;
eeepc->device = device;
+ platform_set_drvdata(pdev, eeepc);
+
eeepc->hotplug_disabled = hotplug_disabled;
eeepc_dmi_check(eeepc);
@@ -1422,9 +1425,16 @@ static int eeepc_acpi_add(struct acpi_device *device)
if (result)
goto fail_rfkill;
+ result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
+ eeepc_acpi_notify, eeepc);
+ if (result)
+ goto fail_acpi_notifier;
+
eeepc_device_present = true;
return 0;
+fail_acpi_notifier:
+ eeepc_rfkill_exit(eeepc);
fail_rfkill:
eeepc_led_exit(eeepc);
fail_led:
@@ -1440,10 +1450,12 @@ fail_platform:
return result;
}
-static void eeepc_acpi_remove(struct acpi_device *device)
+static void eeepc_acpi_remove(struct platform_device *pdev)
{
- struct eeepc_laptop *eeepc = acpi_driver_data(device);
+ struct eeepc_laptop *eeepc = platform_get_drvdata(pdev);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_ALL_NOTIFY, eeepc_acpi_notify);
eeepc_backlight_exit(eeepc);
eeepc_rfkill_exit(eeepc);
eeepc_input_exit(eeepc);
@@ -1460,15 +1472,12 @@ static const struct acpi_device_id eeepc_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
-static struct acpi_driver eeepc_acpi_driver = {
- .name = EEEPC_LAPTOP_NAME,
- .class = EEEPC_ACPI_CLASS,
- .ids = eeepc_device_ids,
- .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
- .ops = {
- .add = eeepc_acpi_add,
- .remove = eeepc_acpi_remove,
- .notify = eeepc_acpi_notify,
+static struct platform_driver eeepc_acpi_driver = {
+ .probe = eeepc_acpi_probe,
+ .remove = eeepc_acpi_remove,
+ .driver = {
+ .name = EEEPC_LAPTOP_NAME,
+ .acpi_match_table = eeepc_device_ids,
},
};
@@ -1481,7 +1490,7 @@ static int __init eeepc_laptop_init(void)
if (result < 0)
return result;
- result = acpi_bus_register_driver(&eeepc_acpi_driver);
+ result = platform_driver_register(&eeepc_acpi_driver);
if (result < 0)
goto fail_acpi_driver;
@@ -1493,7 +1502,7 @@ static int __init eeepc_laptop_init(void)
return 0;
fail_no_device:
- acpi_bus_unregister_driver(&eeepc_acpi_driver);
+ platform_driver_unregister(&eeepc_acpi_driver);
fail_acpi_driver:
platform_driver_unregister(&platform_driver);
return result;
@@ -1501,7 +1510,7 @@ fail_acpi_driver:
static void __exit eeepc_laptop_exit(void)
{
- acpi_bus_unregister_driver(&eeepc_acpi_driver);
+ platform_driver_unregister(&eeepc_acpi_driver);
platform_driver_unregister(&platform_driver);
}
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 931fbcdd21b8..2e265be2267e 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -144,11 +144,11 @@ struct fujitsu_laptop {
bool charge_control_supported;
};
-static struct acpi_device *fext;
+static struct device *fext;
/* Fujitsu ACPI interface function */
-static int call_fext_func(struct acpi_device *device,
+static int call_fext_func(struct device *dev,
int func, int op, int feature, int state)
{
union acpi_object params[4] = {
@@ -158,18 +158,17 @@ static int call_fext_func(struct acpi_device *device,
{ .integer.type = ACPI_TYPE_INTEGER, .integer.value = state }
};
struct acpi_object_list arg_list = { 4, params };
+ acpi_handle handle = ACPI_HANDLE(dev);
unsigned long long value;
acpi_status status;
- status = acpi_evaluate_integer(device->handle, "FUNC", &arg_list,
- &value);
+ status = acpi_evaluate_integer(handle, "FUNC", &arg_list, &value);
if (ACPI_FAILURE(status)) {
- acpi_handle_err(device->handle, "Failed to evaluate FUNC\n");
+ acpi_handle_err(handle, "Failed to evaluate FUNC\n");
return -ENODEV;
}
- acpi_handle_debug(device->handle,
- "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
+ acpi_handle_debug(handle, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
func, op, feature, state, (int)value);
return value;
}
@@ -251,9 +250,9 @@ static struct acpi_battery_hook battery_hook = {
* These functions are intended to be called from acpi_fujitsu_laptop_add and
* acpi_fujitsu_laptop_remove.
*/
-static int fujitsu_battery_charge_control_add(struct acpi_device *device)
+static int fujitsu_battery_charge_control_add(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
int s006_cc_return;
priv->charge_control_supported = false;
@@ -274,9 +273,9 @@ static int fujitsu_battery_charge_control_add(struct acpi_device *device)
return 0;
}
-static void fujitsu_battery_charge_control_remove(struct acpi_device *device)
+static void fujitsu_battery_charge_control_remove(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
if (priv->charge_control_supported)
battery_hook_unregister(&battery_hook);
@@ -284,15 +283,16 @@ static void fujitsu_battery_charge_control_remove(struct acpi_device *device)
/* Hardware access for LCD brightness control */
-static int set_lcd_level(struct acpi_device *device, int level)
+static int set_lcd_level(struct device *dev, int level)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
+ acpi_handle handle = ACPI_HANDLE(dev);
acpi_status status;
char *method;
switch (use_alt_lcd_levels) {
case -1:
- if (acpi_has_method(device->handle, "SBL2"))
+ if (acpi_has_method(handle, "SBL2"))
method = "SBL2";
else
method = "SBLL";
@@ -305,16 +305,14 @@ static int set_lcd_level(struct acpi_device *device, int level)
break;
}
- acpi_handle_debug(device->handle, "set lcd level via %s [%d]\n", method,
- level);
+ acpi_handle_debug(handle, "set lcd level via %s [%d]\n", method, level);
if (level < 0 || level >= priv->max_brightness)
return -EINVAL;
- status = acpi_execute_simple_method(device->handle, method, level);
+ status = acpi_execute_simple_method(handle, method, level);
if (ACPI_FAILURE(status)) {
- acpi_handle_err(device->handle, "Failed to evaluate %s\n",
- method);
+ acpi_handle_err(handle, "Failed to evaluate %s\n", method);
return -ENODEV;
}
@@ -323,15 +321,16 @@ static int set_lcd_level(struct acpi_device *device, int level)
return 0;
}
-static int get_lcd_level(struct acpi_device *device)
+static int get_lcd_level(struct device *dev)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
+ acpi_handle handle = ACPI_HANDLE(dev);
unsigned long long state = 0;
acpi_status status = AE_OK;
- acpi_handle_debug(device->handle, "get lcd level via GBLL\n");
+ acpi_handle_debug(handle, "get lcd level via GBLL\n");
- status = acpi_evaluate_integer(device->handle, "GBLL", NULL, &state);
+ status = acpi_evaluate_integer(handle, "GBLL", NULL, &state);
if (ACPI_FAILURE(status))
return 0;
@@ -340,15 +339,16 @@ static int get_lcd_level(struct acpi_device *device)
return priv->brightness_level;
}
-static int get_max_brightness(struct acpi_device *device)
+static int get_max_brightness(struct device *dev)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
+ acpi_handle handle = ACPI_HANDLE(dev);
unsigned long long state = 0;
acpi_status status = AE_OK;
- acpi_handle_debug(device->handle, "get max lcd level via RBLL\n");
+ acpi_handle_debug(handle, "get max lcd level via RBLL\n");
- status = acpi_evaluate_integer(device->handle, "RBLL", NULL, &state);
+ status = acpi_evaluate_integer(handle, "RBLL", NULL, &state);
if (ACPI_FAILURE(status))
return -1;
@@ -361,15 +361,13 @@ static int get_max_brightness(struct acpi_device *device)
static int bl_get_brightness(struct backlight_device *b)
{
- struct acpi_device *device = bl_get_data(b);
+ struct device *dev = bl_get_data(b);
- return b->props.power == BACKLIGHT_POWER_OFF ? 0 : get_lcd_level(device);
+ return b->props.power == BACKLIGHT_POWER_OFF ? 0 : get_lcd_level(dev);
}
static int bl_update_status(struct backlight_device *b)
{
- struct acpi_device *device = bl_get_data(b);
-
if (fext) {
if (b->props.power == BACKLIGHT_POWER_OFF)
call_fext_func(fext, FUNC_BACKLIGHT, 0x1,
@@ -379,7 +377,7 @@ static int bl_update_status(struct backlight_device *b)
BACKLIGHT_PARAM_POWER, BACKLIGHT_ON);
}
- return set_lcd_level(device, b->props.brightness);
+ return set_lcd_level(bl_get_data(b), b->props.brightness);
}
static const struct backlight_ops fujitsu_bl_ops = {
@@ -455,12 +453,13 @@ static const struct key_entry keymap_backlight[] = {
{ KE_END, 0 }
};
-static int acpi_fujitsu_bl_input_setup(struct acpi_device *device)
+static int acpi_fujitsu_bl_input_setup(struct device *dev)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
+ struct acpi_device *device = ACPI_COMPANION(dev);
int ret;
- priv->input = devm_input_allocate_device(&device->dev);
+ priv->input = devm_input_allocate_device(dev);
if (!priv->input)
return -ENOMEM;
@@ -479,9 +478,9 @@ static int acpi_fujitsu_bl_input_setup(struct acpi_device *device)
return input_register_device(priv->input);
}
-static int fujitsu_backlight_register(struct acpi_device *device)
+static int fujitsu_backlight_register(struct device *dev)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
const struct backlight_properties props = {
.brightness = priv->brightness_level,
.max_brightness = priv->max_brightness - 1,
@@ -489,9 +488,8 @@ static int fujitsu_backlight_register(struct acpi_device *device)
};
struct backlight_device *bd;
- bd = devm_backlight_device_register(&device->dev, "fujitsu-laptop",
- &device->dev, device,
- &fujitsu_bl_ops, &props);
+ bd = devm_backlight_device_register(dev, "fujitsu-laptop",
+ dev, dev, &fujitsu_bl_ops, &props);
if (IS_ERR(bd))
return PTR_ERR(bd);
@@ -500,65 +498,78 @@ static int fujitsu_backlight_register(struct acpi_device *device)
return 0;
}
-static int acpi_fujitsu_bl_add(struct acpi_device *device)
+/* Brightness notify */
+
+static void acpi_fujitsu_bl_notify(acpi_handle handle, u32 event, void *data)
{
+ struct device *dev = data;
+ struct fujitsu_bl *priv = dev_get_drvdata(dev);
+ int oldb, newb;
+
+ if (event != ACPI_FUJITSU_NOTIFY_CODE) {
+ acpi_handle_info(handle, "unsupported event [0x%x]\n", event);
+ sparse_keymap_report_event(priv->input, -1, 1, true);
+ return;
+ }
+
+ oldb = priv->brightness_level;
+ get_lcd_level(dev);
+ newb = priv->brightness_level;
+
+ acpi_handle_debug(handle, "brightness button event [%i -> %i]\n",
+ oldb, newb);
+
+ if (oldb == newb)
+ return;
+
+ if (!disable_brightness_adjust)
+ set_lcd_level(dev, newb);
+
+ sparse_keymap_report_event(priv->input, oldb < newb, 1, true);
+}
+
+static int acpi_fujitsu_bl_probe(struct platform_device *pdev)
+{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct fujitsu_bl *priv;
int ret;
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
return -ENODEV;
- priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
fujitsu_bl = priv;
strscpy(acpi_device_name(device), ACPI_FUJITSU_BL_DEVICE_NAME);
strscpy(acpi_device_class(device), ACPI_FUJITSU_CLASS);
- device->driver_data = priv;
+
+ platform_set_drvdata(pdev, priv);
pr_info("ACPI: %s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
- if (get_max_brightness(device) <= 0)
+ if (get_max_brightness(&pdev->dev) <= 0)
priv->max_brightness = FUJITSU_LCD_N_LEVELS;
- get_lcd_level(device);
+ get_lcd_level(&pdev->dev);
- ret = acpi_fujitsu_bl_input_setup(device);
+ ret = acpi_fujitsu_bl_input_setup(&pdev->dev);
if (ret)
return ret;
- return fujitsu_backlight_register(device);
-}
+ ret = fujitsu_backlight_register(&pdev->dev);
+ if (ret)
+ return ret;
-/* Brightness notify */
+ return acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_fujitsu_bl_notify, &pdev->dev);
+}
-static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
+static void acpi_fujitsu_bl_remove(struct platform_device *pdev)
{
- struct fujitsu_bl *priv = acpi_driver_data(device);
- int oldb, newb;
-
- if (event != ACPI_FUJITSU_NOTIFY_CODE) {
- acpi_handle_info(device->handle, "unsupported event [0x%x]\n",
- event);
- sparse_keymap_report_event(priv->input, -1, 1, true);
- return;
- }
-
- oldb = priv->brightness_level;
- get_lcd_level(device);
- newb = priv->brightness_level;
-
- acpi_handle_debug(device->handle,
- "brightness button event [%i -> %i]\n", oldb, newb);
-
- if (oldb == newb)
- return;
-
- if (!disable_brightness_adjust)
- set_lcd_level(device, newb);
-
- sparse_keymap_report_event(priv->input, oldb < newb, 1, true);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, acpi_fujitsu_bl_notify);
}
/* ACPI device for hotkey handling */
@@ -653,12 +664,13 @@ static const struct dmi_system_id fujitsu_laptop_dmi_table[] = {
{}
};
-static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device)
+static int acpi_fujitsu_laptop_input_setup(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
+ struct acpi_device *device = ACPI_COMPANION(dev);
int ret;
- priv->input = devm_input_allocate_device(&device->dev);
+ priv->input = devm_input_allocate_device(dev);
if (!priv->input)
return -ENOMEM;
@@ -677,9 +689,9 @@ static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device)
return input_register_device(priv->input);
}
-static int fujitsu_laptop_platform_add(struct acpi_device *device)
+static int fujitsu_laptop_platform_add(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
int ret;
priv->pf_device = platform_device_alloc("fujitsu-laptop", PLATFORM_DEVID_NONE);
@@ -707,9 +719,9 @@ err_put_platform_device:
return ret;
}
-static void fujitsu_laptop_platform_remove(struct acpi_device *device)
+static void fujitsu_laptop_platform_remove(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
sysfs_remove_group(&priv->pf_device->dev.kobj,
&fujitsu_pf_attribute_group);
@@ -719,7 +731,7 @@ static void fujitsu_laptop_platform_remove(struct acpi_device *device)
static int logolamp_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
int poweron = FUNC_LED_ON, always = FUNC_LED_ON;
int ret;
@@ -729,23 +741,23 @@ static int logolamp_set(struct led_classdev *cdev,
if (brightness < LED_FULL)
always = FUNC_LED_OFF;
- ret = call_fext_func(device, FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
+ ret = call_fext_func(parent, FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
if (ret < 0)
return ret;
- return call_fext_func(device, FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
+ return call_fext_func(parent, FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
}
static enum led_brightness logolamp_get(struct led_classdev *cdev)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
int ret;
- ret = call_fext_func(device, FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
+ ret = call_fext_func(parent, FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
if (ret == FUNC_LED_ON)
return LED_FULL;
- ret = call_fext_func(device, FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
+ ret = call_fext_func(parent, FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
if (ret == FUNC_LED_ON)
return LED_HALF;
@@ -755,22 +767,21 @@ static enum led_brightness logolamp_get(struct led_classdev *cdev)
static int kblamps_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
if (brightness >= LED_FULL)
- return call_fext_func(device, FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
+ return call_fext_func(parent, FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
FUNC_LED_ON);
else
- return call_fext_func(device, FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
+ return call_fext_func(parent, FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
FUNC_LED_OFF);
}
static enum led_brightness kblamps_get(struct led_classdev *cdev)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
enum led_brightness brightness = LED_OFF;
- if (call_fext_func(device,
+ if (call_fext_func(cdev->dev->parent,
FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
brightness = LED_FULL;
@@ -780,22 +791,22 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev)
static int radio_led_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
if (brightness >= LED_FULL)
- return call_fext_func(device, FUNC_FLAGS, 0x5, RADIO_LED_ON,
+ return call_fext_func(parent, FUNC_FLAGS, 0x5, RADIO_LED_ON,
RADIO_LED_ON);
else
- return call_fext_func(device, FUNC_FLAGS, 0x5, RADIO_LED_ON,
+ return call_fext_func(parent, FUNC_FLAGS, 0x5, RADIO_LED_ON,
0x0);
}
static enum led_brightness radio_led_get(struct led_classdev *cdev)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
enum led_brightness brightness = LED_OFF;
- if (call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
+ if (call_fext_func(parent, FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
brightness = LED_FULL;
return brightness;
@@ -804,60 +815,58 @@ static enum led_brightness radio_led_get(struct led_classdev *cdev)
static int eco_led_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
int curr;
- curr = call_fext_func(device, FUNC_LEDS, 0x2, ECO_LED, 0x0);
+ curr = call_fext_func(parent, FUNC_LEDS, 0x2, ECO_LED, 0x0);
if (brightness >= LED_FULL)
- return call_fext_func(device, FUNC_LEDS, 0x1, ECO_LED,
+ return call_fext_func(parent, FUNC_LEDS, 0x1, ECO_LED,
curr | ECO_LED_ON);
else
- return call_fext_func(device, FUNC_LEDS, 0x1, ECO_LED,
+ return call_fext_func(parent, FUNC_LEDS, 0x1, ECO_LED,
curr & ~ECO_LED_ON);
}
static enum led_brightness eco_led_get(struct led_classdev *cdev)
{
- struct acpi_device *device = to_acpi_device(cdev->dev->parent);
+ struct device *parent = cdev->dev->parent;
enum led_brightness brightness = LED_OFF;
- if (call_fext_func(device, FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
+ if (call_fext_func(parent, FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
brightness = LED_FULL;
return brightness;
}
-static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
+static int acpi_fujitsu_laptop_leds_register(struct device *dev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
struct led_classdev *led;
int ret;
- if (call_fext_func(device,
- FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
- led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL);
+ if (call_fext_func(dev, FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
+ led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
led->name = "fujitsu::logolamp";
led->brightness_set_blocking = logolamp_set;
led->brightness_get = logolamp_get;
- ret = devm_led_classdev_register(&device->dev, led);
+ ret = devm_led_classdev_register(dev, led);
if (ret)
return ret;
}
- if ((call_fext_func(device,
- FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
- (call_fext_func(device, FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
- led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL);
+ if ((call_fext_func(dev, FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
+ (call_fext_func(dev, FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
+ led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
led->name = "fujitsu::kblamps";
led->brightness_set_blocking = kblamps_set;
led->brightness_get = kblamps_get;
- ret = devm_led_classdev_register(&device->dev, led);
+ ret = devm_led_classdev_register(dev, led);
if (ret)
return ret;
}
@@ -872,7 +881,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
* whether given model has a radio toggle button.
*/
if (priv->flags_supported & BIT(17)) {
- led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL);
+ led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
@@ -880,7 +889,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
led->brightness_set_blocking = radio_led_set;
led->brightness_get = radio_led_get;
led->default_trigger = "rfkill-any";
- ret = devm_led_classdev_register(&device->dev, led);
+ ret = devm_led_classdev_register(dev, led);
if (ret)
return ret;
}
@@ -890,17 +899,16 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
* bit 14 seems to indicate presence of said led as well.
* Confirm by testing the status.
*/
- if ((call_fext_func(device, FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
- (call_fext_func(device,
- FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
- led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL);
+ if ((call_fext_func(dev, FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
+ (call_fext_func(dev, FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
+ led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
led->name = "fujitsu::eco_led";
led->brightness_set_blocking = eco_led_set;
led->brightness_get = eco_led_get;
- ret = devm_led_classdev_register(&device->dev, led);
+ ret = devm_led_classdev_register(dev, led);
if (ret)
return ret;
}
@@ -908,21 +916,98 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
return 0;
}
-static int acpi_fujitsu_laptop_add(struct acpi_device *device)
+static void acpi_fujitsu_laptop_press(struct device *dev, int scancode)
+{
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
+ sizeof(scancode), &priv->fifo_lock);
+ if (ret != sizeof(scancode)) {
+ dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n",
+ scancode);
+ return;
+ }
+ sparse_keymap_report_event(priv->input, scancode, 1, false);
+ dev_dbg(&priv->input->dev, "Push scancode into ringbuffer [0x%x]\n",
+ scancode);
+}
+
+static void acpi_fujitsu_laptop_release(struct device *dev)
+{
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
+ int scancode, ret;
+
+ while (true) {
+ ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode,
+ sizeof(scancode), &priv->fifo_lock);
+ if (ret != sizeof(scancode))
+ return;
+ sparse_keymap_report_event(priv->input, scancode, 0, false);
+ dev_dbg(&priv->input->dev,
+ "Pop scancode from ringbuffer [0x%x]\n", scancode);
+ }
+}
+
+static void acpi_fujitsu_laptop_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct device *dev = data;
+ struct fujitsu_laptop *priv = dev_get_drvdata(dev);
+ unsigned long flags;
+ int scancode, i = 0;
+ unsigned int irb;
+
+ if (event != ACPI_FUJITSU_NOTIFY_CODE) {
+ acpi_handle_info(handle, "Unsupported event [0x%x]\n", event);
+ sparse_keymap_report_event(priv->input, -1, 1, true);
+ return;
+ }
+
+ if (priv->flags_supported)
+ priv->flags_state = call_fext_func(dev, FUNC_FLAGS, 0x4, 0x0, 0x0);
+
+ while ((irb = call_fext_func(dev, FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 &&
+ i++ < MAX_HOTKEY_RINGBUFFER_SIZE) {
+ scancode = irb & 0x4ff;
+ if (sparse_keymap_entry_from_scancode(priv->input, scancode))
+ acpi_fujitsu_laptop_press(dev, scancode);
+ else if (scancode == 0)
+ acpi_fujitsu_laptop_release(dev);
+ else
+ acpi_handle_info(handle, "Unknown GIRB result [%x]\n", irb);
+ }
+
+ /*
+ * First seen on the Skylake-based Lifebook E736/E746/E756), the
+ * 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 & (FLAG_SOFTKEYS)) {
+ flags = call_fext_func(dev, FUNC_FLAGS, 0x1, 0x0, 0x0);
+ flags &= (FLAG_SOFTKEYS);
+ for_each_set_bit(i, &flags, BITS_PER_LONG)
+ sparse_keymap_report_event(priv->input, BIT(i), 1, true);
+ }
+}
+
+static int acpi_fujitsu_laptop_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct fujitsu_laptop *priv;
int ret, i = 0;
- priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
WARN_ONCE(fext, "More than one FUJ02E3 ACPI device was found. Driver may not work as intended.");
- fext = device;
+ fext = &pdev->dev;
strscpy(acpi_device_name(device), ACPI_FUJITSU_LAPTOP_DEVICE_NAME);
strscpy(acpi_device_class(device), ACPI_FUJITSU_CLASS);
- device->driver_data = priv;
+
+ platform_set_drvdata(pdev, priv);
/* kfifo */
spin_lock_init(&priv->fifo_lock);
@@ -934,14 +1019,13 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
pr_info("ACPI: %s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
- while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 &&
+ while (call_fext_func(fext, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 &&
i++ < MAX_HOTKEY_RINGBUFFER_SIZE)
; /* No action, result is discarded */
acpi_handle_debug(device->handle, "Discarded %i ringbuffer entries\n",
i);
- priv->flags_supported = call_fext_func(device, FUNC_FLAGS, 0x0, 0x0,
- 0x0);
+ priv->flags_supported = call_fext_func(fext, FUNC_FLAGS, 0x0, 0x0, 0x0);
/* Make sure our bitmask of supported functions is cleared if the
RFKILL function block is not implemented, like on the S7020. */
@@ -949,12 +1033,12 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
priv->flags_supported = 0;
if (priv->flags_supported)
- priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0,
+ priv->flags_state = call_fext_func(fext, FUNC_FLAGS, 0x4, 0x0,
0x0);
/* Suspect this is a keymap of the application panel, print it */
acpi_handle_info(device->handle, "BTNI: [0x%x]\n",
- call_fext_func(device, FUNC_BUTTONS, 0x0, 0x0, 0x0));
+ call_fext_func(fext, FUNC_BUTTONS, 0x0, 0x0, 0x0));
/* Sync backlight power status */
if (fujitsu_bl && fujitsu_bl->bl_device &&
@@ -966,117 +1050,49 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
fujitsu_bl->bl_device->props.power = BACKLIGHT_POWER_ON;
}
- ret = acpi_fujitsu_laptop_input_setup(device);
+ ret = acpi_fujitsu_laptop_input_setup(fext);
if (ret)
goto err_free_fifo;
- ret = acpi_fujitsu_laptop_leds_register(device);
+ ret = acpi_fujitsu_laptop_leds_register(fext);
if (ret)
goto err_free_fifo;
- ret = fujitsu_laptop_platform_add(device);
+ ret = fujitsu_laptop_platform_add(fext);
if (ret)
goto err_free_fifo;
- ret = fujitsu_battery_charge_control_add(device);
+ ret = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_fujitsu_laptop_notify, fext);
+ if (ret)
+ goto err_platform_remove;
+
+ ret = fujitsu_battery_charge_control_add(fext);
if (ret < 0)
pr_warn("Unable to register battery charge control: %d\n", ret);
return 0;
+err_platform_remove:
+ fujitsu_laptop_platform_remove(fext);
err_free_fifo:
kfifo_free(&priv->fifo);
return ret;
}
-static void acpi_fujitsu_laptop_remove(struct acpi_device *device)
-{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
-
- fujitsu_battery_charge_control_remove(device);
-
- fujitsu_laptop_platform_remove(device);
-
- kfifo_free(&priv->fifo);
-}
-
-static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode)
-{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
- int ret;
-
- ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
- sizeof(scancode), &priv->fifo_lock);
- if (ret != sizeof(scancode)) {
- dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n",
- scancode);
- return;
- }
- sparse_keymap_report_event(priv->input, scancode, 1, false);
- dev_dbg(&priv->input->dev, "Push scancode into ringbuffer [0x%x]\n",
- scancode);
-}
-
-static void acpi_fujitsu_laptop_release(struct acpi_device *device)
+static void acpi_fujitsu_laptop_remove(struct platform_device *pdev)
{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
- int scancode, ret;
-
- while (true) {
- ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode,
- sizeof(scancode), &priv->fifo_lock);
- if (ret != sizeof(scancode))
- return;
- sparse_keymap_report_event(priv->input, scancode, 0, false);
- dev_dbg(&priv->input->dev,
- "Pop scancode from ringbuffer [0x%x]\n", scancode);
- }
-}
+ struct fujitsu_laptop *priv = platform_get_drvdata(pdev);
-static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
-{
- struct fujitsu_laptop *priv = acpi_driver_data(device);
- unsigned long flags;
- int scancode, i = 0;
- unsigned int irb;
+ fujitsu_battery_charge_control_remove(&pdev->dev);
- if (event != ACPI_FUJITSU_NOTIFY_CODE) {
- acpi_handle_info(device->handle, "Unsupported event [0x%x]\n",
- event);
- sparse_keymap_report_event(priv->input, -1, 1, true);
- return;
- }
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev), ACPI_DEVICE_NOTIFY,
+ acpi_fujitsu_laptop_notify);
- if (priv->flags_supported)
- priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0,
- 0x0);
+ fujitsu_laptop_platform_remove(&pdev->dev);
- while ((irb = call_fext_func(device,
- FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 &&
- i++ < MAX_HOTKEY_RINGBUFFER_SIZE) {
- scancode = irb & 0x4ff;
- if (sparse_keymap_entry_from_scancode(priv->input, scancode))
- acpi_fujitsu_laptop_press(device, scancode);
- else if (scancode == 0)
- acpi_fujitsu_laptop_release(device);
- else
- acpi_handle_info(device->handle,
- "Unknown GIRB result [%x]\n", irb);
- }
-
- /*
- * First seen on the Skylake-based Lifebook E736/E746/E756), the
- * 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 & (FLAG_SOFTKEYS)) {
- flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
- flags &= (FLAG_SOFTKEYS);
- for_each_set_bit(i, &flags, BITS_PER_LONG)
- sparse_keymap_report_event(priv->input, BIT(i), 1, true);
- }
+ kfifo_free(&priv->fifo);
}
/* Initialization */
@@ -1086,14 +1102,13 @@ static const struct acpi_device_id fujitsu_bl_device_ids[] = {
{"", 0},
};
-static struct acpi_driver acpi_fujitsu_bl_driver = {
- .name = ACPI_FUJITSU_BL_DRIVER_NAME,
- .class = ACPI_FUJITSU_CLASS,
- .ids = fujitsu_bl_device_ids,
- .ops = {
- .add = acpi_fujitsu_bl_add,
- .notify = acpi_fujitsu_bl_notify,
- },
+static struct platform_driver acpi_fujitsu_bl_driver = {
+ .probe = acpi_fujitsu_bl_probe,
+ .remove = acpi_fujitsu_bl_remove,
+ .driver = {
+ .name = ACPI_FUJITSU_BL_DRIVER_NAME,
+ .acpi_match_table = fujitsu_bl_device_ids,
+ },
};
static const struct acpi_device_id fujitsu_laptop_device_ids[] = {
@@ -1101,15 +1116,13 @@ static const struct acpi_device_id fujitsu_laptop_device_ids[] = {
{"", 0},
};
-static struct acpi_driver acpi_fujitsu_laptop_driver = {
- .name = ACPI_FUJITSU_LAPTOP_DRIVER_NAME,
- .class = ACPI_FUJITSU_CLASS,
- .ids = fujitsu_laptop_device_ids,
- .ops = {
- .add = acpi_fujitsu_laptop_add,
- .remove = acpi_fujitsu_laptop_remove,
- .notify = acpi_fujitsu_laptop_notify,
- },
+static struct platform_driver acpi_fujitsu_laptop_driver = {
+ .probe = acpi_fujitsu_laptop_probe,
+ .remove = acpi_fujitsu_laptop_remove,
+ .driver = {
+ .name = ACPI_FUJITSU_LAPTOP_DRIVER_NAME,
+ .acpi_match_table = fujitsu_laptop_device_ids,
+ },
};
static const struct acpi_device_id fujitsu_ids[] __used = {
@@ -1123,7 +1136,7 @@ static int __init fujitsu_init(void)
{
int ret;
- ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver);
+ ret = platform_driver_register(&acpi_fujitsu_bl_driver);
if (ret)
return ret;
@@ -1135,7 +1148,7 @@ static int __init fujitsu_init(void)
/* Register laptop driver */
- ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver);
+ ret = platform_driver_register(&acpi_fujitsu_laptop_driver);
if (ret)
goto err_unregister_platform_driver;
@@ -1146,18 +1159,18 @@ static int __init fujitsu_init(void)
err_unregister_platform_driver:
platform_driver_unregister(&fujitsu_pf_driver);
err_unregister_acpi:
- acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
+ platform_driver_unregister(&acpi_fujitsu_bl_driver);
return ret;
}
static void __exit fujitsu_cleanup(void)
{
- acpi_bus_unregister_driver(&acpi_fujitsu_laptop_driver);
+ platform_driver_unregister(&acpi_fujitsu_laptop_driver);
platform_driver_unregister(&fujitsu_pf_driver);
- acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
+ platform_driver_unregister(&acpi_fujitsu_bl_driver);
pr_info("driver unloaded\n");
}
diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c
index 17f08ce7552d..8319df28e9b8 100644
--- a/drivers/platform/x86/fujitsu-tablet.c
+++ b/drivers/platform/x86/fujitsu-tablet.c
@@ -18,6 +18,7 @@
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/dmi.h>
+#include <linux/platform_device.h>
#define MODULENAME "fujitsu-tablet"
@@ -442,14 +443,12 @@ static acpi_status fujitsu_walk_resources(struct acpi_resource *res, void *data)
}
}
-static int acpi_fujitsu_add(struct acpi_device *adev)
+static int acpi_fujitsu_probe(struct platform_device *pdev)
{
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
acpi_status status;
int error;
- if (!adev)
- return -EINVAL;
-
status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
fujitsu_walk_resources, NULL);
if (ACPI_FAILURE(status) || !fujitsu.irq || !fujitsu.io_base)
@@ -461,7 +460,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev)
snprintf(fujitsu.phys, sizeof(fujitsu.phys),
"%s/input0", acpi_device_hid(adev));
- error = input_fujitsu_setup(&adev->dev,
+ error = input_fujitsu_setup(&pdev->dev,
acpi_device_name(adev), fujitsu.phys);
if (error)
return error;
@@ -484,7 +483,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev)
return 0;
}
-static void acpi_fujitsu_remove(struct acpi_device *adev)
+static void acpi_fujitsu_remove(struct platform_device *pdev)
{
free_irq(fujitsu.irq, fujitsu_interrupt);
release_region(fujitsu.io_base, fujitsu.io_length);
@@ -501,15 +500,14 @@ static int acpi_fujitsu_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume);
-static struct acpi_driver acpi_fujitsu_driver = {
- .name = MODULENAME,
- .class = "hotkey",
- .ids = fujitsu_ids,
- .ops = {
- .add = acpi_fujitsu_add,
- .remove = acpi_fujitsu_remove,
+static struct platform_driver acpi_fujitsu_driver = {
+ .probe = acpi_fujitsu_probe,
+ .remove = acpi_fujitsu_remove,
+ .driver = {
+ .name = MODULENAME,
+ .acpi_match_table = fujitsu_ids,
+ .pm = &acpi_fujitsu_pm,
},
- .drv.pm = &acpi_fujitsu_pm,
};
static int __init fujitsu_module_init(void)
@@ -518,7 +516,7 @@ static int __init fujitsu_module_init(void)
dmi_check_system(dmi_ids);
- error = acpi_bus_register_driver(&acpi_fujitsu_driver);
+ error = platform_driver_register(&acpi_fujitsu_driver);
if (error)
return error;
@@ -527,7 +525,7 @@ static int __init fujitsu_module_init(void)
static void __exit fujitsu_module_exit(void)
{
- acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+ platform_driver_unregister(&acpi_fujitsu_driver);
}
module_init(fujitsu_module_init);
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 7df00447bba4..d1cc6e7d176c 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -48,6 +48,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45E9-BE91-3D44E2C707E4");
enum hp_ec_offsets {
HP_EC_OFFSET_UNKNOWN = 0x00,
+ HP_NO_THERMAL_PROFILE_OFFSET = 0x01,
HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET = 0x59,
HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET = 0x62,
HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET = 0x63,
@@ -125,6 +126,13 @@ static const struct thermal_profile_params omen_v1_legacy_thermal_params = {
.ec_tp_offset = HP_OMEN_EC_THERMAL_PROFILE_OFFSET,
};
+static const struct thermal_profile_params omen_v1_no_ec_thermal_params = {
+ .performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
+ .balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .low_power = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET,
+};
+
/*
* A generic pointer for the currently-active board's thermal profile
* parameters.
@@ -151,6 +159,7 @@ static const char * const omen_thermal_profile_boards[] = {
"8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB",
"8A15", "8A42",
"8BAD",
+ "8C58",
"8E41",
};
@@ -181,6 +190,10 @@ static const char * const victus_thermal_profile_boards[] = {
/* DMI Board names of Victus 16-r and Victus 16-s laptops */
static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = {
{
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") },
+ .driver_data = (void *)&omen_v1_legacy_thermal_params,
+ },
+ {
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8A4D") },
.driver_data = (void *)&omen_v1_legacy_thermal_params,
},
@@ -213,6 +226,10 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
.driver_data = (void *)&omen_v1_thermal_params,
},
{
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") },
+ .driver_data = (void *)&omen_v1_thermal_params,
+ },
+ {
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") },
.driver_data = (void *)&omen_v1_thermal_params,
},
@@ -228,6 +245,10 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") },
.driver_data = (void *)&victus_s_thermal_params,
},
+ {
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") },
+ .driver_data = (void *)&omen_v1_no_ec_thermal_params,
+ },
{},
};
@@ -397,6 +418,11 @@ static const struct key_entry hp_wmi_keymap[] = {
{ KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } },
{ KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
{ KE_KEY, 0x231b, { KEY_HELP } },
+ { KE_IGNORE, 0x21ab, }, /* FnLock on */
+ { KE_IGNORE, 0x121ab, }, /* FnLock off */
+ { KE_IGNORE, 0x30021aa, }, /* kbd backlight: level 2 -> off */
+ { KE_IGNORE, 0x33221aa, }, /* kbd backlight: off -> level 1 */
+ { KE_IGNORE, 0x36421aa, }, /* kbd backlight: level 1 -> level 2*/
{ KE_END, 0 }
};
@@ -451,23 +477,24 @@ enum pwm_modes {
};
struct hp_wmi_hwmon_priv {
+ struct mutex lock; /* protects mode, pwm */
u8 min_rpm;
u8 max_rpm;
- u8 gpu_delta;
+ int gpu_delta;
u8 mode;
u8 pwm;
struct delayed_work keep_alive_dwork;
};
struct victus_s_fan_table_header {
+ u8 num_fans;
u8 unknown;
- u8 num_entries;
} __packed;
struct victus_s_fan_table_entry {
u8 cpu_rpm;
u8 gpu_rpm;
- u8 unknown;
+ u8 noise_db;
} __packed;
struct victus_s_fan_table {
@@ -1828,7 +1855,8 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil
const struct thermal_profile_params *params;
params = active_thermal_profile_params;
- if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN ||
+ params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) {
*profile = active_platform_profile;
return 0;
}
@@ -2183,7 +2211,8 @@ static int thermal_profile_setup(struct platform_device *device)
* behaves like a wrapper around active_platform_profile, to avoid using
* uninitialized data, we default to PLATFORM_PROFILE_BALANCED.
*/
- if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN ||
+ active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) {
active_platform_profile = PLATFORM_PROFILE_BALANCED;
} else {
err = platform_profile_victus_s_get_ec(&active_platform_profile);
@@ -2351,13 +2380,16 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv)
switch (priv->mode) {
case PWM_MODE_MAX:
- if (is_victus_s_thermal_profile())
- hp_wmi_get_fan_count_userdefine_trigger();
+ if (is_victus_s_thermal_profile()) {
+ ret = hp_wmi_get_fan_count_userdefine_trigger();
+ if (ret < 0)
+ return ret;
+ }
ret = hp_wmi_fan_speed_max_set(1);
if (ret < 0)
return ret;
- schedule_delayed_work(&priv->keep_alive_dwork,
- secs_to_jiffies(KEEP_ALIVE_DELAY_SECS));
+ mod_delayed_work(system_wq, &priv->keep_alive_dwork,
+ secs_to_jiffies(KEEP_ALIVE_DELAY_SECS));
return 0;
case PWM_MODE_MANUAL:
if (!is_victus_s_thermal_profile())
@@ -2365,26 +2397,26 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv)
ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv));
if (ret < 0)
return ret;
- schedule_delayed_work(&priv->keep_alive_dwork,
- secs_to_jiffies(KEEP_ALIVE_DELAY_SECS));
+ mod_delayed_work(system_wq, &priv->keep_alive_dwork,
+ secs_to_jiffies(KEEP_ALIVE_DELAY_SECS));
return 0;
case PWM_MODE_AUTO:
if (is_victus_s_thermal_profile()) {
- hp_wmi_get_fan_count_userdefine_trigger();
+ ret = hp_wmi_get_fan_count_userdefine_trigger();
+ if (ret < 0)
+ return ret;
ret = hp_wmi_fan_speed_max_reset(priv);
} else {
ret = hp_wmi_fan_speed_max_set(0);
}
if (ret < 0)
return ret;
- cancel_delayed_work_sync(&priv->keep_alive_dwork);
+ cancel_delayed_work(&priv->keep_alive_dwork);
return 0;
default:
/* shouldn't happen */
return -EINVAL;
}
-
- return 0;
}
static umode_t hp_wmi_hwmon_is_visible(const void *data,
@@ -2417,6 +2449,7 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
{
struct hp_wmi_hwmon_priv *priv;
int rpm, ret;
+ u8 mode;
priv = dev_get_drvdata(dev);
switch (type) {
@@ -2440,11 +2473,13 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
*val = rpm_to_pwm(rpm / 100, priv);
return 0;
}
- switch (priv->mode) {
+ scoped_guard(mutex, &priv->lock)
+ mode = priv->mode;
+ switch (mode) {
case PWM_MODE_MAX:
case PWM_MODE_MANUAL:
case PWM_MODE_AUTO:
- *val = priv->mode;
+ *val = mode;
return 0;
default:
/* shouldn't happen */
@@ -2462,6 +2497,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
int rpm;
priv = dev_get_drvdata(dev);
+ guard(mutex)(&priv->lock);
switch (type) {
case hwmon_pwm:
if (attr == hwmon_pwm_input) {
@@ -2526,22 +2562,30 @@ static void hp_wmi_hwmon_keep_alive_handler(struct work_struct *work)
{
struct delayed_work *dwork;
struct hp_wmi_hwmon_priv *priv;
+ int ret;
dwork = to_delayed_work(work);
priv = container_of(dwork, struct hp_wmi_hwmon_priv, keep_alive_dwork);
+
+ guard(mutex)(&priv->lock);
/*
* Re-apply the current hwmon context settings.
* NOTE: hp_wmi_apply_fan_settings will handle the re-scheduling.
*/
- hp_wmi_apply_fan_settings(priv);
+ ret = hp_wmi_apply_fan_settings(priv);
+ if (ret)
+ pr_warn_ratelimited("keep-alive failed to refresh fan settings: %d\n",
+ ret);
}
static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
{
u8 fan_data[128] = { 0 };
struct victus_s_fan_table *fan_table;
- u8 min_rpm, max_rpm, gpu_delta;
- int ret;
+ u8 min_rpm, max_rpm;
+ u8 cpu_rpm, gpu_rpm, noise_db;
+ int gpu_delta, i, num_entries, ret;
+ size_t header_size, entry_size;
/* Default behaviour on hwmon init is automatic mode */
priv->mode = PWM_MODE_AUTO;
@@ -2556,13 +2600,36 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
return ret;
fan_table = (struct victus_s_fan_table *)fan_data;
- if (fan_table->header.num_entries == 0 ||
- sizeof(struct victus_s_fan_table_header) +
- sizeof(struct victus_s_fan_table_entry) * fan_table->header.num_entries > sizeof(fan_data))
+ if (fan_table->header.num_fans == 0)
+ return -EINVAL;
+
+ header_size = sizeof(struct victus_s_fan_table_header);
+ entry_size = sizeof(struct victus_s_fan_table_entry);
+ num_entries = (sizeof(fan_data) - header_size) / entry_size;
+ min_rpm = U8_MAX;
+ max_rpm = 0;
+
+ for (i = 0 ; i < num_entries ; i++) {
+ cpu_rpm = fan_table->entries[i].cpu_rpm;
+ gpu_rpm = fan_table->entries[i].gpu_rpm;
+ noise_db = fan_table->entries[i].noise_db;
+
+ /*
+ * On some devices, the fan table is truncated with an all-zero row,
+ * hence we stop parsing here.
+ */
+ if (cpu_rpm == 0 && gpu_rpm == 0 && noise_db == 0)
+ break;
+
+ if (cpu_rpm < min_rpm)
+ min_rpm = cpu_rpm;
+ if (cpu_rpm > max_rpm)
+ max_rpm = cpu_rpm;
+ }
+
+ if (min_rpm == U8_MAX || max_rpm == 0)
return -EINVAL;
- min_rpm = fan_table->entries[0].cpu_rpm;
- max_rpm = fan_table->entries[fan_table->header.num_entries - 1].cpu_rpm;
gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm;
priv->min_rpm = min_rpm;
priv->max_rpm = max_rpm;
@@ -2582,6 +2649,10 @@ static int hp_wmi_hwmon_init(void)
if (!priv)
return -ENOMEM;
+ ret = devm_mutex_init(dev, &priv->lock);
+ if (ret)
+ return ret;
+
ret = hp_wmi_setup_fan_settings(priv);
if (ret)
return ret;
@@ -2595,7 +2666,9 @@ static int hp_wmi_hwmon_init(void)
INIT_DELAYED_WORK(&priv->keep_alive_dwork, hp_wmi_hwmon_keep_alive_handler);
platform_set_drvdata(hp_wmi_platform_dev, priv);
- hp_wmi_apply_fan_settings(priv);
+ ret = hp_wmi_apply_fan_settings(priv);
+ if (ret)
+ dev_warn(dev, "Failed to apply initial fan settings: %d\n", ret);
return 0;
}
diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c
index 1c65ce87cde0..115bb37577a1 100644
--- a/drivers/platform/x86/intel/int3472/discrete.c
+++ b/drivers/platform/x86/intel/int3472/discrete.c
@@ -212,7 +212,11 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
*gpio_flags = GPIO_ACTIVE_HIGH;
break;
case INT3472_GPIO_TYPE_PRIVACY_LED:
- *con_id = "privacy-led";
+ *con_id = "privacy";
+ *gpio_flags = GPIO_ACTIVE_HIGH;
+ break;
+ case INT3472_GPIO_TYPE_STROBE:
+ *con_id = "ir_flood";
*gpio_flags = GPIO_ACTIVE_HIGH;
break;
case INT3472_GPIO_TYPE_HOTPLUG_DETECT:
@@ -252,6 +256,7 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
*
* 0x00 Reset
* 0x01 Power down
+ * 0x02 Strobe
* 0x0b Power enable
* 0x0c Clock enable
* 0x0d Privacy LED
@@ -336,6 +341,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
break;
case INT3472_GPIO_TYPE_CLK_ENABLE:
case INT3472_GPIO_TYPE_PRIVACY_LED:
+ case INT3472_GPIO_TYPE_STROBE:
case INT3472_GPIO_TYPE_POWER_ENABLE:
case INT3472_GPIO_TYPE_DOVDD:
case INT3472_GPIO_TYPE_HANDSHAKE:
@@ -354,7 +360,8 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
break;
case INT3472_GPIO_TYPE_PRIVACY_LED:
- ret = skl_int3472_register_pled(int3472, gpio);
+ case INT3472_GPIO_TYPE_STROBE:
+ ret = skl_int3472_register_led(int3472, gpio, con_id);
if (ret)
err_msg = "Failed to register LED\n";
@@ -429,7 +436,7 @@ void int3472_discrete_cleanup(struct int3472_discrete_device *int3472)
gpiod_remove_lookup_table(&int3472->gpios);
skl_int3472_unregister_clock(int3472);
- skl_int3472_unregister_pled(int3472);
+ skl_int3472_unregister_leds(int3472);
skl_int3472_unregister_regulator(int3472);
}
EXPORT_SYMBOL_NS_GPL(int3472_discrete_cleanup, "INTEL_INT3472_DISCRETE");
diff --git a/drivers/platform/x86/intel/int3472/led.c b/drivers/platform/x86/intel/int3472/led.c
index b1d84b968112..9b2573cc347b 100644
--- a/drivers/platform/x86/intel/int3472/led.c
+++ b/drivers/platform/x86/intel/int3472/led.c
@@ -6,55 +6,58 @@
#include <linux/leds.h>
#include <linux/platform_data/x86/int3472.h>
-static int int3472_pled_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
+static int int3472_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
{
- struct int3472_discrete_device *int3472 =
- container_of(led_cdev, struct int3472_discrete_device, pled.classdev);
+ struct int3472_led *led = container_of(led_cdev, struct int3472_led, classdev);
- gpiod_set_value_cansleep(int3472->pled.gpio, brightness);
+ gpiod_set_value_cansleep(led->gpio, brightness);
return 0;
}
-int skl_int3472_register_pled(struct int3472_discrete_device *int3472, struct gpio_desc *gpio)
+int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio,
+ const char *con_id)
{
+ struct int3472_led *led;
char *p;
int ret;
- if (int3472->pled.classdev.dev)
- return -EBUSY;
+ if (int3472->n_leds >= INT3472_MAX_LEDS)
+ return -ENOSPC;
- int3472->pled.gpio = gpio;
+ led = &int3472->leds[int3472->n_leds];
+ led->gpio = gpio;
/* Generate the name, replacing the ':' in the ACPI devname with '_' */
- snprintf(int3472->pled.name, sizeof(int3472->pled.name),
- "%s::privacy_led", acpi_dev_name(int3472->sensor));
- p = strchr(int3472->pled.name, ':');
+ snprintf(led->name, sizeof(led->name),
+ "%s::%s_led", acpi_dev_name(int3472->sensor), con_id);
+ p = strchr(led->name, ':');
if (p)
*p = '_';
- int3472->pled.classdev.name = int3472->pled.name;
- int3472->pled.classdev.max_brightness = 1;
- int3472->pled.classdev.brightness_set_blocking = int3472_pled_set;
+ led->classdev.name = led->name;
+ led->classdev.max_brightness = 1;
+ led->classdev.brightness_set_blocking = int3472_led_set;
- ret = led_classdev_register(int3472->dev, &int3472->pled.classdev);
+ ret = led_classdev_register(int3472->dev, &led->classdev);
if (ret)
return ret;
- int3472->pled.lookup.provider = int3472->pled.name;
- int3472->pled.lookup.dev_id = int3472->sensor_name;
- int3472->pled.lookup.con_id = "privacy";
- led_add_lookup(&int3472->pled.lookup);
+ led->lookup.provider = led->name;
+ led->lookup.dev_id = int3472->sensor_name;
+ led->lookup.con_id = con_id;
+ led_add_lookup(&led->lookup);
+ int3472->n_leds++;
return 0;
}
-void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472)
+void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472)
{
- if (IS_ERR_OR_NULL(int3472->pled.classdev.dev))
- return;
+ for (unsigned int i = 0; i < int3472->n_leds; i++) {
+ struct int3472_led *led = &int3472->leds[i];
- led_remove_lookup(&int3472->pled.lookup);
- led_classdev_unregister(&int3472->pled.classdev);
- gpiod_put(int3472->pled.gpio);
+ led_remove_lookup(&led->lookup);
+ led_classdev_unregister(&led->classdev);
+ gpiod_put(led->gpio);
+ }
}
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 02b303418d18..d91e1ab842d6 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -1315,7 +1315,7 @@ static struct telem_endpoint *pmc_core_register_endpoint(struct pci_dev *pcidev,
unsigned int i;
for (i = 0; guids[i]; i++) {
- ep = pmt_telem_find_and_register_endpoint(pcidev, guids[i], 0);
+ ep = pmt_telem_find_and_register_endpoint(&pcidev->dev, guids[i], 0);
if (!IS_ERR(ep))
return ep;
}
@@ -1600,7 +1600,7 @@ static int pmc_core_get_telem_info(struct pmc_dev *pmcdev, struct pmc_dev_info *
if (!pmc->map->lpm_req_guid)
return -ENXIO;
- ep = pmt_telem_find_and_register_endpoint(pcidev, pmc->map->lpm_req_guid, 0);
+ ep = pmt_telem_find_and_register_endpoint(&pcidev->dev, pmc->map->lpm_req_guid, 0);
if (IS_ERR(ep)) {
dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %pe", ep);
return -EPROBE_DEFER;
diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 03fad9331fc0..6f6e83e70fc5 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -60,7 +60,7 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
info.base_addr = ssram_base;
info.parent = &pcidev->dev;
- return intel_vsec_register(pcidev, &info);
+ return intel_vsec_register(&pcidev->dev, &info);
}
static inline u64 get_base(void __iomem *addr, u32 offset)
diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index be3c8d9e4fff..b4c9964df807 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -60,11 +60,11 @@ pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count)
return count;
}
-int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf,
+int pmt_telem_read_mmio(struct device *dev, struct pmt_callbacks *cb, u32 guid, void *buf,
void __iomem *addr, loff_t off, u32 count)
{
if (cb && cb->read_telem)
- return cb->read_telem(pdev, guid, buf, off, count);
+ return cb->read_telem(dev, guid, buf, off, count);
addr += off;
@@ -99,7 +99,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj,
if (count > entry->size - off)
count = entry->size - off;
- count = pmt_telem_read_mmio(entry->pcidev, entry->cb, entry->header.guid, buf,
+ count = pmt_telem_read_mmio(entry->ep->dev, entry->cb, entry->header.guid, buf,
entry->base, off, count);
return count;
@@ -208,7 +208,7 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
struct intel_vsec_device *ivdev,
struct resource *disc_res)
{
- struct pci_dev *pci_dev = ivdev->pcidev;
+ struct pci_dev *pci_dev = to_pci_dev(ivdev->dev);
struct device *dev = &ivdev->auxdev.dev;
struct intel_pmt_header *header = &entry->header;
u8 bir;
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index 3c5ad5f52bca..1ae56a5baad2 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -19,11 +19,12 @@
#define GET_BIR(v) ((v) & GENMASK(2, 0))
#define GET_ADDRESS(v) ((v) & GENMASK(31, 3))
+struct device;
struct pci_dev;
extern struct class intel_pmt_class;
struct telem_endpoint {
- struct pci_dev *pcidev;
+ struct device *dev;
struct telem_header header;
struct pmt_callbacks *cb;
void __iomem *base;
@@ -65,7 +66,7 @@ struct intel_pmt_namespace {
struct intel_pmt_entry *entry);
};
-int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf,
+int pmt_telem_read_mmio(struct device *dev, struct pmt_callbacks *cb, u32 guid, void *buf,
void __iomem *addr, loff_t off, u32 count);
bool intel_pmt_is_early_client_hw(struct device *dev);
int intel_pmt_dev_create(struct intel_pmt_entry *entry,
diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c
index e500aa327d23..c482368bfaae 100644
--- a/drivers/platform/x86/intel/pmt/discovery.c
+++ b/drivers/platform/x86/intel/pmt/discovery.c
@@ -542,7 +542,7 @@ static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxi
if (!priv)
return -ENOMEM;
- priv->parent = &ivdev->pcidev->dev;
+ priv->parent = ivdev->dev;
auxiliary_set_drvdata(auxdev, priv);
priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv,
@@ -609,7 +609,7 @@ void intel_pmt_get_features(struct intel_pmt_entry *entry)
mutex_lock(&feature_list_lock);
list_for_each_entry(feature, &pmt_feature_list, list) {
- if (feature->priv->parent != &entry->ep->pcidev->dev)
+ if (feature->priv->parent != entry->ep->dev)
continue;
pmt_get_features(entry, feature);
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index a52803bfe124..bdc7c24a3678 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -112,7 +112,7 @@ static int pmt_telem_add_endpoint(struct intel_vsec_device *ivdev,
return -ENOMEM;
ep = entry->ep;
- ep->pcidev = ivdev->pcidev;
+ ep->dev = ivdev->dev;
ep->header.access_type = entry->header.access_type;
ep->header.guid = entry->header.guid;
ep->header.base_offset = entry->header.base_offset;
@@ -204,7 +204,7 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info)
goto unlock;
}
- info->pdev = entry->ep->pcidev;
+ info->dev = entry->ep->dev;
info->header = entry->ep->header;
unlock:
@@ -218,9 +218,10 @@ static int pmt_copy_region(struct telemetry_region *region,
struct intel_pmt_entry *entry)
{
+ struct pci_dev *pdev = to_pci_dev(entry->ep->dev);
struct oobmsm_plat_info *plat_info;
- plat_info = intel_vsec_get_mapping(entry->ep->pcidev);
+ plat_info = intel_vsec_get_mapping(pdev);
if (IS_ERR(plat_info))
return PTR_ERR(plat_info);
@@ -308,7 +309,7 @@ int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count)
if (offset + NUM_BYTES_QWORD(count) > size)
return -EINVAL;
- pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base, offset,
+ pmt_telem_read_mmio(ep->dev, ep->cb, ep->header.guid, data, ep->base, offset,
NUM_BYTES_QWORD(count));
return ep->present ? 0 : -EPIPE;
@@ -335,7 +336,7 @@ int pmt_telem_read32(struct telem_endpoint *ep, u32 id, u32 *data, u32 count)
EXPORT_SYMBOL_NS_GPL(pmt_telem_read32, "INTEL_PMT_TELEMETRY");
struct telem_endpoint *
-pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos)
+pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos)
{
int devid = 0;
int inst = 0;
@@ -348,7 +349,7 @@ pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos)
if (err)
return ERR_PTR(err);
- if (ep_info.header.guid == guid && ep_info.pdev == pcidev) {
+ if (ep_info.header.guid == guid && ep_info.dev == dev) {
if (inst == pos)
return pmt_telem_register_endpoint(devid);
++inst;
diff --git a/drivers/platform/x86/intel/pmt/telemetry.h b/drivers/platform/x86/intel/pmt/telemetry.h
index d45af5512b4e..0f88c5e7d90e 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.h
+++ b/drivers/platform/x86/intel/pmt/telemetry.h
@@ -6,8 +6,8 @@
#define PMT_TELEM_TELEMETRY 0
#define PMT_TELEM_CRASHLOG 1
+struct device;
struct telem_endpoint;
-struct pci_dev;
struct telem_header {
u8 access_type;
@@ -17,7 +17,7 @@ struct telem_header {
};
struct telem_endpoint_info {
- struct pci_dev *pdev;
+ struct device *dev;
struct telem_header header;
};
@@ -71,8 +71,8 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info);
/**
* pmt_telem_find_and_register_endpoint() - Get a telemetry endpoint from
- * pci_dev device, guid and pos
- * @pdev: PCI device inside the Intel vsec
+ * device, guid and pos
+ * @dev: device inside the Intel vsec
* @guid: GUID of the telemetry space
* @pos: Instance of the guid
*
@@ -80,8 +80,8 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info);
* * endpoint - On success returns pointer to the telemetry endpoint
* * -ENXIO - telemetry endpoint not found
*/
-struct telem_endpoint *pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev,
- u32 guid, u16 pos);
+struct telem_endpoint *
+pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos);
/**
* pmt_telem_read() - Read qwords from counter sram using sample id
diff --git a/drivers/platform/x86/intel/rst.c b/drivers/platform/x86/intel/rst.c
index f3a60e14d4c1..4bd10927aad9 100644
--- a/drivers/platform/x86/intel/rst.c
+++ b/drivers/platform/x86/intel/rst.c
@@ -5,6 +5,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
MODULE_DESCRIPTION("Intel Rapid Start Technology Driver");
@@ -99,8 +100,9 @@ static struct device_attribute irst_timeout_attr = {
.store = irst_store_wakeup_time
};
-static int irst_add(struct acpi_device *acpi)
+static int irst_probe(struct platform_device *pdev)
{
+ struct acpi_device *acpi = ACPI_COMPANION(&pdev->dev);
int error;
error = device_create_file(&acpi->dev, &irst_timeout_attr);
@@ -114,8 +116,10 @@ static int irst_add(struct acpi_device *acpi)
return error;
}
-static void irst_remove(struct acpi_device *acpi)
+static void irst_remove(struct platform_device *pdev)
{
+ struct acpi_device *acpi = ACPI_COMPANION(&pdev->dev);
+
device_remove_file(&acpi->dev, &irst_wakeup_attr);
device_remove_file(&acpi->dev, &irst_timeout_attr);
}
@@ -125,16 +129,15 @@ static const struct acpi_device_id irst_ids[] = {
{"", 0}
};
-static struct acpi_driver irst_driver = {
- .name = "intel_rapid_start",
- .class = "intel_rapid_start",
- .ids = irst_ids,
- .ops = {
- .add = irst_add,
- .remove = irst_remove,
+static struct platform_driver irst_driver = {
+ .probe = irst_probe,
+ .remove = irst_remove,
+ .driver = {
+ .name = "intel_rapid_start",
+ .acpi_match_table = irst_ids,
},
};
-module_acpi_driver(irst_driver);
+module_platform_driver(irst_driver);
MODULE_DEVICE_TABLE(acpi, irst_ids);
diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index da75f53d0bcc..d7e37d4ace23 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -599,13 +599,14 @@ static int sdsi_get_layout(struct sdsi_priv *priv, struct disc_table *table)
return 0;
}
-static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
+static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct device *dev,
struct disc_table *disc_table, struct resource *disc_res)
{
u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
u32 offset = DT_OFFSET(disc_table->offset);
+ struct pci_dev *parent = to_pci_dev(dev);
struct resource res = {};
/* Starting location of SDSi MMIO region based on access type */
@@ -681,7 +682,7 @@ static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de
return ret;
/* Map the SDSi mailbox registers */
- ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
+ ret = sdsi_map_mbox_registers(priv, intel_cap_dev->dev, &disc_table, disc_res);
if (ret)
return ret;
diff --git a/drivers/platform/x86/intel/smartconnect.c b/drivers/platform/x86/intel/smartconnect.c
index 31019a1a6d5e..4d866b6366d6 100644
--- a/drivers/platform/x86/intel/smartconnect.c
+++ b/drivers/platform/x86/intel/smartconnect.c
@@ -5,22 +5,24 @@
#include <linux/acpi.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
MODULE_DESCRIPTION("Intel Smart Connect disabling driver");
MODULE_LICENSE("GPL");
-static int smartconnect_acpi_init(struct acpi_device *acpi)
+static int smartconnect_acpi_probe(struct platform_device *pdev)
{
+ acpi_handle handle = ACPI_HANDLE(&pdev->dev);
unsigned long long value;
acpi_status status;
- status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value);
+ status = acpi_evaluate_integer(handle, "GAOS", NULL, &value);
if (ACPI_FAILURE(status))
return -EINVAL;
if (value & 0x1) {
- dev_info(&acpi->dev, "Disabling Intel Smart Connect\n");
- status = acpi_execute_simple_method(acpi->handle, "SAOS", 0);
+ dev_info(&pdev->dev, "Disabling Intel Smart Connect\n");
+ status = acpi_execute_simple_method(handle, "SAOS", 0);
}
return 0;
@@ -32,13 +34,12 @@ static const struct acpi_device_id smartconnect_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, smartconnect_ids);
-static struct acpi_driver smartconnect_driver = {
- .name = "intel_smart_connect",
- .class = "intel_smart_connect",
- .ids = smartconnect_ids,
- .ops = {
- .add = smartconnect_acpi_init,
+static struct platform_driver smartconnect_driver = {
+ .probe = smartconnect_acpi_probe,
+ .driver = {
+ .name = "intel_smart_connect",
+ .acpi_match_table = smartconnect_ids,
},
};
-module_acpi_driver(smartconnect_driver);
+module_platform_driver(smartconnect_driver);
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 5059d320edf8..7d5dbc1c1d05 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -24,7 +24,9 @@
#include <linux/intel_vsec.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/overflow.h>
#include <linux/pci.h>
+#include <linux/string.h>
#include <linux/types.h>
#define PMT_XA_START 0
@@ -42,7 +44,7 @@ enum vsec_device_state {
};
struct vsec_priv {
- struct intel_vsec_platform_info *info;
+ const struct intel_vsec_platform_info *info;
struct device *suppliers[VSEC_FEATURE_COUNT];
struct oobmsm_plat_info plat_info;
enum vsec_device_state state[VSEC_FEATURE_COUNT];
@@ -109,6 +111,7 @@ static void intel_vsec_dev_release(struct device *dev)
ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id);
+ kfree(intel_vsec_dev->acpi_disc);
kfree(intel_vsec_dev->resource);
kfree(intel_vsec_dev);
}
@@ -158,18 +161,23 @@ static bool vsec_driver_present(int cap_id)
*/
static const struct pci_device_id intel_vsec_pci_ids[];
-static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev,
+static int intel_vsec_link_devices(struct device *parent, struct device *dev,
int consumer_id)
{
const struct vsec_feature_dependency *deps;
enum vsec_device_state *state;
struct device **suppliers;
struct vsec_priv *priv;
+ struct pci_dev *pdev;
int supplier_id;
if (!consumer_id)
return 0;
+ if (!dev_is_pci(parent))
+ return 0;
+
+ pdev = to_pci_dev(parent);
if (!pci_match_id(intel_vsec_pci_ids, pdev))
return 0;
@@ -204,7 +212,7 @@ static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev,
return 0;
}
-int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
+int intel_vsec_add_aux(struct device *parent,
struct intel_vsec_device *intel_vsec_dev,
const char *name)
{
@@ -252,7 +260,7 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
if (ret)
goto cleanup_aux;
- ret = intel_vsec_link_devices(pdev, &auxdev->dev, intel_vsec_dev->cap_id);
+ ret = intel_vsec_link_devices(parent, &auxdev->dev, intel_vsec_dev->cap_id);
if (ret)
goto cleanup_aux;
@@ -269,33 +277,32 @@ cleanup_aux:
}
EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC");
-static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
- struct intel_vsec_platform_info *info,
- unsigned long cap_id)
+static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *header,
+ const struct intel_vsec_platform_info *info,
+ unsigned long cap_id, u64 base_addr)
{
struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL;
struct resource __free(kfree) *res = NULL;
struct resource *tmp;
struct device *parent;
unsigned long quirks = info->quirks;
- u64 base_addr;
int i;
if (info->parent)
parent = info->parent;
else
- parent = &pdev->dev;
+ parent = dev;
if (!intel_vsec_supported(header->id, info->caps))
return -EINVAL;
if (!header->num_entries) {
- dev_dbg(&pdev->dev, "Invalid 0 entry count for header id %d\n", header->id);
+ dev_dbg(dev, "Invalid 0 entry count for header id %d\n", header->id);
return -EINVAL;
}
if (!header->entry_size) {
- dev_dbg(&pdev->dev, "Invalid 0 entry size for header id %d\n", header->id);
+ dev_dbg(dev, "Invalid 0 entry size for header id %d\n", header->id);
return -EINVAL;
}
@@ -310,17 +317,19 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
if (quirks & VSEC_QUIRK_TABLE_SHIFT)
header->offset >>= TABLE_OFFSET_SHIFT;
- if (info->base_addr)
- base_addr = info->base_addr;
- else
- base_addr = pdev->resource[header->tbir].start;
-
/*
* The DVSEC/VSEC contains the starting offset and count for a block of
* discovery tables. Create a resource array of these tables to the
* auxiliary device driver.
*/
for (i = 0, tmp = res; i < header->num_entries; i++, tmp++) {
+ /*
+ * Skip resource mapping check for ACPI-based discovery
+ * since those tables are read from _DSD, not MMIO.
+ */
+ if (info->src == INTEL_VSEC_DISC_ACPI)
+ break;
+
tmp->start = base_addr + header->offset + i * (header->entry_size * sizeof(u32));
tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
tmp->flags = IORESOURCE_MEM;
@@ -332,13 +341,26 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
release_mem_region(tmp->start, resource_size(tmp));
}
- intel_vsec_dev->pcidev = pdev;
+ intel_vsec_dev->dev = dev;
intel_vsec_dev->resource = no_free_ptr(res);
intel_vsec_dev->num_resources = header->num_entries;
intel_vsec_dev->quirks = info->quirks;
intel_vsec_dev->base_addr = info->base_addr;
intel_vsec_dev->priv_data = info->priv_data;
intel_vsec_dev->cap_id = cap_id;
+ intel_vsec_dev->src = info->src;
+
+ if (info->src == INTEL_VSEC_DISC_ACPI) {
+ size_t bytes;
+
+ if (check_mul_overflow(intel_vsec_dev->num_resources,
+ sizeof(*info->acpi_disc), &bytes))
+ return -EOVERFLOW;
+
+ intel_vsec_dev->acpi_disc = kmemdup(info->acpi_disc, bytes, GFP_KERNEL);
+ if (!intel_vsec_dev->acpi_disc)
+ return -ENOMEM;
+ }
if (header->id == VSEC_ID_SDSI)
intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
@@ -349,7 +371,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
* Pass the ownership of intel_vsec_dev and resource within it to
* intel_vsec_add_aux()
*/
- return intel_vsec_add_aux(pdev, parent, no_free_ptr(intel_vsec_dev),
+ return intel_vsec_add_aux(parent, no_free_ptr(intel_vsec_dev),
intel_vsec_name(header->id));
}
@@ -410,12 +432,14 @@ static int get_cap_id(u32 header_id, unsigned long *cap_id)
return 0;
}
-static int intel_vsec_register_device(struct pci_dev *pdev,
+static int intel_vsec_register_device(struct device *dev,
struct intel_vsec_header *header,
- struct intel_vsec_platform_info *info)
+ const struct intel_vsec_platform_info *info,
+ u64 base_addr)
{
const struct vsec_feature_dependency *consumer_deps;
struct vsec_priv *priv;
+ struct pci_dev *pdev;
unsigned long cap_id;
int ret;
@@ -427,8 +451,12 @@ static int intel_vsec_register_device(struct pci_dev *pdev,
* Only track dependencies for devices probed by the VSEC driver.
* For others using the exported APIs, add the device directly.
*/
+ if (!dev_is_pci(dev))
+ return intel_vsec_add_dev(dev, header, info, cap_id, base_addr);
+
+ pdev = to_pci_dev(dev);
if (!pci_match_id(intel_vsec_pci_ids, pdev))
- return intel_vsec_add_dev(pdev, header, info, cap_id);
+ return intel_vsec_add_dev(dev, header, info, cap_id, base_addr);
priv = pci_get_drvdata(pdev);
if (priv->state[cap_id] == STATE_REGISTERED ||
@@ -444,7 +472,7 @@ static int intel_vsec_register_device(struct pci_dev *pdev,
consumer_deps = get_consumer_dependencies(priv, cap_id);
if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) {
- ret = intel_vsec_add_dev(pdev, header, info, cap_id);
+ ret = intel_vsec_add_dev(dev, header, info, cap_id, base_addr);
if (ret)
priv->state[cap_id] = STATE_SKIP;
else
@@ -456,24 +484,23 @@ static int intel_vsec_register_device(struct pci_dev *pdev,
return -EAGAIN;
}
-static bool intel_vsec_walk_header(struct pci_dev *pdev,
- struct intel_vsec_platform_info *info)
+static int intel_vsec_walk_header(struct device *dev,
+ const struct intel_vsec_platform_info *info)
{
struct intel_vsec_header **header = info->headers;
- bool have_devices = false;
int ret;
for ( ; *header; header++) {
- ret = intel_vsec_register_device(pdev, *header, info);
- if (!ret)
- have_devices = true;
+ ret = intel_vsec_register_device(dev, *header, info, info->base_addr);
+ if (ret)
+ return ret;
}
- return have_devices;
+ return 0;
}
static bool intel_vsec_walk_dvsec(struct pci_dev *pdev,
- struct intel_vsec_platform_info *info)
+ const struct intel_vsec_platform_info *info)
{
bool have_devices = false;
int pos = 0;
@@ -512,7 +539,8 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev,
pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr);
header.id = PCI_DVSEC_HEADER2_ID(hdr);
- ret = intel_vsec_register_device(pdev, &header, info);
+ ret = intel_vsec_register_device(&pdev->dev, &header, info,
+ pci_resource_start(pdev, header.tbir));
if (ret)
continue;
@@ -523,7 +551,7 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev,
}
static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
- struct intel_vsec_platform_info *info)
+ const struct intel_vsec_platform_info *info)
{
bool have_devices = false;
int pos = 0;
@@ -557,7 +585,8 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
header.tbir = INTEL_DVSEC_TABLE_BAR(table);
header.offset = INTEL_DVSEC_TABLE_OFFSET(table);
- ret = intel_vsec_register_device(pdev, &header, info);
+ ret = intel_vsec_register_device(&pdev->dev, &header, info,
+ pci_resource_start(pdev, header.tbir));
if (ret)
continue;
@@ -567,21 +596,18 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
return have_devices;
}
-int intel_vsec_register(struct pci_dev *pdev,
- struct intel_vsec_platform_info *info)
+int intel_vsec_register(struct device *dev,
+ const struct intel_vsec_platform_info *info)
{
- if (!pdev || !info || !info->headers)
+ if (!dev || !info || !info->headers)
return -EINVAL;
- if (!intel_vsec_walk_header(pdev, info))
- return -ENODEV;
- else
- return 0;
+ return intel_vsec_walk_header(dev, info);
}
EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC");
static bool intel_vsec_get_features(struct pci_dev *pdev,
- struct intel_vsec_platform_info *info)
+ const struct intel_vsec_platform_info *info)
{
bool found = false;
@@ -599,7 +625,7 @@ static bool intel_vsec_get_features(struct pci_dev *pdev,
found = true;
if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) &&
- intel_vsec_walk_header(pdev, info))
+ intel_vsec_walk_header(&pdev->dev, info))
found = true;
return found;
@@ -625,7 +651,7 @@ static void intel_vsec_skip_missing_dependencies(struct pci_dev *pdev)
static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct intel_vsec_platform_info *info;
+ const struct intel_vsec_platform_info *info;
struct vsec_priv *priv;
int num_caps, ret;
int run_once = 0;
@@ -636,7 +662,7 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
return ret;
pci_save_state(pdev);
- info = (struct intel_vsec_platform_info *)id->driver_data;
+ info = (const struct intel_vsec_platform_info *)id->driver_data;
if (!info)
return -EINVAL;
@@ -671,7 +697,10 @@ int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info,
{
struct vsec_priv *priv;
- priv = pci_get_drvdata(vsec_dev->pcidev);
+ if (!dev_is_pci(vsec_dev->dev))
+ return -ENODEV;
+
+ priv = pci_get_drvdata(to_pci_dev(vsec_dev->dev));
if (!priv)
return -EINVAL;
@@ -819,7 +848,7 @@ static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev)
xa_for_each(&auxdev_array, index, intel_vsec_dev) {
/* check if pdev doesn't match */
- if (pdev != intel_vsec_dev->pcidev)
+ if (&pdev->dev != intel_vsec_dev->dev)
continue;
devm_release_action(&pdev->dev, intel_vsec_remove_aux,
&intel_vsec_dev->auxdev);
diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c
index 98846e88d3d0..7fc6ff8d1040 100644
--- a/drivers/platform/x86/intel/vsec_tpmi.c
+++ b/drivers/platform/x86/intel/vsec_tpmi.c
@@ -46,6 +46,7 @@
* provided by the Intel VSEC driver.
*/
+#include <linux/align.h>
#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
@@ -479,6 +480,9 @@ static ssize_t mem_write(struct file *file, const char __user *userbuf, size_t l
addr = array[2];
value = array[3];
+ if (!IS_ALIGNED(addr, sizeof(u32)))
+ return -EINVAL;
+
if (punit >= pfs->pfs_header.num_entries) {
ret = -EINVAL;
goto exit_write;
@@ -530,7 +534,7 @@ static const struct file_operations mem_write_ops = {
.release = single_release,
};
-#define tpmi_to_dev(info) (&info->vsec_dev->pcidev->dev)
+#define tpmi_to_dev(info) ((info)->vsec_dev->dev)
static void tpmi_dbgfs_register(struct intel_tpmi_info *tpmi_info)
{
@@ -642,7 +646,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
tmp->flags = IORESOURCE_MEM;
}
- feature_vsec_dev->pcidev = vsec_dev->pcidev;
+ feature_vsec_dev->dev = vsec_dev->dev;
feature_vsec_dev->resource = res;
feature_vsec_dev->num_resources = pfs->pfs_header.num_entries;
feature_vsec_dev->priv_data = &tpmi_info->plat_info;
@@ -655,7 +659,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
* feature_vsec_dev and res memory are also freed as part of
* device deletion.
*/
- return intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
+ return intel_vsec_add_aux(&vsec_dev->auxdev.dev,
feature_vsec_dev, feature_id_name);
}
@@ -742,7 +746,7 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i
static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
{
struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
- struct pci_dev *pci_dev = vsec_dev->pcidev;
+ struct pci_dev *pci_dev = to_pci_dev(vsec_dev->dev);
struct intel_tpmi_info *tpmi_info;
u64 pfs_start = 0;
int ret, i;
diff --git a/drivers/platform/x86/intel/wmi/sbl-fw-update.c b/drivers/platform/x86/intel/wmi/sbl-fw-update.c
index 3716ccaaed6a..62c9c7f1842b 100644
--- a/drivers/platform/x86/intel/wmi/sbl-fw-update.c
+++ b/drivers/platform/x86/intel/wmi/sbl-fw-update.c
@@ -28,15 +28,10 @@ static int get_fwu_request(struct device *dev, u32 *out)
__le32 *result;
int ret;
- ret = wmidev_query_block(to_wmi_device(dev), 0, &buffer);
+ ret = wmidev_query_block(to_wmi_device(dev), 0, &buffer, sizeof(*result));
if (ret < 0)
return ret;
- if (buffer.length < sizeof(*result)) {
- kfree(buffer.data);
- return -ENODATA;
- }
-
result = buffer.data;
*out = le32_to_cpu(*result);
kfree(result);
diff --git a/drivers/platform/x86/intel/wmi/thunderbolt.c b/drivers/platform/x86/intel/wmi/thunderbolt.c
index 47017f2d7597..9b1920d61674 100644
--- a/drivers/platform/x86/intel/wmi/thunderbolt.c
+++ b/drivers/platform/x86/intel/wmi/thunderbolt.c
@@ -34,7 +34,7 @@ static ssize_t force_power_store(struct device *dev,
if (mode > 1)
return -EINVAL;
- ret = wmidev_invoke_method(to_wmi_device(dev), 0, 1, &buffer, NULL);
+ ret = wmidev_invoke_procedure(to_wmi_device(dev), 0, 1, &buffer);
if (ret < 0)
return ret;
diff --git a/drivers/platform/x86/lenovo/ideapad-laptop.c b/drivers/platform/x86/lenovo/ideapad-laptop.c
index ae1ebb071fab..4fbc904f1fc3 100644
--- a/drivers/platform/x86/lenovo/ideapad-laptop.c
+++ b/drivers/platform/x86/lenovo/ideapad-laptop.c
@@ -2340,6 +2340,7 @@ static struct wmi_driver ideapad_wmi_driver = {
.name = "ideapad_wmi",
},
.id_table = ideapad_wmi_ids,
+ .min_event_size = sizeof(u32),
.probe = ideapad_wmi_probe,
.notify = ideapad_wmi_notify,
};
diff --git a/drivers/platform/x86/lenovo/thinkpad_acpi.c b/drivers/platform/x86/lenovo/thinkpad_acpi.c
index 8982d92dfd97..e1cee42a1683 100644
--- a/drivers/platform/x86/lenovo/thinkpad_acpi.c
+++ b/drivers/platform/x86/lenovo/thinkpad_acpi.c
@@ -299,7 +299,6 @@ struct ibm_struct;
struct tp_acpi_drv_struct {
const struct acpi_device_id *hid;
- struct acpi_driver *driver;
void (*notify) (struct ibm_struct *, u32);
acpi_handle *handle;
@@ -322,7 +321,6 @@ struct ibm_struct {
struct tp_acpi_drv_struct *acpi;
struct {
- u8 acpi_driver_registered:1;
u8 acpi_notify_installed:1;
u8 proc_created:1;
u8 init_called:1;
@@ -374,7 +372,7 @@ static struct {
u32 hotkey_poll_active:1;
u32 has_adaptive_kbd:1;
u32 kbd_lang:1;
- u32 trackpoint_doubletap:1;
+ u32 trackpoint_doubletap_enable:1;
struct quirk_entry *quirks;
} tp_features;
@@ -832,9 +830,9 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
vdbg_printk(TPACPI_DBG_INIT,
"setting up ACPI notify for %s\n", ibm->name);
- ibm->acpi->device = acpi_fetch_acpi_dev(*ibm->acpi->handle);
+ ibm->acpi->device = acpi_get_acpi_dev(*ibm->acpi->handle);
if (!ibm->acpi->device) {
- pr_err("acpi_fetch_acpi_dev(%s) failed\n", ibm->name);
+ pr_err("acpi_get_acpi_dev(%s) failed\n", ibm->name);
return -ENODEV;
}
@@ -859,44 +857,6 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
return 0;
}
-static int __init tpacpi_device_add(struct acpi_device *device)
-{
- return 0;
-}
-
-static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
-{
- int rc;
-
- dbg_printk(TPACPI_DBG_INIT,
- "registering %s as an ACPI driver\n", ibm->name);
-
- BUG_ON(!ibm->acpi);
-
- ibm->acpi->driver = kzalloc_obj(struct acpi_driver);
- if (!ibm->acpi->driver) {
- pr_err("failed to allocate memory for ibm->acpi->driver\n");
- return -ENOMEM;
- }
-
- sprintf(ibm->acpi->driver->name, "%s_%s", TPACPI_NAME, ibm->name);
- ibm->acpi->driver->ids = ibm->acpi->hid;
-
- ibm->acpi->driver->ops.add = &tpacpi_device_add;
-
- rc = acpi_bus_register_driver(ibm->acpi->driver);
- if (rc < 0) {
- pr_err("acpi_bus_register_driver(%s) failed: %d\n",
- ibm->name, rc);
- kfree(ibm->acpi->driver);
- ibm->acpi->driver = NULL;
- } else if (!rc)
- ibm->flags.acpi_driver_registered = 1;
-
- return rc;
-}
-
-
/****************************************************************************
****************************************************************************
*
@@ -1315,7 +1275,7 @@ static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
{
if (id >= TPACPI_RFK_SW_MAX)
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
else {
int status;
@@ -1330,7 +1290,7 @@ static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *
}
seq_printf(m, "status:\t\t%s\n", str_enabled_disabled(status == TPACPI_RFK_RADIO_ON));
- seq_printf(m, "commands:\tenable, disable\n");
+ seq_puts(m, "commands:\tenable, disable\n");
}
return 0;
@@ -3019,6 +2979,31 @@ static const struct attribute_group adaptive_kbd_attr_group = {
.attrs = adaptive_kbd_attributes,
};
+/* sysfs doubletap enable --------------------------------------------- */
+static ssize_t doubletap_enable_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%d\n", tp_features.trackpoint_doubletap_enable);
+}
+
+static ssize_t doubletap_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool enable;
+ int err;
+
+ err = kstrtobool(buf, &enable);
+ if (err)
+ return err;
+
+ tp_features.trackpoint_doubletap_enable = enable;
+ return count;
+}
+
+static DEVICE_ATTR_RW(doubletap_enable);
+
/* --------------------------------------------------------------------- */
static struct attribute *hotkey_attributes[] = {
@@ -3033,6 +3018,7 @@ static struct attribute *hotkey_attributes[] = {
&dev_attr_hotkey_recommended_mask.attr,
&dev_attr_hotkey_tablet_mode.attr,
&dev_attr_hotkey_radio_sw.attr,
+ &dev_attr_doubletap_enable.attr,
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
&dev_attr_hotkey_source_mask.attr,
&dev_attr_hotkey_poll_freq.attr,
@@ -3558,8 +3544,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_poll_setup_safe(true);
- /* Enable doubletap by default */
- tp_features.trackpoint_doubletap = 1;
+ /* Enable TrackPoint doubletap event reporting by default. */
+ tp_features.trackpoint_doubletap_enable = 1;
return 0;
}
@@ -3864,9 +3850,9 @@ static bool hotkey_notify_8xxx(const u32 hkey, bool *send_acpi_ev)
{
switch (hkey) {
case TP_HKEY_EV_TRACK_DOUBLETAP:
- if (tp_features.trackpoint_doubletap)
- tpacpi_input_send_key(hkey, send_acpi_ev);
-
+ /* Only send event if doubletap is enabled */
+ if (!tp_features.trackpoint_doubletap_enable)
+ *send_acpi_ev = false;
return true;
default:
return false;
@@ -4017,7 +4003,7 @@ static int hotkey_read(struct seq_file *m)
int res, status;
if (!tp_features.hotkey) {
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
return 0;
}
@@ -4033,10 +4019,10 @@ static int hotkey_read(struct seq_file *m)
seq_printf(m, "status:\t\t%s\n", str_enabled_disabled(status & BIT(0)));
if (hotkey_all_mask) {
seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
- seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
+ seq_puts(m, "commands:\tenable, disable, reset, <mask>\n");
} else {
- seq_printf(m, "mask:\t\tnot supported\n");
- seq_printf(m, "commands:\tenable, disable, reset\n");
+ seq_puts(m, "mask:\t\tnot supported\n");
+ seq_puts(m, "commands:\tenable, disable, reset\n");
}
return 0;
@@ -4933,7 +4919,7 @@ static int video_read(struct seq_file *m)
int status, autosw;
if (video_supported == TPACPI_VIDEO_NONE) {
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
return 0;
}
@@ -4949,18 +4935,18 @@ static int video_read(struct seq_file *m)
if (autosw < 0)
return autosw;
- seq_printf(m, "status:\t\tsupported\n");
+ seq_puts(m, "status:\t\tsupported\n");
seq_printf(m, "lcd:\t\t%s\n", str_enabled_disabled(status & BIT(0)));
seq_printf(m, "crt:\t\t%s\n", str_enabled_disabled(status & BIT(1)));
if (video_supported == TPACPI_VIDEO_NEW)
seq_printf(m, "dvi:\t\t%s\n", str_enabled_disabled(status & BIT(3)));
seq_printf(m, "auto:\t\t%s\n", str_enabled_disabled(autosw & BIT(0)));
- seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
- seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
+ seq_puts(m, "commands:\tlcd_enable, lcd_disable\n");
+ seq_puts(m, "commands:\tcrt_enable, crt_disable\n");
if (video_supported == TPACPI_VIDEO_NEW)
- seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
- seq_printf(m, "commands:\tauto_enable, auto_disable\n");
- seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
+ seq_puts(m, "commands:\tdvi_enable, dvi_disable\n");
+ seq_puts(m, "commands:\tauto_enable, auto_disable\n");
+ seq_puts(m, "commands:\tvideo_switch, expand_toggle\n");
return 0;
}
@@ -5204,14 +5190,14 @@ static int kbdlight_read(struct seq_file *m)
int level;
if (!tp_features.kbdlight) {
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
} else {
level = kbdlight_get_level();
if (level < 0)
seq_printf(m, "status:\t\terror %d\n", level);
else
seq_printf(m, "status:\t\t%d\n", level);
- seq_printf(m, "commands:\t0, 1, 2\n");
+ seq_puts(m, "commands:\t0, 1, 2\n");
}
return 0;
@@ -5378,16 +5364,16 @@ static int light_read(struct seq_file *m)
int status;
if (!tp_features.light) {
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
} else if (!tp_features.light_status) {
- seq_printf(m, "status:\t\tunknown\n");
- seq_printf(m, "commands:\ton, off\n");
+ seq_puts(m, "status:\t\tunknown\n");
+ seq_puts(m, "commands:\ton, off\n");
} else {
status = light_get_status();
if (status < 0)
return status;
seq_printf(m, "status:\t\t%s\n", str_on_off(status & BIT(0)));
- seq_printf(m, "commands:\ton, off\n");
+ seq_puts(m, "commands:\ton, off\n");
}
return 0;
@@ -5477,10 +5463,10 @@ static int cmos_read(struct seq_file *m)
/* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
R30, R31, T20-22, X20-21 */
if (!cmos_handle)
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
else {
- seq_printf(m, "status:\t\tsupported\n");
- seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
+ seq_puts(m, "status:\t\tsupported\n");
+ seq_puts(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
}
return 0;
@@ -5846,10 +5832,10 @@ static int __init led_init(struct ibm_init_struct *iibm)
static int led_read(struct seq_file *m)
{
if (!led_supported) {
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
return 0;
}
- seq_printf(m, "status:\t\tsupported\n");
+ seq_puts(m, "status:\t\tsupported\n");
if (led_supported == TPACPI_LED_570) {
/* 570 */
@@ -5862,7 +5848,7 @@ static int led_read(struct seq_file *m)
}
}
- seq_printf(m, "commands:\t<led> on, <led> off, <led> blink (<led> is 0-15)\n");
+ seq_puts(m, "commands:\t<led> on, <led> off, <led> blink (<led> is 0-15)\n");
return 0;
}
@@ -5946,10 +5932,10 @@ static int __init beep_init(struct ibm_init_struct *iibm)
static int beep_read(struct seq_file *m)
{
if (!beep_handle)
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
else {
- seq_printf(m, "status:\t\tsupported\n");
- seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
+ seq_puts(m, "status:\t\tsupported\n");
+ seq_puts(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
}
return 0;
@@ -6398,14 +6384,14 @@ static int thermal_read(struct seq_file *m)
if (unlikely(n < 0))
return n;
- seq_printf(m, "temperatures:\t");
+ seq_puts(m, "temperatures:\t");
if (n > 0) {
for (i = 0; i < (n - 1); i++)
seq_printf(m, "%d ", t.temp[i] / 1000);
seq_printf(m, "%d\n", t.temp[i] / 1000);
} else
- seq_printf(m, "not supported\n");
+ seq_puts(m, "not supported\n");
return 0;
}
@@ -6918,10 +6904,10 @@ static int brightness_read(struct seq_file *m)
level = brightness_get(NULL);
if (level < 0) {
- seq_printf(m, "level:\t\tunreadable\n");
+ seq_puts(m, "level:\t\tunreadable\n");
} else {
seq_printf(m, "level:\t\t%d\n", level);
- seq_printf(m, "commands:\tup, down\n");
+ seq_puts(m, "commands:\tup, down\n");
seq_printf(m, "commands:\tlevel <level> (<level> is 0-%d)\n",
bright_maxlvl);
}
@@ -7637,10 +7623,10 @@ static int volume_read(struct seq_file *m)
u8 status;
if (volume_get_status(&status) < 0) {
- seq_printf(m, "level:\t\tunreadable\n");
+ seq_puts(m, "level:\t\tunreadable\n");
} else {
if (tp_features.mixer_no_level_control)
- seq_printf(m, "level:\t\tunsupported\n");
+ seq_puts(m, "level:\t\tunsupported\n");
else
seq_printf(m, "level:\t\t%d\n",
status & TP_EC_AUDIO_LVL_MSK);
@@ -7648,9 +7634,9 @@ static int volume_read(struct seq_file *m)
seq_printf(m, "mute:\t\t%s\n", str_on_off(status & BIT(TP_EC_AUDIO_MUTESW)));
if (volume_control_allowed) {
- seq_printf(m, "commands:\tunmute, mute\n");
+ seq_puts(m, "commands:\tunmute, mute\n");
if (!tp_features.mixer_no_level_control) {
- seq_printf(m, "commands:\tup, down\n");
+ seq_puts(m, "commands:\tup, down\n");
seq_printf(m, "commands:\tlevel <level> (<level> is 0-%d)\n",
TP_EC_VOLUME_MAX);
}
@@ -9156,9 +9142,9 @@ static int fan_read(struct seq_file *m)
} else if (fan_status_access_mode == TPACPI_FAN_RD_TPEC) {
if (status & TP_EC_FAN_FULLSPEED)
/* Disengaged mode takes precedence */
- seq_printf(m, "level:\t\tdisengaged\n");
+ seq_puts(m, "level:\t\tdisengaged\n");
else if (status & TP_EC_FAN_AUTO)
- seq_printf(m, "level:\t\tauto\n");
+ seq_puts(m, "level:\t\tauto\n");
else
seq_printf(m, "level:\t\t%d\n", status);
}
@@ -9166,19 +9152,19 @@ static int fan_read(struct seq_file *m)
case TPACPI_FAN_NONE:
default:
- seq_printf(m, "status:\t\tnot supported\n");
+ seq_puts(m, "status:\t\tnot supported\n");
}
if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
- seq_printf(m, "commands:\tlevel <level>");
+ seq_puts(m, "commands:\tlevel <level>");
switch (fan_control_access_mode) {
case TPACPI_FAN_WR_ACPI_SFAN:
- seq_printf(m, " (<level> is 0-7)\n");
+ seq_puts(m, " (<level> is 0-7)\n");
break;
default:
- seq_printf(m, " (<level> is 0-7, auto, disengaged, full-speed)\n");
+ seq_puts(m, " (<level> is 0-7, auto, disengaged, full-speed)\n");
break;
}
}
@@ -9188,7 +9174,7 @@ static int fan_read(struct seq_file *m)
"commands:\twatchdog <timeout> (<timeout> is 0 (off), 1-120 (seconds))\n");
if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
- seq_printf(m, "commands:\tspeed <speed> (<speed> is 0-65535)\n");
+ seq_puts(m, "commands:\tspeed <speed> (<speed> is 0-65535)\n");
return 0;
}
@@ -9249,9 +9235,6 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
{
int speed;
- /* TODO:
- * Support speed <low> <medium> <high> ? */
-
if (sscanf(cmd, "speed %d", &speed) != 1)
return 0;
@@ -11488,7 +11471,9 @@ static bool tpacpi_driver_event(const unsigned int hkey_event)
mutex_unlock(&tpacpi_inputdev_send_mutex);
return true;
case TP_HKEY_EV_DOUBLETAP_TOGGLE:
- tp_features.trackpoint_doubletap = !tp_features.trackpoint_doubletap;
+ /* Toggle kernel-level doubletap event filtering */
+ tp_features.trackpoint_doubletap_enable =
+ !tp_features.trackpoint_doubletap_enable;
return true;
case TP_HKEY_EV_PROFILE_TOGGLE:
case TP_HKEY_EV_PROFILE_TOGGLE2:
@@ -11532,6 +11517,8 @@ static void ibm_exit(struct ibm_struct *ibm)
acpi_remove_notify_handler(*ibm->acpi->handle,
ibm->acpi->type,
dispatch_acpi_notify);
+ ibm->acpi->device->driver_data = NULL;
+ acpi_dev_put(ibm->acpi->device);
ibm->flags.acpi_notify_installed = 0;
}
@@ -11542,16 +11529,6 @@ static void ibm_exit(struct ibm_struct *ibm)
ibm->flags.proc_created = 0;
}
- if (ibm->flags.acpi_driver_registered) {
- dbg_printk(TPACPI_DBG_EXIT,
- "%s: acpi_bus_unregister_driver\n", ibm->name);
- BUG_ON(!ibm->acpi);
- acpi_bus_unregister_driver(ibm->acpi->driver);
- kfree(ibm->acpi->driver);
- ibm->acpi->driver = NULL;
- ibm->flags.acpi_driver_registered = 0;
- }
-
if (ibm->flags.init_called && ibm->exit) {
ibm->exit();
ibm->flags.init_called = 0;
@@ -11587,12 +11564,6 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
}
if (ibm->acpi) {
- if (ibm->acpi->hid) {
- ret = register_tpacpi_subdriver(ibm);
- if (ret)
- goto err_out;
- }
-
if (ibm->acpi->notify) {
ret = setup_acpi_notify(ibm);
if (ret == -ENODEV) {
diff --git a/drivers/platform/x86/lenovo/wmi-camera.c b/drivers/platform/x86/lenovo/wmi-camera.c
index eb60fb9a5b3f..89ecbce60bf4 100644
--- a/drivers/platform/x86/lenovo/wmi-camera.c
+++ b/drivers/platform/x86/lenovo/wmi-camera.c
@@ -134,6 +134,7 @@ static struct wmi_driver lenovo_wmi_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = lenovo_wmi_id_table,
+ .min_event_size = sizeof(u8),
.no_singleton = true,
.probe = lenovo_wmi_probe,
.notify = lenovo_wmi_notify,
diff --git a/drivers/platform/x86/lenovo/wmi-events.c b/drivers/platform/x86/lenovo/wmi-events.c
index 0994cd7dd504..4a6a2c82413a 100644
--- a/drivers/platform/x86/lenovo/wmi-events.c
+++ b/drivers/platform/x86/lenovo/wmi-events.c
@@ -183,6 +183,7 @@ static struct wmi_driver lwmi_events_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = lwmi_events_id_table,
+ .min_event_size = sizeof(u32),
.probe = lwmi_events_probe,
.notify = lwmi_events_notify,
.no_singleton = true,
diff --git a/drivers/platform/x86/lenovo/ymc.c b/drivers/platform/x86/lenovo/ymc.c
index 470d53e3c9d2..1b73a55f1b89 100644
--- a/drivers/platform/x86/lenovo/ymc.c
+++ b/drivers/platform/x86/lenovo/ymc.c
@@ -153,6 +153,7 @@ static struct wmi_driver lenovo_ymc_driver = {
.name = "lenovo-ymc",
},
.id_table = lenovo_ymc_wmi_id_table,
+ .min_event_size = sizeof(u32),
.probe = lenovo_ymc_probe,
.notify = lenovo_ymc_notify,
};
diff --git a/drivers/platform/x86/lenovo/yogabook.c b/drivers/platform/x86/lenovo/yogabook.c
index 69887de36c9b..1a4b2ab1f35d 100644
--- a/drivers/platform/x86/lenovo/yogabook.c
+++ b/drivers/platform/x86/lenovo/yogabook.c
@@ -411,8 +411,8 @@ static struct wmi_driver yogabook_wmi_driver = {
.name = "yogabook-wmi",
.pm = pm_sleep_ptr(&yogabook_pm_ops),
},
- .no_notify_data = true,
.id_table = yogabook_wmi_id_table,
+ .min_event_size = 0,
.probe = yogabook_wmi_probe,
.remove = yogabook_wmi_remove,
.notify = yogabook_wmi_notify,
diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
index 61ef7a218a80..9681412d694b 100644
--- a/drivers/platform/x86/lg-laptop.c
+++ b/drivers/platform/x86/lg-laptop.c
@@ -271,11 +271,6 @@ static void wmi_input_setup(void)
}
}
-static void acpi_notify(struct acpi_device *device, u32 event)
-{
- acpi_handle_debug(device->handle, "notify: %d\n", event);
-}
-
static ssize_t fan_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buffer, size_t count)
@@ -764,8 +759,9 @@ static void lg_laptop_remove_address_space_handler(void *data)
&lg_laptop_address_space_handler);
}
-static int acpi_add(struct acpi_device *device)
+static int acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct platform_device_info pdev_info = {
.fwnode = acpi_fwnode_handle(device),
.name = PLATFORM_NAME,
@@ -781,11 +777,11 @@ static int acpi_add(struct acpi_device *device)
status = acpi_install_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID,
&lg_laptop_address_space_handler,
- NULL, &device->dev);
+ NULL, &pdev->dev);
if (ACPI_FAILURE(status))
return -ENODEV;
- ret = devm_add_action_or_reset(&device->dev, lg_laptop_remove_address_space_handler,
+ ret = devm_add_action_or_reset(&pdev->dev, lg_laptop_remove_address_space_handler,
device);
if (ret < 0)
return ret;
@@ -879,7 +875,7 @@ out_platform_registered:
return ret;
}
-static void acpi_remove(struct acpi_device *device)
+static void acpi_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group);
@@ -899,34 +895,13 @@ static const struct acpi_device_id device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, device_ids);
-static struct acpi_driver acpi_driver = {
- .name = "LG Gram Laptop Support",
- .class = "lg-laptop",
- .ids = device_ids,
- .ops = {
- .add = acpi_add,
- .remove = acpi_remove,
- .notify = acpi_notify,
- },
+static struct platform_driver acpi_driver = {
+ .probe = acpi_probe,
+ .remove = acpi_remove,
+ .driver = {
+ .name = "LG Gram Laptop Support",
+ .acpi_match_table = device_ids,
+ },
};
-static int __init acpi_init(void)
-{
- int result;
-
- result = acpi_bus_register_driver(&acpi_driver);
- if (result < 0) {
- pr_debug("Error registering driver\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit acpi_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_driver);
-}
-
-module_init(acpi_init);
-module_exit(acpi_exit);
+module_platform_driver(acpi_driver);
diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c
index 9a457956025a..dbc5e35ec38b 100644
--- a/drivers/platform/x86/mxm-wmi.c
+++ b/drivers/platform/x86/mxm-wmi.c
@@ -80,15 +80,3 @@ bool mxm_wmi_supported(void)
return guid_valid;
}
EXPORT_SYMBOL_GPL(mxm_wmi_supported);
-
-static int __init mxm_wmi_init(void)
-{
- return 0;
-}
-
-static void __exit mxm_wmi_exit(void)
-{
-}
-
-module_init(mxm_wmi_init);
-module_exit(mxm_wmi_exit);
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index d923ddaa4849..1337f7c49805 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -183,9 +183,9 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
};
/* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
-static int acpi_pcc_hotkey_add(struct acpi_device *device);
-static void acpi_pcc_hotkey_remove(struct acpi_device *device);
-static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
+static int acpi_pcc_hotkey_probe(struct platform_device *pdev);
+static void acpi_pcc_hotkey_remove(struct platform_device *pdev);
+static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data);
static const struct acpi_device_id pcc_device_ids[] = {
{ "MAT0012", 0},
@@ -201,16 +201,14 @@ static int acpi_pcc_hotkey_resume(struct device *dev);
#endif
static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
-static struct acpi_driver acpi_pcc_driver = {
- .name = ACPI_PCC_DRIVER_NAME,
- .class = ACPI_PCC_CLASS,
- .ids = pcc_device_ids,
- .ops = {
- .add = acpi_pcc_hotkey_add,
- .remove = acpi_pcc_hotkey_remove,
- .notify = acpi_pcc_hotkey_notify,
- },
- .drv.pm = &acpi_pcc_hotkey_pm,
+static struct platform_driver acpi_pcc_driver = {
+ .probe = acpi_pcc_hotkey_probe,
+ .remove = acpi_pcc_hotkey_remove,
+ .driver = {
+ .name = ACPI_PCC_DRIVER_NAME,
+ .acpi_match_table = pcc_device_ids,
+ .pm = &acpi_pcc_hotkey_pm,
+ },
};
static const struct key_entry panasonic_keymap[] = {
@@ -869,9 +867,9 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
pr_err("Unknown hotkey event: 0x%04llx\n", result);
}
-static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
+static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
{
- struct pcc_acpi *pcc = acpi_driver_data(device);
+ struct pcc_acpi *pcc = data;
switch (event) {
case HKEY_NOTIFY:
@@ -891,7 +889,7 @@ static void pcc_optd_notify(acpi_handle handle, u32 event, void *data)
set_optd_power_state(0);
}
-static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node)
+static void pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node)
{
acpi_status status;
acpi_handle handle;
@@ -904,10 +902,7 @@ static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node)
pcc_optd_notify, pcc);
if (ACPI_FAILURE(status))
pr_err("Failed to register notify on %s\n", node);
- } else
- return -ENODEV;
-
- return 0;
+ }
}
static void pcc_unregister_optd_notifier(struct pcc_acpi *pcc, char *node)
@@ -968,14 +963,7 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
#ifdef CONFIG_PM_SLEEP
static int acpi_pcc_hotkey_resume(struct device *dev)
{
- struct pcc_acpi *pcc;
-
- if (!dev)
- return -EINVAL;
-
- pcc = acpi_driver_data(to_acpi_device(dev));
- if (!pcc)
- return -EINVAL;
+ struct pcc_acpi *pcc = acpi_driver_data(ACPI_COMPANION(dev));
if (pcc->num_sifr > SINF_MUTE)
acpi_pcc_write_sset(pcc, SINF_MUTE, pcc->mute);
@@ -991,15 +979,13 @@ static int acpi_pcc_hotkey_resume(struct device *dev)
}
#endif
-static int acpi_pcc_hotkey_add(struct acpi_device *device)
+static int acpi_pcc_hotkey_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct backlight_properties props;
struct pcc_acpi *pcc;
int num_sifr, result;
- if (!device)
- return -EINVAL;
-
num_sifr = acpi_pcc_get_sqty(device);
/*
@@ -1083,19 +1069,25 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
if (result)
goto out_backlight;
+ result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify, pcc);
+ if (result)
+ goto out_sysfs;
+
/* optical drive initialization */
if (ACPI_SUCCESS(check_optd_present())) {
pcc->platform = platform_device_register_simple("panasonic",
PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(pcc->platform)) {
result = PTR_ERR(pcc->platform);
- goto out_sysfs;
+ goto out_notify_handler;
}
result = device_create_file(&pcc->platform->dev,
&dev_attr_cdpower);
- pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
if (result)
goto out_platform;
+
+ pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
} else {
pcc->platform = NULL;
}
@@ -1105,6 +1097,9 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
out_platform:
platform_device_unregister(pcc->platform);
+out_notify_handler:
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
out_sysfs:
sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
out_backlight:
@@ -1112,6 +1107,7 @@ out_backlight:
out_input:
input_unregister_device(pcc->input_dev);
out_sinf:
+ device->driver_data = NULL;
kfree(pcc->sinf);
out_hotkey:
kfree(pcc);
@@ -1119,20 +1115,21 @@ out_hotkey:
return result;
}
-static void acpi_pcc_hotkey_remove(struct acpi_device *device)
+static void acpi_pcc_hotkey_remove(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct pcc_acpi *pcc = acpi_driver_data(device);
- if (!device || !pcc)
- return;
-
i8042_remove_filter(panasonic_i8042_filter);
if (pcc->platform) {
+ pcc_unregister_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
platform_device_unregister(pcc->platform);
}
- pcc_unregister_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
+
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
@@ -1140,8 +1137,10 @@ static void acpi_pcc_hotkey_remove(struct acpi_device *device)
input_unregister_device(pcc->input_dev);
+ device->driver_data = NULL;
+
kfree(pcc->sinf);
kfree(pcc);
}
-module_acpi_driver(acpi_pcc_driver);
+module_platform_driver(acpi_pcc_driver);
diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c
index 3b086863c6ac..3f19589d1ba0 100644
--- a/drivers/platform/x86/pcengines-apuv2.c
+++ b/drivers/platform/x86/pcengines-apuv2.c
@@ -294,7 +294,8 @@ static int __init apu_board_init(void)
}
apu_gpio_pdev = apu_create_pdev(AMD_FCH_GPIO_DRIVER_NAME,
- id->driver_data, sizeof(struct amd_fch_gpio_pdata), NULL);
+ id->driver_data, sizeof(struct amd_fch_gpio_pdata),
+ &apu2_gpiochip_node);
err = PTR_ERR_OR_ZERO(apu_gpio_pdev);
if (err)
goto err_unregister_swnodes;
diff --git a/drivers/platform/x86/redmi-wmi.c b/drivers/platform/x86/redmi-wmi.c
index e5cb348e3a39..58898630eda6 100644
--- a/drivers/platform/x86/redmi-wmi.c
+++ b/drivers/platform/x86/redmi-wmi.c
@@ -141,6 +141,7 @@ static struct wmi_driver redmi_wmi_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = redmi_wmi_id_table,
+ .min_event_size = 32,
.probe = redmi_wmi_probe,
.notify = redmi_wmi_notify,
.no_singleton = true,
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index d3e7a52c22a7..b18f00e9082f 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -178,8 +178,7 @@ enum sony_nc_rfkill {
static int sony_rfkill_handle;
static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
-static int sony_nc_rfkill_setup(struct acpi_device *device,
- unsigned int handle);
+static int sony_nc_rfkill_setup(struct device *dev, unsigned int handle);
static void sony_nc_rfkill_cleanup(void);
static void sony_nc_rfkill_update(void);
@@ -435,7 +434,7 @@ static void sony_laptop_report_input_event(u8 event)
dprintk("unknown input event %.2x\n", event);
}
-static int sony_laptop_setup_input(struct acpi_device *acpi_device)
+static int sony_laptop_setup_input(struct device *parent)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
@@ -468,7 +467,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
key_dev->name = "Sony Vaio Keys";
key_dev->id.bustype = BUS_ISA;
key_dev->id.vendor = PCI_VENDOR_ID_SONY;
- key_dev->dev.parent = &acpi_device->dev;
+ key_dev->dev.parent = parent;
/* Initialize the Input Drivers: special keys */
input_set_capability(key_dev, EV_MSC, MSC_SCAN);
@@ -497,7 +496,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
jog_dev->name = "Sony Vaio Jogdial";
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
- jog_dev->dev.parent = &acpi_device->dev;
+ jog_dev->dev.parent = parent;
input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
input_set_capability(jog_dev, EV_REL, REL_WHEEL);
@@ -1176,7 +1175,7 @@ enum event_types {
KILLSWITCH,
GFX_SWITCH
};
-static void sony_nc_notify(struct acpi_device *device, u32 event)
+static void sony_nc_notify(acpi_handle ah, u32 event, void *data)
{
u32 real_ev = event;
u8 ev_type = 0;
@@ -1287,7 +1286,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
/*
* ACPI device
*/
-static void sony_nc_function_setup(struct acpi_device *device,
+static void sony_nc_function_setup(struct device *dev,
struct platform_device *pf_device)
{
unsigned int i, result, bitmask, arg;
@@ -1360,7 +1359,7 @@ static void sony_nc_function_setup(struct acpi_device *device,
break;
case 0x0124:
case 0x0135:
- result = sony_nc_rfkill_setup(device, handle);
+ result = sony_nc_rfkill_setup(dev, handle);
if (result)
pr_err("couldn't set up rfkill support (%d)\n",
result);
@@ -1600,8 +1599,7 @@ static const struct rfkill_ops sony_rfkill_ops = {
.set_block = sony_nc_rfkill_set,
};
-static int sony_nc_setup_rfkill(struct acpi_device *device,
- enum sony_nc_rfkill nc_type)
+static int sony_nc_setup_rfkill(struct device *parent, enum sony_nc_rfkill nc_type)
{
int err;
struct rfkill *rfk;
@@ -1631,8 +1629,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
return -EINVAL;
}
- rfk = rfkill_alloc(name, &device->dev, type,
- &sony_rfkill_ops, (void *)nc_type);
+ rfk = rfkill_alloc(name, parent, type, &sony_rfkill_ops, (void *)nc_type);
if (!rfk)
return -ENOMEM;
@@ -1692,8 +1689,7 @@ static void sony_nc_rfkill_update(void)
}
}
-static int sony_nc_rfkill_setup(struct acpi_device *device,
- unsigned int handle)
+static int sony_nc_rfkill_setup(struct device *parent, unsigned int handle)
{
u64 offset;
int i;
@@ -1734,18 +1730,18 @@ static int sony_nc_rfkill_setup(struct acpi_device *device,
dprintk("Radio devices, found 0x%.2x\n", buffer[i]);
if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI])
- sony_nc_setup_rfkill(device, SONY_WIFI);
+ sony_nc_setup_rfkill(parent, SONY_WIFI);
if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
- sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
+ sony_nc_setup_rfkill(parent, SONY_BLUETOOTH);
if (((0xf0 & buffer[i]) == 0x20 ||
(0xf0 & buffer[i]) == 0x50) &&
!sony_rfkill_devices[SONY_WWAN])
- sony_nc_setup_rfkill(device, SONY_WWAN);
+ sony_nc_setup_rfkill(parent, SONY_WWAN);
if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
- sony_nc_setup_rfkill(device, SONY_WIMAX);
+ sony_nc_setup_rfkill(parent, SONY_WIMAX);
}
return 0;
}
@@ -3149,8 +3145,9 @@ static void sony_nc_backlight_cleanup(void)
backlight_device_unregister(sony_bl_props.dev);
}
-static int sony_nc_add(struct acpi_device *device)
+static int sony_nc_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
acpi_status status;
int result = 0;
struct sony_nc_value *item;
@@ -3184,7 +3181,7 @@ static int sony_nc_add(struct acpi_device *device)
}
}
- result = sony_laptop_setup_input(device);
+ result = sony_laptop_setup_input(&pdev->dev);
if (result) {
pr_err("Unable to create input devices\n");
goto outplatform;
@@ -3201,7 +3198,7 @@ static int sony_nc_add(struct acpi_device *device)
/* retrieve the available handles */
result = sony_nc_handles_setup(sony_pf_device);
if (!result)
- sony_nc_function_setup(device, sony_pf_device);
+ sony_nc_function_setup(&pdev->dev, sony_pf_device);
}
if (acpi_video_get_backlight_type() == acpi_backlight_vendor)
@@ -3244,6 +3241,11 @@ static int sony_nc_add(struct acpi_device *device)
}
}
+ result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ sony_nc_notify, NULL);
+ if (result)
+ goto out_sysfs;
+
pr_info("SNC setup done.\n");
return 0;
@@ -3266,10 +3268,13 @@ outwalk:
return result;
}
-static void sony_nc_remove(struct acpi_device *device)
+static void sony_nc_remove(struct platform_device *pdev)
{
struct sony_nc_value *item;
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, sony_nc_notify);
+
sony_nc_backlight_cleanup();
sony_nc_acpi_device = NULL;
@@ -3297,16 +3302,14 @@ static const struct acpi_device_id sony_nc_device_ids[] = {
{"", 0},
};
-static struct acpi_driver sony_nc_driver = {
- .name = SONY_NC_DRIVER_NAME,
- .class = SONY_NC_CLASS,
- .ids = sony_nc_device_ids,
- .ops = {
- .add = sony_nc_add,
- .remove = sony_nc_remove,
- .notify = sony_nc_notify,
- },
- .drv.pm = &sony_nc_pm,
+static struct platform_driver sony_nc_driver = {
+ .probe = sony_nc_probe,
+ .remove = sony_nc_remove,
+ .driver = {
+ .name = SONY_NC_DRIVER_NAME,
+ .acpi_match_table = sony_nc_device_ids,
+ .pm = &sony_nc_pm,
+ },
};
/*********** SPIC (SNY6001) Device ***********/
@@ -4276,9 +4279,9 @@ end:
/*
* Disable the spic device by calling its _DIS method
*/
-static int sony_pic_disable(struct acpi_device *device)
+static int sony_pic_disable(struct device *dev)
{
- acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
+ acpi_status ret = acpi_evaluate_object(ACPI_HANDLE(dev), "_DIS", NULL,
NULL);
if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
@@ -4294,7 +4297,7 @@ static int sony_pic_disable(struct acpi_device *device)
*
* Call _SRS to set current resources
*/
-static int sony_pic_enable(struct acpi_device *device,
+static int sony_pic_enable(struct device *dev,
struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
{
acpi_status status;
@@ -4376,7 +4379,7 @@ static int sony_pic_enable(struct acpi_device *device,
/* Attempt to set the resource */
dprintk("Evaluating _SRS\n");
- status = acpi_set_current_resources(device->handle, &buffer);
+ status = acpi_set_current_resources(ACPI_HANDLE(dev), &buffer);
/* check for total failure */
if (ACPI_FAILURE(status)) {
@@ -4465,12 +4468,12 @@ found:
* ACPI driver
*
*****************/
-static void sony_pic_remove(struct acpi_device *device)
+static void sony_pic_remove(struct platform_device *pdev)
{
struct sony_pic_ioport *io, *tmp_io;
struct sony_pic_irq *irq, *tmp_irq;
- if (sony_pic_disable(device)) {
+ if (sony_pic_disable(&pdev->dev)) {
pr_err("Couldn't disable device\n");
return;
}
@@ -4504,11 +4507,12 @@ static void sony_pic_remove(struct acpi_device *device)
dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
}
-static int sony_pic_add(struct acpi_device *device)
+static int sony_pic_probe(struct platform_device *pdev)
{
- int result;
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct sony_pic_ioport *io, *tmp_io;
struct sony_pic_irq *irq, *tmp_irq;
+ int result;
spic_dev.acpi_dev = device;
strscpy(acpi_device_class(device), "sony/hotkey");
@@ -4523,7 +4527,7 @@ static int sony_pic_add(struct acpi_device *device)
}
/* setup input devices and helper fifo */
- result = sony_laptop_setup_input(device);
+ result = sony_laptop_setup_input(&pdev->dev);
if (result) {
pr_err("Unable to create input devices\n");
goto err_free_resources;
@@ -4593,7 +4597,7 @@ static int sony_pic_add(struct acpi_device *device)
}
/* set resource status _SRS */
- result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+ result = sony_pic_enable(&pdev->dev, spic_dev.cur_ioport, spic_dev.cur_irq);
if (result) {
pr_err("Couldn't enable device\n");
goto err_free_irq;
@@ -4616,7 +4620,7 @@ err_remove_pf:
sony_pf_remove();
err_disable_device:
- sony_pic_disable(device);
+ sony_pic_disable(&pdev->dev);
err_free_irq:
free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
@@ -4652,15 +4656,14 @@ err_free_resources:
#ifdef CONFIG_PM_SLEEP
static int sony_pic_suspend(struct device *dev)
{
- if (sony_pic_disable(to_acpi_device(dev)))
+ if (sony_pic_disable(dev))
return -ENXIO;
return 0;
}
static int sony_pic_resume(struct device *dev)
{
- sony_pic_enable(to_acpi_device(dev),
- spic_dev.cur_ioport, spic_dev.cur_irq);
+ sony_pic_enable(dev, spic_dev.cur_ioport, spic_dev.cur_irq);
return 0;
}
#endif
@@ -4672,15 +4675,14 @@ static const struct acpi_device_id sony_pic_device_ids[] = {
{"", 0},
};
-static struct acpi_driver sony_pic_driver = {
- .name = SONY_PIC_DRIVER_NAME,
- .class = SONY_PIC_CLASS,
- .ids = sony_pic_device_ids,
- .ops = {
- .add = sony_pic_add,
- .remove = sony_pic_remove,
- },
- .drv.pm = &sony_pic_pm,
+static struct platform_driver sony_pic_driver = {
+ .probe = sony_pic_probe,
+ .remove = sony_pic_remove,
+ .driver = {
+ .name = SONY_PIC_DRIVER_NAME,
+ .acpi_match_table = sony_pic_device_ids,
+ .pm = &sony_pic_pm,
+ },
};
static const struct dmi_system_id sonypi_dmi_table[] __initconst = {
@@ -4706,7 +4708,7 @@ static int __init sony_laptop_init(void)
int result;
if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
- result = acpi_bus_register_driver(&sony_pic_driver);
+ result = platform_driver_register(&sony_pic_driver);
if (result) {
pr_err("Unable to register SPIC driver\n");
goto out;
@@ -4714,7 +4716,7 @@ static int __init sony_laptop_init(void)
spic_drv_registered = 1;
}
- result = acpi_bus_register_driver(&sony_nc_driver);
+ result = platform_driver_register(&sony_nc_driver);
if (result) {
pr_err("Unable to register SNC driver\n");
goto out_unregister_pic;
@@ -4724,16 +4726,16 @@ static int __init sony_laptop_init(void)
out_unregister_pic:
if (spic_drv_registered)
- acpi_bus_unregister_driver(&sony_pic_driver);
+ platform_driver_unregister(&sony_pic_driver);
out:
return result;
}
static void __exit sony_laptop_exit(void)
{
- acpi_bus_unregister_driver(&sony_nc_driver);
+ platform_driver_unregister(&sony_nc_driver);
if (spic_drv_registered)
- acpi_bus_unregister_driver(&sony_pic_driver);
+ platform_driver_unregister(&sony_pic_driver);
}
module_init(sony_laptop_init);
diff --git a/drivers/platform/x86/system76_acpi.c b/drivers/platform/x86/system76_acpi.c
index 3da753b3d00d..693cbb461382 100644
--- a/drivers/platform/x86/system76_acpi.c
+++ b/drivers/platform/x86/system76_acpi.c
@@ -18,6 +18,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/sysfs.h>
#include <linux/types.h>
@@ -644,11 +645,10 @@ static void input_key(struct system76_data *data, unsigned int code)
}
// Handle ACPI notification
-static void system76_notify(struct acpi_device *acpi_dev, u32 event)
+static void system76_notify(acpi_handle handle, u32 event, void *context)
{
- struct system76_data *data;
+ struct system76_data *data = context;
- data = acpi_driver_data(acpi_dev);
switch (event) {
case 0x80:
kb_led_hotkey_hardware(data);
@@ -671,16 +671,19 @@ static void system76_notify(struct acpi_device *acpi_dev, u32 event)
}
}
-// Add a System76 ACPI device
-static int system76_add(struct acpi_device *acpi_dev)
+// Probe a System76 platform device
+static int system76_probe(struct platform_device *pdev)
{
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev);
struct system76_data *data;
int err;
- data = devm_kzalloc(&acpi_dev->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- acpi_dev->driver_data = data;
+
+ platform_set_drvdata(pdev, data);
+
data->acpi_dev = acpi_dev;
// Some models do not run open EC firmware. Check for an ACPI method
@@ -696,7 +699,7 @@ static int system76_add(struct acpi_device *acpi_dev)
data->ap_led.brightness_set_blocking = ap_led_set;
data->ap_led.max_brightness = 1;
data->ap_led.default_trigger = "rfkill-none";
- err = devm_led_classdev_register(&acpi_dev->dev, &data->ap_led);
+ err = devm_led_classdev_register(&pdev->dev, &data->ap_led);
if (err)
return err;
@@ -740,24 +743,29 @@ static int system76_add(struct acpi_device *acpi_dev)
}
if (data->kbled_type != KBLED_NONE) {
- err = devm_led_classdev_register(&acpi_dev->dev, &data->kb_led);
+ err = devm_led_classdev_register(&pdev->dev, &data->kb_led);
if (err)
return err;
}
- data->input = devm_input_allocate_device(&acpi_dev->dev);
+ data->input = devm_input_allocate_device(&pdev->dev);
if (!data->input)
return -ENOMEM;
data->input->name = "System76 ACPI Hotkeys";
data->input->phys = "system76_acpi/input0";
data->input->id.bustype = BUS_HOST;
- data->input->dev.parent = &acpi_dev->dev;
+ data->input->dev.parent = &pdev->dev;
input_set_capability(data->input, EV_KEY, KEY_SCREENLOCK);
err = input_register_device(data->input);
if (err)
- goto error;
+ return err;
+
+ err = acpi_dev_install_notify_handler(acpi_dev, ACPI_DEVICE_NOTIFY,
+ system76_notify, data);
+ if (err)
+ return err;
if (data->has_open_ec) {
err = system76_get_object(data, "NFAN", &data->nfan);
@@ -768,7 +776,7 @@ static int system76_add(struct acpi_device *acpi_dev)
if (err)
goto error;
- data->therm = devm_hwmon_device_register_with_info(&acpi_dev->dev,
+ data->therm = devm_hwmon_device_register_with_info(&pdev->dev,
"system76_acpi", data, &thermal_chip_info, NULL);
err = PTR_ERR_OR_ZERO(data->therm);
if (err)
@@ -784,15 +792,14 @@ error:
kfree(data->ntmp);
kfree(data->nfan);
}
+ acpi_dev_remove_notify_handler(acpi_dev, ACPI_DEVICE_NOTIFY, system76_notify);
return err;
}
-// Remove a System76 ACPI device
-static void system76_remove(struct acpi_device *acpi_dev)
+// Remove a System76 platform device
+static void system76_remove(struct platform_device *pdev)
{
- struct system76_data *data;
-
- data = acpi_driver_data(acpi_dev);
+ struct system76_data *data = platform_get_drvdata(pdev);
if (data->has_open_ec) {
system76_battery_exit();
@@ -800,23 +807,21 @@ static void system76_remove(struct acpi_device *acpi_dev)
kfree(data->ntmp);
}
- devm_led_classdev_unregister(&acpi_dev->dev, &data->ap_led);
- devm_led_classdev_unregister(&acpi_dev->dev, &data->kb_led);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, system76_notify);
system76_get(data, "FINI");
}
-static struct acpi_driver system76_driver = {
- .name = "System76 ACPI Driver",
- .class = "hotkey",
- .ids = device_ids,
- .ops = {
- .add = system76_add,
- .remove = system76_remove,
- .notify = system76_notify,
+static struct platform_driver system76_driver = {
+ .probe = system76_probe,
+ .remove = system76_remove,
+ .driver = {
+ .name = "System76 ACPI Driver",
+ .acpi_match_table = device_ids,
},
};
-module_acpi_driver(system76_driver);
+module_platform_driver(system76_driver);
MODULE_DESCRIPTION("System76 ACPI Driver");
MODULE_AUTHOR("Jeremy Soller <jeremy@system76.com>");
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index a7b4b6c8e549..e09d7f8ce45f 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -232,9 +232,9 @@ static int topstar_acpi_fncx_switch(struct acpi_device *device, bool state)
return 0;
}
-static void topstar_acpi_notify(struct acpi_device *device, u32 event)
+static void topstar_acpi_notify(acpi_handle handle, u32 event, void *data)
{
- struct topstar_laptop *topstar = acpi_driver_data(device);
+ struct topstar_laptop *topstar = data;
static bool dup_evnt[2];
bool *dup;
@@ -285,8 +285,9 @@ static const struct dmi_system_id topstar_dmi_ids[] = {
{}
};
-static int topstar_acpi_add(struct acpi_device *device)
+static int topstar_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct topstar_laptop *topstar;
int err;
@@ -296,9 +297,10 @@ static int topstar_acpi_add(struct acpi_device *device)
if (!topstar)
return -ENOMEM;
+ platform_set_drvdata(pdev, topstar);
+
strscpy(acpi_device_name(device), "Topstar TPSACPI");
strscpy(acpi_device_class(device), TOPSTAR_LAPTOP_CLASS);
- device->driver_data = topstar;
topstar->device = device;
err = topstar_acpi_init(topstar);
@@ -313,14 +315,21 @@ static int topstar_acpi_add(struct acpi_device *device)
if (err)
goto err_platform_exit;
+ err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ topstar_acpi_notify, topstar);
+ if (err)
+ goto err_input_exit;
+
if (led_workaround) {
err = topstar_led_init(topstar);
if (err)
- goto err_input_exit;
+ goto err_notify_handler_exit;
}
return 0;
+err_notify_handler_exit:
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, topstar_acpi_notify);
err_input_exit:
topstar_input_exit(topstar);
err_platform_exit:
@@ -332,13 +341,15 @@ err_free:
return err;
}
-static void topstar_acpi_remove(struct acpi_device *device)
+static void topstar_acpi_remove(struct platform_device *pdev)
{
- struct topstar_laptop *topstar = acpi_driver_data(device);
+ struct topstar_laptop *topstar = platform_get_drvdata(pdev);
if (led_workaround)
topstar_led_exit(topstar);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, topstar_acpi_notify);
topstar_input_exit(topstar);
topstar_platform_exit(topstar);
topstar_acpi_exit(topstar);
@@ -353,14 +364,12 @@ static const struct acpi_device_id topstar_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, topstar_device_ids);
-static struct acpi_driver topstar_acpi_driver = {
- .name = "Topstar laptop ACPI driver",
- .class = TOPSTAR_LAPTOP_CLASS,
- .ids = topstar_device_ids,
- .ops = {
- .add = topstar_acpi_add,
- .remove = topstar_acpi_remove,
- .notify = topstar_acpi_notify,
+static struct platform_driver topstar_acpi_driver = {
+ .probe = topstar_acpi_probe,
+ .remove = topstar_acpi_remove,
+ .driver = {
+ .name = "Topstar laptop ACPI driver",
+ .acpi_match_table = topstar_device_ids,
},
};
@@ -372,7 +381,7 @@ static int __init topstar_laptop_init(void)
if (ret < 0)
return ret;
- ret = acpi_bus_register_driver(&topstar_acpi_driver);
+ ret = platform_driver_register(&topstar_acpi_driver);
if (ret < 0)
goto err_driver_unreg;
@@ -386,7 +395,7 @@ err_driver_unreg:
static void __exit topstar_laptop_exit(void)
{
- acpi_bus_unregister_driver(&topstar_acpi_driver);
+ platform_driver_unregister(&topstar_acpi_driver);
platform_driver_unregister(&topstar_platform_driver);
}
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 18fb558115aa..35d899c01740 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -44,6 +44,7 @@
#include <linux/rfkill.h>
#include <linux/hwmon.h>
#include <linux/iio/iio.h>
+#include <linux/platform_device.h>
#include <linux/toshiba.h>
#include <acpi/battery.h>
#include <acpi/video.h>
@@ -223,6 +224,7 @@ struct toshiba_acpi_dev {
unsigned int cooling_method_supported:1;
unsigned int battery_charge_mode_supported:1;
unsigned int sysfs_created:1;
+ unsigned int notify_handler_installed:1;
unsigned int special_functions;
bool kbd_event_generated;
@@ -3193,14 +3195,80 @@ static void print_supported_features(struct toshiba_acpi_dev *dev)
pr_cont("\n");
}
-static void toshiba_acpi_remove(struct acpi_device *acpi_dev)
+static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *data)
{
- struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+ struct toshiba_acpi_dev *dev = data;
+ struct acpi_device *acpi_dev = dev->acpi_dev;
+
+ switch (event) {
+ case 0x80: /* Hotkeys and some system events */
+ /*
+ * Machines with this WMI GUID aren't supported due to bugs in
+ * their AML.
+ *
+ * Return silently to avoid triggering a netlink event.
+ */
+ if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+ return;
+ toshiba_acpi_process_hotkeys(dev);
+ break;
+ case 0x81: /* Dock events */
+ case 0x82:
+ case 0x83:
+ pr_info("Dock event received %x\n", event);
+ break;
+ case 0x88: /* Thermal events */
+ pr_info("Thermal event received\n");
+ break;
+ case 0x8f: /* LID closed */
+ case 0x90: /* LID is closed and Dock has been ejected */
+ break;
+ case 0x8c: /* SATA power events */
+ case 0x8b:
+ pr_info("SATA power event received %x\n", event);
+ break;
+ case 0x92: /* Keyboard backlight mode changed */
+ dev->kbd_event_generated = true;
+ /* Update sysfs entries */
+ if (sysfs_update_group(&acpi_dev->dev.kobj,
+ &toshiba_attr_group))
+ pr_err("Unable to update sysfs entries\n");
+ /* Notify LED subsystem about keyboard backlight change */
+ if (dev->kbd_type == 2 && dev->kbd_mode != SCI_KBD_MODE_AUTO)
+ led_classdev_notify_brightness_hw_changed(&dev->kbd_led,
+ (dev->kbd_mode == SCI_KBD_MODE_ON) ?
+ LED_FULL : LED_OFF);
+ break;
+ case 0x8e: /* Power button pressed */
+ break;
+ case 0x85: /* Unknown */
+ case 0x8d: /* Unknown */
+ case 0x94: /* Unknown */
+ case 0x95: /* Unknown */
+ default:
+ pr_info("Unknown event received %x\n", event);
+ break;
+ }
+
+ acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
+ dev_name(&acpi_dev->dev),
+ event, (event == 0x80) ?
+ dev->last_key_event : 0);
+}
+
+static void toshiba_acpi_remove(struct platform_device *pdev)
+{
+ struct toshiba_acpi_dev *dev = platform_get_drvdata(pdev);
misc_deregister(&dev->miscdev);
remove_toshiba_proc_entries(dev);
+ if (dev->notify_handler_installed)
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY,
+ toshiba_acpi_notify);
+
#if IS_ENABLED(CONFIG_HWMON)
if (dev->hwmon_device)
hwmon_device_unregister(dev->hwmon_device);
@@ -3240,6 +3308,8 @@ static void toshiba_acpi_remove(struct acpi_device *acpi_dev)
if (toshiba_acpi)
toshiba_acpi = NULL;
+ dev_set_drvdata(&dev->acpi_dev->dev, NULL);
+
kfree(dev);
}
@@ -3302,8 +3372,9 @@ static const struct dmi_system_id toshiba_dmi_quirks[] __initconst = {
{ }
};
-static int toshiba_acpi_add(struct acpi_device *acpi_dev)
+static int toshiba_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev);
struct toshiba_acpi_dev *dev;
const char *hci_method;
u32 dummy;
@@ -3337,7 +3408,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
return ret;
}
- acpi_dev->driver_data = dev;
+ platform_set_drvdata(pdev, dev);
dev_set_drvdata(&acpi_dev->dev, dev);
/* Query the BIOS for supported features */
@@ -3368,7 +3439,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->led_dev.max_brightness = 1;
dev->led_dev.brightness_set = toshiba_illumination_set;
dev->led_dev.brightness_get = toshiba_illumination_get;
- led_classdev_register(&acpi_dev->dev, &dev->led_dev);
+ led_classdev_register(&pdev->dev, &dev->led_dev);
}
toshiba_eco_mode_available(dev);
@@ -3377,7 +3448,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->eco_led.max_brightness = 1;
dev->eco_led.brightness_set = toshiba_eco_mode_set_status;
dev->eco_led.brightness_get = toshiba_eco_mode_get_status;
- led_classdev_register(&dev->acpi_dev->dev, &dev->eco_led);
+ led_classdev_register(&pdev->dev, &dev->eco_led);
}
toshiba_kbd_illum_available(dev);
@@ -3393,7 +3464,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->kbd_led.max_brightness = 1;
dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
- led_classdev_register(&dev->acpi_dev->dev, &dev->kbd_led);
+ led_classdev_register(&pdev->dev, &dev->kbd_led);
}
ret = toshiba_touchpad_get(dev, &dummy);
@@ -3401,7 +3472,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
toshiba_accelerometer_available(dev);
if (dev->accelerometer_supported) {
- dev->indio_dev = iio_device_alloc(&acpi_dev->dev, sizeof(*dev));
+ dev->indio_dev = iio_device_alloc(&pdev->dev, sizeof(*dev));
if (!dev->indio_dev) {
pr_err("Unable to allocate iio device\n");
goto iio_error;
@@ -3450,7 +3521,7 @@ iio_error:
#if IS_ENABLED(CONFIG_HWMON)
if (dev->fan_rpm_supported) {
dev->hwmon_device = hwmon_device_register_with_info(
- &dev->acpi_dev->dev, "toshiba_acpi_sensors", NULL,
+ &pdev->dev, "toshiba_acpi_sensors", NULL,
&toshiba_acpi_hwmon_chip_info, NULL);
if (IS_ERR(dev->hwmon_device)) {
dev->hwmon_device = NULL;
@@ -3477,6 +3548,13 @@ iio_error:
}
dev->sysfs_created = !ret;
+ ret = acpi_dev_install_notify_handler(acpi_dev, ACPI_DEVICE_NOTIFY,
+ toshiba_acpi_notify, dev);
+ if (ret)
+ goto error;
+
+ dev->notify_handler_installed = 1;
+
create_toshiba_proc_entries(dev);
toshiba_acpi = dev;
@@ -3491,74 +3569,14 @@ iio_error:
return 0;
error:
- toshiba_acpi_remove(acpi_dev);
+ toshiba_acpi_remove(pdev);
return ret;
}
-static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
-{
- struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
-
- switch (event) {
- case 0x80: /* Hotkeys and some system events */
- /*
- * Machines with this WMI GUID aren't supported due to bugs in
- * their AML.
- *
- * Return silently to avoid triggering a netlink event.
- */
- if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
- return;
- toshiba_acpi_process_hotkeys(dev);
- break;
- case 0x81: /* Dock events */
- case 0x82:
- case 0x83:
- pr_info("Dock event received %x\n", event);
- break;
- case 0x88: /* Thermal events */
- pr_info("Thermal event received\n");
- break;
- case 0x8f: /* LID closed */
- case 0x90: /* LID is closed and Dock has been ejected */
- break;
- case 0x8c: /* SATA power events */
- case 0x8b:
- pr_info("SATA power event received %x\n", event);
- break;
- case 0x92: /* Keyboard backlight mode changed */
- dev->kbd_event_generated = true;
- /* Update sysfs entries */
- if (sysfs_update_group(&acpi_dev->dev.kobj,
- &toshiba_attr_group))
- pr_err("Unable to update sysfs entries\n");
- /* Notify LED subsystem about keyboard backlight change */
- if (dev->kbd_type == 2 && dev->kbd_mode != SCI_KBD_MODE_AUTO)
- led_classdev_notify_brightness_hw_changed(&dev->kbd_led,
- (dev->kbd_mode == SCI_KBD_MODE_ON) ?
- LED_FULL : LED_OFF);
- break;
- case 0x8e: /* Power button pressed */
- break;
- case 0x85: /* Unknown */
- case 0x8d: /* Unknown */
- case 0x94: /* Unknown */
- case 0x95: /* Unknown */
- default:
- pr_info("Unknown event received %x\n", event);
- break;
- }
-
- acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
- dev_name(&acpi_dev->dev),
- event, (event == 0x80) ?
- dev->last_key_event : 0);
-}
-
#ifdef CONFIG_PM_SLEEP
static int toshiba_acpi_suspend(struct device *device)
{
- struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
+ struct toshiba_acpi_dev *dev = dev_get_drvdata(device);
if (dev->hotkey_dev) {
u32 result;
@@ -3573,7 +3591,7 @@ static int toshiba_acpi_suspend(struct device *device)
static int toshiba_acpi_resume(struct device *device)
{
- struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
+ struct toshiba_acpi_dev *dev = dev_get_drvdata(device);
if (dev->hotkey_dev) {
if (toshiba_acpi_enable_hotkeys(dev))
@@ -3595,16 +3613,14 @@ static int toshiba_acpi_resume(struct device *device)
static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,
toshiba_acpi_suspend, toshiba_acpi_resume);
-static struct acpi_driver toshiba_acpi_driver = {
- .name = "Toshiba ACPI driver",
- .ids = toshiba_device_ids,
- .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
- .ops = {
- .add = toshiba_acpi_add,
- .remove = toshiba_acpi_remove,
- .notify = toshiba_acpi_notify,
+static struct platform_driver toshiba_acpi_driver = {
+ .probe = toshiba_acpi_probe,
+ .remove = toshiba_acpi_remove,
+ .driver = {
+ .name = "Toshiba ACPI driver",
+ .acpi_match_table = toshiba_device_ids,
+ .pm = &toshiba_acpi_pm,
},
- .drv.pm = &toshiba_acpi_pm,
};
static void __init toshiba_dmi_init(void)
@@ -3634,7 +3650,7 @@ static int __init toshiba_acpi_init(void)
return -ENODEV;
}
- ret = acpi_bus_register_driver(&toshiba_acpi_driver);
+ ret = platform_driver_register(&toshiba_acpi_driver);
if (ret) {
pr_err("Failed to register ACPI driver: %d\n", ret);
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
@@ -3645,7 +3661,7 @@ static int __init toshiba_acpi_init(void)
static void __exit toshiba_acpi_exit(void)
{
- acpi_bus_unregister_driver(&toshiba_acpi_driver);
+ platform_driver_unregister(&toshiba_acpi_driver);
if (toshiba_proc_dir)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c
index e587beef05b9..e50d4fc1e603 100644
--- a/drivers/platform/x86/toshiba_bluetooth.c
+++ b/drivers/platform/x86/toshiba_bluetooth.c
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/rfkill.h>
+#include <linux/platform_device.h>
#define BT_KILLSWITCH_MASK 0x01
#define BT_PLUGGED_MASK 0x40
@@ -35,9 +36,9 @@ struct toshiba_bluetooth_dev {
bool powered;
};
-static int toshiba_bt_rfkill_add(struct acpi_device *device);
-static void toshiba_bt_rfkill_remove(struct acpi_device *device);
-static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
+static int toshiba_bt_rfkill_probe(struct platform_device *pdev);
+static void toshiba_bt_rfkill_remove(struct platform_device *pdev);
+static void toshiba_bt_rfkill_notify(acpi_handle handle, u32 event, void *data);
static const struct acpi_device_id bt_device_ids[] = {
{ "TOS6205", 0},
@@ -50,16 +51,14 @@ static int toshiba_bt_resume(struct device *dev);
#endif
static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
-static struct acpi_driver toshiba_bt_rfkill_driver = {
- .name = "Toshiba BT",
- .class = "Toshiba",
- .ids = bt_device_ids,
- .ops = {
- .add = toshiba_bt_rfkill_add,
- .remove = toshiba_bt_rfkill_remove,
- .notify = toshiba_bt_rfkill_notify,
- },
- .drv.pm = &toshiba_bt_pm,
+static struct platform_driver toshiba_bt_rfkill_driver = {
+ .probe = toshiba_bt_rfkill_probe,
+ .remove = toshiba_bt_rfkill_remove,
+ .driver = {
+ .name = "Toshiba BT",
+ .acpi_match_table = bt_device_ids,
+ .pm = &toshiba_bt_pm,
+ },
};
static int toshiba_bluetooth_present(acpi_handle handle)
@@ -203,9 +202,9 @@ static const struct rfkill_ops rfk_ops = {
};
/* ACPI driver functions */
-static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
+static void toshiba_bt_rfkill_notify(acpi_handle handle, u32 event, void *data)
{
- struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
+ struct toshiba_bluetooth_dev *bt_dev = data;
if (toshiba_bluetooth_sync_status(bt_dev))
return;
@@ -216,11 +215,9 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
#ifdef CONFIG_PM_SLEEP
static int toshiba_bt_resume(struct device *dev)
{
- struct toshiba_bluetooth_dev *bt_dev;
+ struct toshiba_bluetooth_dev *bt_dev = dev_get_drvdata(dev);
int ret;
- bt_dev = acpi_driver_data(to_acpi_device(dev));
-
ret = toshiba_bluetooth_sync_status(bt_dev);
if (ret)
return ret;
@@ -231,8 +228,9 @@ static int toshiba_bt_resume(struct device *dev)
}
#endif
-static int toshiba_bt_rfkill_add(struct acpi_device *device)
+static int toshiba_bt_rfkill_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct toshiba_bluetooth_dev *bt_dev;
int result;
@@ -246,8 +244,8 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
if (!bt_dev)
return -ENOMEM;
bt_dev->acpi_dev = device;
- device->driver_data = bt_dev;
- dev_set_drvdata(&device->dev, bt_dev);
+
+ platform_set_drvdata(pdev, bt_dev);
result = toshiba_bluetooth_sync_status(bt_dev);
if (result) {
@@ -256,14 +254,14 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
}
bt_dev->rfk = rfkill_alloc("Toshiba Bluetooth",
- &device->dev,
+ &pdev->dev,
RFKILL_TYPE_BLUETOOTH,
&rfk_ops,
bt_dev);
if (!bt_dev->rfk) {
pr_err("Unable to allocate rfkill device\n");
- kfree(bt_dev);
- return -ENOMEM;
+ result = -ENOMEM;
+ goto err_free_bt_dev;
}
rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
@@ -271,18 +269,36 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
result = rfkill_register(bt_dev->rfk);
if (result) {
pr_err("Unable to register rfkill device\n");
- rfkill_destroy(bt_dev->rfk);
- kfree(bt_dev);
+ goto err_rfkill_destroy;
}
+ result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ toshiba_bt_rfkill_notify, bt_dev);
+ if (result) {
+ pr_err("Unable to register ACPI notify handler\n");
+ goto err_rfkill_unregister;
+ }
+
+ return 0;
+
+err_rfkill_unregister:
+ rfkill_unregister(bt_dev->rfk);
+err_rfkill_destroy:
+ rfkill_destroy(bt_dev->rfk);
+err_free_bt_dev:
+ kfree(bt_dev);
return result;
}
-static void toshiba_bt_rfkill_remove(struct acpi_device *device)
+static void toshiba_bt_rfkill_remove(struct platform_device *pdev)
{
- struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
+ struct toshiba_bluetooth_dev *bt_dev = platform_get_drvdata(pdev);
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
/* clean up */
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ toshiba_bt_rfkill_notify);
+
if (bt_dev->rfk) {
rfkill_unregister(bt_dev->rfk);
rfkill_destroy(bt_dev->rfk);
@@ -293,4 +309,4 @@ static void toshiba_bt_rfkill_remove(struct acpi_device *device)
toshiba_bluetooth_disable(device->handle);
}
-module_acpi_driver(toshiba_bt_rfkill_driver);
+module_platform_driver(toshiba_bt_rfkill_driver);
diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c
index e9324bf16aea..1486252b5983 100644
--- a/drivers/platform/x86/toshiba_haps.c
+++ b/drivers/platform/x86/toshiba_haps.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/acpi.h>
+#include <linux/platform_device.h>
MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>");
MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor");
@@ -129,8 +130,10 @@ static const struct attribute_group haps_attr_group = {
/*
* ACPI stuff
*/
-static void toshiba_haps_notify(struct acpi_device *device, u32 event)
+static void toshiba_haps_notify(acpi_handle handle, u32 event, void *data)
{
+ struct acpi_device *device = data;
+
pr_debug("Received event: 0x%x\n", event);
acpi_bus_generate_netlink_event(device->pnp.device_class,
@@ -138,12 +141,19 @@ static void toshiba_haps_notify(struct acpi_device *device, u32 event)
event, 0);
}
-static void toshiba_haps_remove(struct acpi_device *device)
+static void toshiba_haps_remove(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+
+ acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ toshiba_haps_notify);
+
sysfs_remove_group(&device->dev.kobj, &haps_attr_group);
if (toshiba_haps)
toshiba_haps = NULL;
+
+ dev_set_drvdata(&device->dev, NULL);
}
/* Helper function */
@@ -170,8 +180,9 @@ static int toshiba_haps_available(acpi_handle handle)
return 1;
}
-static int toshiba_haps_add(struct acpi_device *acpi_dev)
+static int toshiba_haps_probe(struct platform_device *pdev)
{
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev);
struct toshiba_haps_dev *haps;
int ret;
@@ -183,14 +194,15 @@ static int toshiba_haps_add(struct acpi_device *acpi_dev)
pr_info("Toshiba HDD Active Protection Sensor device\n");
- haps = devm_kzalloc(&acpi_dev->dev, sizeof(*haps), GFP_KERNEL);
+ haps = devm_kzalloc(&pdev->dev, sizeof(*haps), GFP_KERNEL);
if (!haps)
return -ENOMEM;
haps->acpi_dev = acpi_dev;
haps->protection_level = 2;
- acpi_dev->driver_data = haps;
+
dev_set_drvdata(&acpi_dev->dev, haps);
+ platform_set_drvdata(pdev, haps);
/* Set the protection level, currently at level 2 (Medium) */
ret = toshiba_haps_protection_level(acpi_dev->handle, 2);
@@ -201,19 +213,26 @@ static int toshiba_haps_add(struct acpi_device *acpi_dev)
if (ret)
return ret;
+ ret = acpi_dev_install_notify_handler(acpi_dev, ACPI_DEVICE_NOTIFY,
+ toshiba_haps_notify, acpi_dev);
+ if (ret)
+ goto err;
+
toshiba_haps = haps;
return 0;
+
+err:
+ sysfs_remove_group(&acpi_dev->dev.kobj, &haps_attr_group);
+ return ret;
}
#ifdef CONFIG_PM_SLEEP
static int toshiba_haps_suspend(struct device *device)
{
- struct toshiba_haps_dev *haps;
+ struct toshiba_haps_dev *haps = dev_get_drvdata(device);
int ret;
- haps = acpi_driver_data(to_acpi_device(device));
-
/* Deactivate the protection on suspend */
ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0);
@@ -222,11 +241,9 @@ static int toshiba_haps_suspend(struct device *device)
static int toshiba_haps_resume(struct device *device)
{
- struct toshiba_haps_dev *haps;
+ struct toshiba_haps_dev *haps = dev_get_drvdata(device);
int ret;
- haps = acpi_driver_data(to_acpi_device(device));
-
/* Set the stored protection level */
ret = toshiba_haps_protection_level(haps->acpi_dev->handle,
haps->protection_level);
@@ -249,16 +266,14 @@ static const struct acpi_device_id haps_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, haps_device_ids);
-static struct acpi_driver toshiba_haps_driver = {
- .name = "Toshiba HAPS",
- .ids = haps_device_ids,
- .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
- .ops = {
- .add = toshiba_haps_add,
- .remove = toshiba_haps_remove,
- .notify = toshiba_haps_notify,
+static struct platform_driver toshiba_haps_driver = {
+ .probe = toshiba_haps_probe,
+ .remove = toshiba_haps_remove,
+ .driver = {
+ .name = "Toshiba HAPS",
+ .acpi_match_table = haps_device_ids,
+ .pm = &toshiba_haps_pm,
},
- .drv.pm = &toshiba_haps_pm,
};
-module_acpi_driver(toshiba_haps_driver);
+module_platform_driver(toshiba_haps_driver);
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index 6341dca20b76..945df5092637 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -110,6 +110,8 @@
#define EC_ADDR_BAT_CYCLE_COUNT_2 0x04A7
#define EC_ADDR_PROJECT_ID 0x0740
+#define PROJECT_ID_PH4TRX1 0x12
+#define PROJECT_ID_PH6TRX1 0x15
#define EC_ADDR_AP_OEM 0x0741
#define ENABLE_MANUAL_CTRL BIT(0)
@@ -266,8 +268,8 @@
#define BATTERY_CHARGE_FULL_OVER_24H BIT(3)
#define BATTERY_ERM_STATUS_REACHED BIT(4)
-#define EC_ADDR_CHARGE_PRIO 0x07CC
-#define CHARGING_PERFORMANCE BIT(7)
+#define EC_ADDR_USB_C_POWER_PRIORITY 0x07CC
+#define USB_C_POWER_PRIORITY BIT(7)
/* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
#define EC_ADDR_LIGHTBAR_BAT_CTRL 0x07E2
@@ -319,8 +321,17 @@
#define UNIWILL_FEATURE_TOUCHPAD_TOGGLE BIT(2)
#define UNIWILL_FEATURE_LIGHTBAR BIT(3)
#define UNIWILL_FEATURE_BATTERY BIT(4)
-#define UNIWILL_FEATURE_HWMON BIT(5)
-#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL BIT(6)
+#define UNIWILL_FEATURE_CPU_TEMP BIT(5)
+#define UNIWILL_FEATURE_GPU_TEMP BIT(6)
+#define UNIWILL_FEATURE_PRIMARY_FAN BIT(7)
+#define UNIWILL_FEATURE_SECONDARY_FAN BIT(8)
+#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL BIT(9)
+#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY BIT(10)
+
+enum usb_c_power_priority_options {
+ USB_C_POWER_PRIORITY_CHARGING = 0,
+ USB_C_POWER_PRIORITY_PERFORMANCE,
+};
struct uniwill_data {
struct device *dev;
@@ -340,6 +351,8 @@ struct uniwill_data {
struct mutex input_lock; /* Protects input sequence during notify */
struct input_dev *input_device;
struct notifier_block nb;
+ struct mutex usb_c_power_priority_lock; /* Protects dependent bit write and state safe */
+ enum usb_c_power_priority_options last_usb_c_power_priority_option;
};
struct uniwill_battery_entry {
@@ -427,7 +440,7 @@ static const struct key_entry uniwill_keymap[] = {
{ KE_END }
};
-static inline bool uniwill_device_supports(struct uniwill_data *data,
+static inline bool uniwill_device_supports(const struct uniwill_data *data,
unsigned int features)
{
return (data->features & features) == features;
@@ -524,6 +537,7 @@ static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
case EC_ADDR_CTGP_DB_CTGP_OFFSET:
case EC_ADDR_CTGP_DB_TPP_OFFSET:
case EC_ADDR_CTGP_DB_DB_OFFSET:
+ case EC_ADDR_USB_C_POWER_PRIORITY:
return true;
default:
return false;
@@ -562,6 +576,7 @@ static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
case EC_ADDR_CTGP_DB_CTGP_OFFSET:
case EC_ADDR_CTGP_DB_TPP_OFFSET:
case EC_ADDR_CTGP_DB_DB_OFFSET:
+ case EC_ADDR_USB_C_POWER_PRIORITY:
return true;
default:
return false;
@@ -584,6 +599,7 @@ static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
case EC_ADDR_TRIGGER:
case EC_ADDR_SWITCH_STATUS:
case EC_ADDR_CHARGE_CTRL:
+ case EC_ADDR_USB_C_POWER_PRIORITY:
return true;
default:
return false;
@@ -880,6 +896,105 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
return 0;
}
+static const char * const usb_c_power_priority_text[] = {
+ [USB_C_POWER_PRIORITY_CHARGING] = "charging",
+ [USB_C_POWER_PRIORITY_PERFORMANCE] = "performance",
+};
+
+static const u8 usb_c_power_priority_value[] = {
+ [USB_C_POWER_PRIORITY_CHARGING] = 0,
+ [USB_C_POWER_PRIORITY_PERFORMANCE] = USB_C_POWER_PRIORITY,
+};
+
+static ssize_t usb_c_power_priority_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct uniwill_data *data = dev_get_drvdata(dev);
+ enum usb_c_power_priority_options option;
+ unsigned int value;
+ int ret;
+
+ ret = sysfs_match_string(usb_c_power_priority_text, buf);
+ if (ret < 0)
+ return ret;
+
+ option = ret;
+ value = usb_c_power_priority_value[option];
+
+ guard(mutex)(&data->usb_c_power_priority_lock);
+
+ ret = regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
+ USB_C_POWER_PRIORITY, value);
+ if (ret < 0)
+ return ret;
+
+ data->last_usb_c_power_priority_option = option;
+
+ return count;
+}
+
+static ssize_t usb_c_power_priority_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct uniwill_data *data = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
+ if (ret < 0)
+ return ret;
+
+ value &= USB_C_POWER_PRIORITY;
+
+ if (usb_c_power_priority_value[USB_C_POWER_PRIORITY_PERFORMANCE] == value)
+ return sysfs_emit(buf, "%s\n",
+ usb_c_power_priority_text[USB_C_POWER_PRIORITY_PERFORMANCE]);
+
+ return sysfs_emit(buf, "%s\n", usb_c_power_priority_text[USB_C_POWER_PRIORITY_CHARGING]);
+}
+
+static DEVICE_ATTR_RW(usb_c_power_priority);
+
+static int usb_c_power_priority_restore(struct uniwill_data *data)
+{
+ unsigned int value;
+
+ value = usb_c_power_priority_value[data->last_usb_c_power_priority_option];
+
+ guard(mutex)(&data->usb_c_power_priority_lock);
+
+ return regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
+ USB_C_POWER_PRIORITY, value);
+}
+
+static int usb_c_power_priority_init(struct uniwill_data *data)
+{
+ unsigned int value;
+ int ret;
+
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+ return 0;
+
+ ret = devm_mutex_init(data->dev, &data->usb_c_power_priority_lock);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
+ if (ret < 0)
+ return ret;
+
+ value &= USB_C_POWER_PRIORITY;
+
+ data->last_usb_c_power_priority_option =
+ usb_c_power_priority_value[USB_C_POWER_PRIORITY_PERFORMANCE] == value ?
+ USB_C_POWER_PRIORITY_PERFORMANCE :
+ USB_C_POWER_PRIORITY_CHARGING;
+
+ return 0;
+}
+
static struct attribute *uniwill_attrs[] = {
/* Keyboard-related */
&dev_attr_fn_lock.attr,
@@ -890,6 +1005,7 @@ static struct attribute *uniwill_attrs[] = {
&dev_attr_breathing_in_suspend.attr,
/* Power-management-related */
&dev_attr_ctgp_offset.attr,
+ &dev_attr_usb_c_power_priority.attr,
NULL
};
@@ -924,6 +1040,11 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
return attr->mode;
}
+ if (attr == &dev_attr_usb_c_power_priority.attr) {
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+ return attr->mode;
+ }
+
return 0;
}
@@ -937,6 +1058,48 @@ static const struct attribute_group *uniwill_groups[] = {
NULL
};
+static umode_t uniwill_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ const struct uniwill_data *data = drvdata;
+ unsigned int feature;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (channel) {
+ case 0:
+ feature = UNIWILL_FEATURE_CPU_TEMP;
+ break;
+ case 1:
+ feature = UNIWILL_FEATURE_GPU_TEMP;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case hwmon_fan:
+ case hwmon_pwm:
+ switch (channel) {
+ case 0:
+ feature = UNIWILL_FEATURE_PRIMARY_FAN;
+ break;
+ case 1:
+ feature = UNIWILL_FEATURE_SECONDARY_FAN;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ if (uniwill_device_supports(data, feature))
+ return 0444;
+
+ return 0;
+}
+
static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
long *val)
{
@@ -1020,7 +1183,7 @@ static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type,
}
static const struct hwmon_ops uniwill_ops = {
- .visible = 0444,
+ .is_visible = uniwill_is_visible,
.read = uniwill_read,
.read_string = uniwill_read_string,
};
@@ -1048,7 +1211,10 @@ static int uniwill_hwmon_init(struct uniwill_data *data)
{
struct device *hdev;
- if (!uniwill_device_supports(data, UNIWILL_FEATURE_HWMON))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_CPU_TEMP) &&
+ !uniwill_device_supports(data, UNIWILL_FEATURE_GPU_TEMP) &&
+ !uniwill_device_supports(data, UNIWILL_FEATURE_PRIMARY_FAN) &&
+ !uniwill_device_supports(data, UNIWILL_FEATURE_SECONDARY_FAN))
return 0;
hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
@@ -1369,11 +1535,10 @@ static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action
return NOTIFY_OK;
case UNIWILL_OSD_DC_ADAPTER_CHANGED:
- /* noop for the time being, will change once charging priority
- * gets implemented.
- */
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+ return NOTIFY_DONE;
- return NOTIFY_OK;
+ return notifier_from_errno(usb_c_power_priority_restore(data));
case UNIWILL_OSD_FN_LOCK:
if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
return NOTIFY_DONE;
@@ -1467,6 +1632,7 @@ static int uniwill_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
data->regmap = regmap;
+
ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
if (ret < 0)
return ret;
@@ -1504,6 +1670,10 @@ static int uniwill_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ ret = usb_c_power_priority_init(data);
+ if (ret < 0)
+ return ret;
+
return uniwill_input_init(data);
}
@@ -1633,6 +1803,14 @@ static int uniwill_resume_nvidia_ctgp(struct uniwill_data *data)
CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
}
+static int uniwill_resume_usb_c_power_priority(struct uniwill_data *data)
+{
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
+ return 0;
+
+ return usb_c_power_priority_restore(data);
+}
+
static int uniwill_resume(struct device *dev)
{
struct uniwill_data *data = dev_get_drvdata(dev);
@@ -1656,7 +1834,11 @@ static int uniwill_resume(struct device *dev)
if (ret < 0)
return ret;
- return uniwill_resume_nvidia_ctgp(data);
+ ret = uniwill_resume_nvidia_ctgp(data);
+ if (ret < 0)
+ return ret;
+
+ return uniwill_resume_usb_c_power_priority(data);
}
static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume);
@@ -1682,12 +1864,24 @@ static struct platform_driver uniwill_driver = {
.shutdown = uniwill_shutdown,
};
+static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_BATTERY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN,
+};
+
static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
.features = UNIWILL_FEATURE_FN_LOCK |
UNIWILL_FEATURE_SUPER_KEY |
UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON,
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN,
};
static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
@@ -1696,7 +1890,89 @@ static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
UNIWILL_FEATURE_LIGHTBAR |
UNIWILL_FEATURE_BATTERY |
- UNIWILL_FEATURE_HWMON,
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN,
+};
+
+/*
+ * The featuresets below reflect somewhat chronological changes:
+ * 1 -> 2: UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL is added to the EC firmware.
+ * 2 -> 3: UNIWILL_FEATURE_USB_C_POWER_PRIORITY is removed from the EC firmware.
+ * Some devices might divert from this timeline.
+ */
+
+static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN |
+ UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_1_nvidia_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN |
+ UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_2_nvidia_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN |
+ UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
+ UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+};
+
+static struct uniwill_device_descriptor tux_featureset_3_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN,
+};
+
+static struct uniwill_device_descriptor tux_featureset_3_nvidia_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN |
+ UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+};
+
+static int phxtxx1_probe(struct uniwill_data *data)
+{
+ unsigned int value;
+ int ret;
+
+ ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
+ if (ret < 0)
+ return ret;
+
+ if (value == PROJECT_ID_PH4TRX1 || value == PROJECT_ID_PH6TRX1)
+ data->features |= UNIWILL_FEATURE_SECONDARY_FAN;
+
+ return 0;
+};
+
+static struct uniwill_device_descriptor phxtxx1_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
+ .probe = phxtxx1_probe,
};
static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
@@ -1709,37 +1985,61 @@ static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
return ret;
if (value & HAS_GPU)
- data->features |= UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
+ data->features |= UNIWILL_FEATURE_GPU_TEMP |
+ UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
return 0;
};
static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN |
+ UNIWILL_FEATURE_SECONDARY_FAN |
+ UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
.probe = phxarx1_phxaqf1_probe,
};
-static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
- .features = UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
+static struct uniwill_device_descriptor pf5pu1g_descriptor __initdata = {
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
+ UNIWILL_FEATURE_CPU_TEMP |
+ UNIWILL_FEATURE_PRIMARY_FAN,
};
-static struct uniwill_device_descriptor empty_descriptor __initdata = {};
-
static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
{
- .ident = "XMG FUSION 15",
+ .ident = "XMG FUSION 15 (L19)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &lapqc71a_lapqc71b_descriptor,
},
{
- .ident = "XMG FUSION 15",
+ .ident = "XMG FUSION 15 (L19)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &lapqc71a_lapqc71b_descriptor,
+ },
+ {
+ .ident = "XMG FUSION 15 (L19)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
+ },
+ .driver_data = &lapqc71a_lapqc71b_descriptor,
+ },
+ {
+ .ident = "XMG FUSION 15 (L19)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
+ },
+ .driver_data = &lapqc71a_lapqc71b_descriptor,
},
{
.ident = "Intel NUC x15",
@@ -1763,7 +2063,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &phxtxx1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
@@ -1771,7 +2071,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
@@ -1787,7 +2087,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1795,7 +2095,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
@@ -1803,7 +2103,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
@@ -1811,7 +2111,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
@@ -1819,7 +2119,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
@@ -1827,7 +2127,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1835,7 +2135,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
@@ -1843,7 +2143,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_descriptor,
},
{
.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
@@ -1851,7 +2151,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_descriptor,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
@@ -1859,7 +2159,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1867,7 +2167,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
@@ -1875,7 +2175,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
@@ -1883,7 +2183,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
@@ -1891,7 +2191,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1899,7 +2199,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15 Gen1 AMD",
@@ -1907,7 +2207,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1915,7 +2215,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 17 Gen1 AMD",
@@ -1923,7 +2223,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1931,7 +2231,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15 Gen1 Intel",
@@ -1939,7 +2239,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1947,7 +2247,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 17 Gen1 Intel",
@@ -1955,7 +2255,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Trinity 15 Intel Gen1",
@@ -1963,7 +2263,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Trinity 17 Intel Gen1",
@@ -1971,7 +2271,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
@@ -1979,7 +2279,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
@@ -1987,7 +2287,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
@@ -1995,7 +2295,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
@@ -2003,7 +2303,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
@@ -2011,7 +2311,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 15 Gen4 Intel",
@@ -2019,7 +2319,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
@@ -2027,7 +2327,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_2_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen5 AMD",
@@ -2035,7 +2335,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
@@ -2043,7 +2343,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
@@ -2051,7 +2351,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
@@ -2059,7 +2359,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -2067,7 +2367,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
@@ -2075,7 +2375,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
@@ -2083,7 +2383,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 AMD",
@@ -2091,7 +2391,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -2099,7 +2399,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Stellaris 16 Gen7 Intel",
@@ -2107,7 +2407,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
},
- .driver_data = &tux_featureset_1_descriptor,
+ .driver_data = &tux_featureset_3_nvidia_descriptor,
},
{
.ident = "TUXEDO Book BA15 Gen10 AMD",
@@ -2115,7 +2415,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &pf5pu1g_descriptor,
},
{
.ident = "TUXEDO Pulse 14 Gen1 AMD",
@@ -2123,7 +2423,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Pulse 15 Gen1 AMD",
@@ -2131,7 +2431,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{
.ident = "TUXEDO Pulse 15 Gen2 AMD",
@@ -2139,7 +2439,7 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
},
- .driver_data = &empty_descriptor,
+ .driver_data = &tux_featureset_1_descriptor,
},
{ }
};
diff --git a/drivers/platform/x86/uniwill/uniwill-wmi.c b/drivers/platform/x86/uniwill/uniwill-wmi.c
index 31d9c39f14ab..097882f10b1e 100644
--- a/drivers/platform/x86/uniwill/uniwill-wmi.c
+++ b/drivers/platform/x86/uniwill/uniwill-wmi.c
@@ -77,6 +77,7 @@ static struct wmi_driver uniwill_wmi_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = uniwill_wmi_id_table,
+ .min_event_size = sizeof(u32),
.notify = uniwill_wmi_notify,
.no_singleton = true,
};
diff --git a/drivers/platform/x86/wireless-hotkey.c b/drivers/platform/x86/wireless-hotkey.c
index e5083c0e1515..f680d8ff8e87 100644
--- a/drivers/platform/x86/wireless-hotkey.c
+++ b/drivers/platform/x86/wireless-hotkey.c
@@ -35,16 +35,17 @@ static const struct acpi_device_id wl_ids[] = {
{"", 0},
};
-static int wireless_input_setup(struct acpi_device *device)
+static int wireless_input_setup(struct device *dev)
{
- struct wl_button *button = acpi_driver_data(device);
+ struct wl_button *button = dev_get_drvdata(dev);
int err;
button->input_dev = input_allocate_device();
if (!button->input_dev)
return -ENOMEM;
- snprintf(button->phys, sizeof(button->phys), "%s/input0", acpi_device_hid(device));
+ snprintf(button->phys, sizeof(button->phys), "%s/input0",
+ acpi_device_hid(ACPI_COMPANION(dev)));
button->input_dev->name = "Wireless hotkeys";
button->input_dev->phys = button->phys;
@@ -63,17 +64,17 @@ err_free_dev:
return err;
}
-static void wireless_input_destroy(struct acpi_device *device)
+static void wireless_input_destroy(struct device *dev)
{
- struct wl_button *button = acpi_driver_data(device);
+ struct wl_button *button = dev_get_drvdata(dev);
input_unregister_device(button->input_dev);
kfree(button);
}
-static void wl_notify(struct acpi_device *acpi_dev, u32 event)
+static void wl_notify(acpi_handle handle, u32 event, void *data)
{
- struct wl_button *button = acpi_driver_data(acpi_dev);
+ struct wl_button *button = data;
if (event != 0x80) {
pr_info("Received unknown event (0x%x)\n", event);
@@ -86,7 +87,7 @@ static void wl_notify(struct acpi_device *acpi_dev, u32 event)
input_sync(button->input_dev);
}
-static int wl_add(struct acpi_device *device)
+static int wl_probe(struct platform_device *pdev)
{
struct wl_button *button;
int err;
@@ -95,30 +96,38 @@ static int wl_add(struct acpi_device *device)
if (!button)
return -ENOMEM;
- device->driver_data = button;
+ platform_set_drvdata(pdev, button);
- err = wireless_input_setup(device);
+ err = wireless_input_setup(&pdev->dev);
if (err) {
pr_err("Failed to setup wireless hotkeys\n");
kfree(button);
+ return err;
+ }
+ err = acpi_dev_install_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, wl_notify, button);
+ if (err) {
+ pr_err("Failed to install ACPI notify handler\n");
+ wireless_input_destroy(&pdev->dev);
}
return err;
}
-static void wl_remove(struct acpi_device *device)
+static void wl_remove(struct platform_device *pdev)
{
- wireless_input_destroy(device);
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, wl_notify);
+ wireless_input_destroy(&pdev->dev);
}
-static struct acpi_driver wl_driver = {
- .name = "wireless-hotkey",
- .ids = wl_ids,
- .ops = {
- .add = wl_add,
- .remove = wl_remove,
- .notify = wl_notify,
+static struct platform_driver wl_driver = {
+ .probe = wl_probe,
+ .remove = wl_remove,
+ .driver = {
+ .name = "wireless-hotkey",
+ .acpi_match_table = wl_ids,
},
};
-module_acpi_driver(wl_driver);
+module_platform_driver(wl_driver);
diff --git a/drivers/platform/x86/wmi-bmof.c b/drivers/platform/x86/wmi-bmof.c
index e3a126de421b..6623cf60e4b4 100644
--- a/drivers/platform/x86/wmi-bmof.c
+++ b/drivers/platform/x86/wmi-bmof.c
@@ -62,7 +62,7 @@ static int wmi_bmof_probe(struct wmi_device *wdev, const void *context)
if (!buffer)
return -ENOMEM;
- ret = wmidev_query_block(wdev, 0, buffer);
+ ret = wmidev_query_block(wdev, 0, buffer, 0);
if (ret < 0)
return ret;
diff --git a/drivers/platform/x86/xiaomi-wmi.c b/drivers/platform/x86/xiaomi-wmi.c
index badf9e42e015..3874f3336a0d 100644
--- a/drivers/platform/x86/xiaomi-wmi.c
+++ b/drivers/platform/x86/xiaomi-wmi.c
@@ -83,6 +83,7 @@ static struct wmi_driver xiaomi_wmi_driver = {
.name = "xiaomi-wmi",
},
.id_table = xiaomi_wmi_id_table,
+ .min_event_size = 0,
.probe = xiaomi_wmi_probe,
.notify_new = xiaomi_wmi_notify,
.no_singleton = true,