aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-17 17:05:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-17 17:05:21 -0700
commita5cb6b2bbff9cdd32aab635ad464a1ee299a63bd (patch)
tree67803af2631c8e015db8f466e906ff04617ec6dd /drivers
parente2f710f97f3544df08ebe608c8157536e0ffb494 (diff)
parentd8b17a364ec48239fccb65efe74bb485e79e6743 (diff)
Merge tag 'platform-drivers-x86-v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Ilpo Järvinen: - amd/pmf: Report system state changes using existing input events - asus-wmi: Zenbook 2023 camera LED disable support and fix TUF laptop keyboard RGB LED sysfs interface - dell-pc: Fan modes / platform profile support - hp-wmi: Fix platform profile switching on Omen/Victus laptops - intel/ISST: Use only TPMI interface when TPMI and legacy interfaces are available - intel/pmc: LTR restore support to pair with LTR ignore - intel/tpmi: Performance Limit Reasons (PLR) and APIC <-> Punit CPU numbering mapping support - WMI: driver override support and docs improvements - lenovo-yoga-c630: Support for EC (platform/arm64) - platform/arm64: Fix build with COMPILE_TEST (broke after addition of C630) - tools: Intel Speed Select Turbo Ratio Limit fix - Miscellaneous cleanups / refactoring / improvements * tag 'platform-drivers-x86-v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (65 commits) platform/x86: asus-wmi: fix TUF laptop RGB variant platform/x86/intel/tpmi/plr: Fix output in plr_print_bits() Docs/admin-guide: Remove pmf leftover reference from the index platform/x86: ideapad-laptop: use cleanup.h platform/x86: hp-wmi: Fix implementation of the platform_profile_omen_get function platform: arm64: EC_LENOVO_YOGA_C630 should depend on ARCH_QCOM platform: arm64: EC_ACER_ASPIRE1 should depend on ARCH_QCOM platform/x86/amd/pmf: Remove update system state document platform/x86/amd/pmf: Use existing input event codes to update system states platform/x86: hp-wmi: Fix platform profile option switch bug on Omen and Victus laptops platform/x86:intel/pmc: Add support to undo ltr_ignore platform/x86:intel/pmc: Use the Elvis operator platform/x86:intel/pmc: Use DEFINE_SHOW_STORE_ATTRIBUTE macro platform/x86:intel/pmc: Remove unneeded min_t check platform/x86:intel/pmc: Add support to show ltr_ignore value platform/x86:intel/pmc: Move pmc assignment closer to first usage platform/x86:intel/pmc: Convert index variables to be unsigned platform/x86:intel/pmc: Simplify mutex usage with cleanup helpers platform/x86:intel/pmc: Use the return value of pmc_core_send_msg tools/power/x86/intel-speed-select: v1.20 release ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/Makefile2
-rw-r--r--drivers/platform/arm64/Kconfig17
-rw-r--r--drivers/platform/arm64/Makefile1
-rw-r--r--drivers/platform/arm64/lenovo-yoga-c630.c291
-rw-r--r--drivers/platform/x86/amd/pmf/pmf.h2
-rw-r--r--drivers/platform/x86/amd/pmf/tee-if.c73
-rw-r--r--drivers/platform/x86/asus-tf103c-dock.c10
-rw-r--r--drivers/platform/x86/asus-wmi.c41
-rw-r--r--drivers/platform/x86/dell/Kconfig13
-rw-r--r--drivers/platform/x86/dell/Makefile1
-rw-r--r--drivers/platform/x86/dell/dell-laptop.c23
-rw-r--r--drivers/platform/x86/dell/dell-pc.c309
-rw-r--r--drivers/platform/x86/dell/dell-smbios-base.c35
-rw-r--r--drivers/platform/x86/dell/dell-smbios.h7
-rw-r--r--drivers/platform/x86/hp/Kconfig1
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c18
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/int-attributes.c7
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c18
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c19
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/spmobj-attributes.c3
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/string-attributes.c12
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c188
-rw-r--r--drivers/platform/x86/ideapad-laptop.c71
-rw-r--r--drivers/platform/x86/intel/Kconfig11
-rw-r--r--drivers/platform/x86/intel/Makefile4
-rw-r--r--drivers/platform/x86/intel/chtwc_int33fe.c6
-rw-r--r--drivers/platform/x86/intel/ifs/core.c15
-rw-r--r--drivers/platform/x86/intel/intel_plr_tpmi.c354
-rw-r--r--drivers/platform/x86/intel/pmc/core.c262
-rw-r--r--drivers/platform/x86/intel/pmc/pltdrv.c16
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.c75
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.h3
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c4
-rw-r--r--drivers/platform/x86/intel/telemetry/debugfs.c4
-rw-r--r--drivers/platform/x86/intel/telemetry/pltdrv.c4
-rw-r--r--drivers/platform/x86/intel/tpmi.c11
-rw-r--r--drivers/platform/x86/intel/tpmi_power_domains.c235
-rw-r--r--drivers/platform/x86/intel/tpmi_power_domains.h18
-rw-r--r--drivers/platform/x86/intel/turbo_max_3.c4
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c83
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h13
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c101
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c108
-rw-r--r--drivers/platform/x86/intel_ips.c3
-rw-r--r--drivers/platform/x86/intel_scu_wdt.c2
-rw-r--r--drivers/platform/x86/p2sb.c2
-rw-r--r--drivers/platform/x86/serial-multi-instantiate.c4
-rw-r--r--drivers/platform/x86/think-lmi.c4
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c6
-rw-r--r--drivers/platform/x86/wmi.c33
50 files changed, 2055 insertions, 492 deletions
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index bf69cc8d7429..19ac54648586 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -12,4 +12,4 @@ obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
-obj-$(CONFIG_ARM64) += arm64/
+obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/
diff --git a/drivers/platform/arm64/Kconfig b/drivers/platform/arm64/Kconfig
index 8fdca0f8e909..f88395ea3376 100644
--- a/drivers/platform/arm64/Kconfig
+++ b/drivers/platform/arm64/Kconfig
@@ -18,6 +18,7 @@ if ARM64_PLATFORM_DEVICES
config EC_ACER_ASPIRE1
tristate "Acer Aspire 1 Embedded Controller driver"
+ depends on ARCH_QCOM || COMPILE_TEST
depends on I2C
depends on DRM
depends on POWER_SUPPLY
@@ -32,4 +33,20 @@ config EC_ACER_ASPIRE1
laptop where this information is not properly exposed via the
standard ACPI devices.
+config EC_LENOVO_YOGA_C630
+ tristate "Lenovo Yoga C630 Embedded Controller driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on I2C
+ select AUXILIARY_BUS
+ help
+ Driver for the Embedded Controller in the Qualcomm Snapdragon-based
+ Lenovo Yoga C630, which provides battery and power adapter
+ information.
+
+ This driver provides battery and AC status support for the mentioned
+ laptop where this information is not properly exposed via the
+ standard ACPI devices.
+
+ Say M or Y here to include this support.
+
endif # ARM64_PLATFORM_DEVICES
diff --git a/drivers/platform/arm64/Makefile b/drivers/platform/arm64/Makefile
index 4fcc9855579b..b2ae9114fdd8 100644
--- a/drivers/platform/arm64/Makefile
+++ b/drivers/platform/arm64/Makefile
@@ -6,3 +6,4 @@
#
obj-$(CONFIG_EC_ACER_ASPIRE1) += acer-aspire1-ec.o
+obj-$(CONFIG_EC_LENOVO_YOGA_C630) += lenovo-yoga-c630.o
diff --git a/drivers/platform/arm64/lenovo-yoga-c630.c b/drivers/platform/arm64/lenovo-yoga-c630.c
new file mode 100644
index 000000000000..1f05c9a6a89d
--- /dev/null
+++ b/drivers/platform/arm64/lenovo-yoga-c630.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2024, Linaro Ltd
+ * Authors:
+ * Bjorn Andersson
+ * Dmitry Baryshkov
+ */
+#include <linux/auxiliary_bus.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/irqreturn.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+#include <linux/platform_data/lenovo-yoga-c630.h>
+
+#define LENOVO_EC_RESPONSE_REG 0x01
+#define LENOVO_EC_REQUEST_REG 0x02
+
+#define LENOVO_EC_UCSI_WRITE 0x20
+#define LENOVO_EC_UCSI_READ 0x21
+
+#define LENOVO_EC_READ_REG 0xb0
+#define LENOVO_EC_REQUEST_NEXT_EVENT 0x84
+
+#define LENOVO_EC_UCSI_VERSION 0x20
+
+struct yoga_c630_ec {
+ struct i2c_client *client;
+ struct mutex lock;
+ struct blocking_notifier_head notifier_list;
+};
+
+static int yoga_c630_ec_request(struct yoga_c630_ec *ec, u8 *req, size_t req_len,
+ u8 *resp, size_t resp_len)
+{
+ int ret;
+
+ lockdep_assert_held(&ec->lock);
+
+ ret = i2c_smbus_write_i2c_block_data(ec->client, LENOVO_EC_REQUEST_REG,
+ req_len, req);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_read_i2c_block_data(ec->client, LENOVO_EC_RESPONSE_REG,
+ resp_len, resp);
+}
+
+int yoga_c630_ec_read8(struct yoga_c630_ec *ec, u8 addr)
+{
+ u8 req[2] = { LENOVO_EC_READ_REG, };
+ int ret;
+ u8 val;
+
+ guard(mutex)(&ec->lock);
+
+ req[1] = addr;
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &val, 1);
+ if (ret < 0)
+ return ret;
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_read8);
+
+int yoga_c630_ec_read16(struct yoga_c630_ec *ec, u8 addr)
+{
+ u8 req[2] = { LENOVO_EC_READ_REG, };
+ int ret;
+ u8 msb;
+ u8 lsb;
+
+ /* don't overflow the address */
+ if (addr == 0xff)
+ return -EINVAL;
+
+ guard(mutex)(&ec->lock);
+
+ req[1] = addr;
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &lsb, 1);
+ if (ret < 0)
+ return ret;
+
+ req[1] = addr + 1;
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &msb, 1);
+ if (ret < 0)
+ return ret;
+
+ return msb << 8 | lsb;
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_read16);
+
+u16 yoga_c630_ec_ucsi_get_version(struct yoga_c630_ec *ec)
+{
+ u8 req[3] = { 0xb3, 0xf2, };
+ int ret;
+ u8 msb;
+ u8 lsb;
+
+ guard(mutex)(&ec->lock);
+
+ req[2] = LENOVO_EC_UCSI_VERSION;
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &lsb, 1);
+ if (ret < 0)
+ return ret;
+
+ req[2] = LENOVO_EC_UCSI_VERSION + 1;
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &msb, 1);
+ if (ret < 0)
+ return ret;
+
+ return msb << 8 | lsb;
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_get_version);
+
+int yoga_c630_ec_ucsi_write(struct yoga_c630_ec *ec,
+ const u8 req[YOGA_C630_UCSI_WRITE_SIZE])
+{
+ int ret;
+
+ mutex_lock(&ec->lock);
+ ret = i2c_smbus_write_i2c_block_data(ec->client, LENOVO_EC_UCSI_WRITE,
+ YOGA_C630_UCSI_WRITE_SIZE, req);
+ mutex_unlock(&ec->lock);
+
+ return ret < 0 ? ret : 0;
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_write);
+
+int yoga_c630_ec_ucsi_read(struct yoga_c630_ec *ec,
+ u8 resp[YOGA_C630_UCSI_READ_SIZE])
+{
+ int ret;
+
+ mutex_lock(&ec->lock);
+ ret = i2c_smbus_read_i2c_block_data(ec->client, LENOVO_EC_UCSI_READ,
+ YOGA_C630_UCSI_READ_SIZE, resp);
+ mutex_unlock(&ec->lock);
+
+ return ret < 0 ? ret : 0;
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_ucsi_read);
+
+static irqreturn_t yoga_c630_ec_thread_intr(int irq, void *data)
+{
+ u8 req[] = { LENOVO_EC_REQUEST_NEXT_EVENT };
+ struct yoga_c630_ec *ec = data;
+ u8 event;
+ int ret;
+
+ mutex_lock(&ec->lock);
+ ret = yoga_c630_ec_request(ec, req, sizeof(req), &event, 1);
+ mutex_unlock(&ec->lock);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ blocking_notifier_call_chain(&ec->notifier_list, event, ec);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * yoga_c630_ec_register_notify - Register a notifier callback for EC events.
+ * @ec: Yoga C630 EC
+ * @nb: Notifier block pointer to register
+ *
+ * Return: 0 on success or negative error code.
+ */
+int yoga_c630_ec_register_notify(struct yoga_c630_ec *ec, struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&ec->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_register_notify);
+
+/**
+ * yoga_c630_ec_unregister_notify - Unregister notifier callback for EC events.
+ * @ec: Yoga C630 EC
+ * @nb: Notifier block pointer to unregister
+ *
+ * Unregister a notifier callback that was previously registered with
+ * yoga_c630_ec_register_notify().
+ */
+void yoga_c630_ec_unregister_notify(struct yoga_c630_ec *ec, struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&ec->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(yoga_c630_ec_unregister_notify);
+
+static void yoga_c630_aux_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+ kfree(adev);
+}
+
+static void yoga_c630_aux_remove(void *data)
+{
+ struct auxiliary_device *adev = data;
+
+ auxiliary_device_delete(adev);
+ auxiliary_device_uninit(adev);
+}
+
+static int yoga_c630_aux_init(struct device *parent, const char *name,
+ struct yoga_c630_ec *ec)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return -ENOMEM;
+
+ adev->name = name;
+ adev->id = 0;
+ adev->dev.parent = parent;
+ adev->dev.release = yoga_c630_aux_release;
+ adev->dev.platform_data = ec;
+
+ ret = auxiliary_device_init(adev);
+ if (ret) {
+ kfree(adev);
+ return ret;
+ }
+
+ ret = auxiliary_device_add(adev);
+ if (ret) {
+ auxiliary_device_uninit(adev);
+ return ret;
+ }
+
+ return devm_add_action_or_reset(parent, yoga_c630_aux_remove, adev);
+}
+
+static int yoga_c630_ec_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct yoga_c630_ec *ec;
+ int ret;
+
+ ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
+ if (!ec)
+ return -ENOMEM;
+
+ mutex_init(&ec->lock);
+ ec->client = client;
+ BLOCKING_INIT_NOTIFIER_HEAD(&ec->notifier_list);
+
+ ret = devm_request_threaded_irq(dev, client->irq,
+ NULL, yoga_c630_ec_thread_intr,
+ IRQF_ONESHOT, "yoga_c630_ec", ec);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "unable to request irq\n");
+
+ ret = yoga_c630_aux_init(dev, YOGA_C630_DEV_PSY, ec);
+ if (ret)
+ return ret;
+
+ return yoga_c630_aux_init(dev, YOGA_C630_DEV_UCSI, ec);
+}
+
+
+static const struct of_device_id yoga_c630_ec_of_match[] = {
+ { .compatible = "lenovo,yoga-c630-ec" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, yoga_c630_ec_of_match);
+
+static const struct i2c_device_id yoga_c630_ec_i2c_id_table[] = {
+ { "yoga-c630-ec", },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, yoga_c630_ec_i2c_id_table);
+
+static struct i2c_driver yoga_c630_ec_i2c_driver = {
+ .driver = {
+ .name = "yoga-c630-ec",
+ .of_match_table = yoga_c630_ec_of_match
+ },
+ .probe = yoga_c630_ec_probe,
+ .id_table = yoga_c630_ec_i2c_id_table,
+};
+module_i2c_driver(yoga_c630_ec_i2c_driver);
+
+MODULE_DESCRIPTION("Lenovo Yoga C630 Embedded Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index eeedd0c0395a..753d5662c080 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -12,6 +12,7 @@
#define PMF_H
#include <linux/acpi.h>
+#include <linux/input.h>
#include <linux/platform_profile.h>
#define POLICY_BUF_MAX_SZ 0x4b000
@@ -300,6 +301,7 @@ struct amd_pmf_dev {
void __iomem *policy_base;
bool smart_pc_enabled;
u16 pmf_if_version;
+ struct input_dev *pmf_idev;
};
struct apmf_sps_prop_granular_v2 {
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index b438de4d6bfc..e246367aacee 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -62,18 +62,12 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
param[0].u.memref.shm_offs = 0;
}
-static int amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
+static void amd_pmf_update_uevents(struct amd_pmf_dev *dev, u16 event)
{
- char *envp[2] = {};
-
- envp[0] = kasprintf(GFP_KERNEL, "EVENT_ID=%d", event);
- if (!envp[0])
- return -EINVAL;
-
- kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, envp);
-
- kfree(envp[0]);
- return 0;
+ input_report_key(dev->pmf_idev, event, 1); /* key press */
+ input_sync(dev->pmf_idev);
+ input_report_key(dev->pmf_idev, event, 0); /* key release */
+ input_sync(dev->pmf_idev);
}
static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
@@ -149,7 +143,20 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
break;
case PMF_POLICY_SYSTEM_STATE:
- amd_pmf_update_uevents(dev, val);
+ switch (val) {
+ case 0:
+ amd_pmf_update_uevents(dev, KEY_SLEEP);
+ break;
+ case 1:
+ amd_pmf_update_uevents(dev, KEY_SUSPEND);
+ break;
+ case 2:
+ amd_pmf_update_uevents(dev, KEY_SCREENLOCK);
+ break;
+ default:
+ dev_err(dev->dev, "Invalid PMF policy system state: %d\n", val);
+ }
+
dev_dbg(dev->dev, "update SYSTEM_STATE: %s\n",
amd_pmf_uevent_as_str(val));
break;
@@ -301,14 +308,9 @@ static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf,
return -EINVAL;
/* re-alloc to the new buffer length of the policy binary */
- new_policy_buf = kzalloc(length, GFP_KERNEL);
- if (!new_policy_buf)
- return -ENOMEM;
-
- if (copy_from_user(new_policy_buf, buf, length)) {
- kfree(new_policy_buf);
- return -EFAULT;
- }
+ new_policy_buf = memdup_user(buf, length);
+ if (IS_ERR(new_policy_buf))
+ return PTR_ERR(new_policy_buf);
kfree(dev->policy_buf);
dev->policy_buf = new_policy_buf;
@@ -368,6 +370,30 @@ static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id)
return rc;
}
+static int amd_pmf_register_input_device(struct amd_pmf_dev *dev)
+{
+ int err;
+
+ dev->pmf_idev = devm_input_allocate_device(dev->dev);
+ if (!dev->pmf_idev)
+ return -ENOMEM;
+
+ dev->pmf_idev->name = "PMF-TA output events";
+ dev->pmf_idev->phys = "amd-pmf/input0";
+
+ input_set_capability(dev->pmf_idev, EV_KEY, KEY_SLEEP);
+ input_set_capability(dev->pmf_idev, EV_KEY, KEY_SCREENLOCK);
+ input_set_capability(dev->pmf_idev, EV_KEY, KEY_SUSPEND);
+
+ err = input_register_device(dev->pmf_idev);
+ if (err) {
+ dev_err(dev->dev, "Failed to register input device: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
{
u32 size;
@@ -475,6 +501,10 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
if (pb_side_load)
amd_pmf_open_pb(dev, dev->dbgfs_dir);
+ ret = amd_pmf_register_input_device(dev);
+ if (ret)
+ goto error;
+
return 0;
error:
@@ -485,6 +515,9 @@ error:
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
{
+ if (dev->pmf_idev)
+ input_unregister_device(dev->pmf_idev);
+
if (pb_side_load && dev->esbin)
amd_pmf_remove_pb(dev);
diff --git a/drivers/platform/x86/asus-tf103c-dock.c b/drivers/platform/x86/asus-tf103c-dock.c
index 8f0f87637c5f..b441d8ca72d3 100644
--- a/drivers/platform/x86/asus-tf103c-dock.c
+++ b/drivers/platform/x86/asus-tf103c-dock.c
@@ -490,7 +490,7 @@ static void tf103c_dock_enable_touchpad(struct tf103c_dock_data *dock)
return;
}
- strscpy(board_info.type, "elan_i2c", I2C_NAME_SIZE);
+ strscpy(board_info.type, "elan_i2c");
board_info.addr = TF103C_DOCK_TP_ADDR;
board_info.dev_name = TF103C_DOCK_DEV_NAME "-tp";
board_info.irq = dock->tp_irq;
@@ -795,7 +795,7 @@ static int tf103c_dock_probe(struct i2c_client *client)
*/
dock->ec_client = client;
- strscpy(board_info.type, "tf103c-dock-intr", I2C_NAME_SIZE);
+ strscpy(board_info.type, "tf103c-dock-intr");
board_info.addr = TF103C_DOCK_INTR_ADDR;
board_info.dev_name = TF103C_DOCK_DEV_NAME "-intr";
@@ -803,7 +803,7 @@ static int tf103c_dock_probe(struct i2c_client *client)
if (IS_ERR(dock->intr_client))
return dev_err_probe(dev, PTR_ERR(dock->intr_client), "creating intr client\n");
- strscpy(board_info.type, "tf103c-dock-kbd", I2C_NAME_SIZE);
+ strscpy(board_info.type, "tf103c-dock-kbd");
board_info.addr = TF103C_DOCK_KBD_ADDR;
board_info.dev_name = TF103C_DOCK_DEV_NAME "-kbd";
@@ -846,8 +846,8 @@ static int tf103c_dock_probe(struct i2c_client *client)
dock->hid->vendor = 0x0b05; /* USB_VENDOR_ID_ASUSTEK */
dock->hid->product = 0x0103; /* From TF-103-C */
dock->hid->version = 0x0100; /* 1.0 */
- strscpy(dock->hid->name, "Asus TF103C Dock Keyboard", sizeof(dock->hid->name));
- strscpy(dock->hid->phys, dev_name(dev), sizeof(dock->hid->phys));
+ strscpy(dock->hid->name, "Asus TF103C Dock Keyboard");
+ strscpy(dock->hid->phys, dev_name(dev));
ret = hid_add_device(dock->hid);
if (ret)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3f9b6285c9a6..cc735931f97b 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -238,6 +238,7 @@ struct asus_wmi {
struct led_classdev lightbar_led;
int lightbar_led_wk;
struct led_classdev micmute_led;
+ struct led_classdev camera_led;
struct workqueue_struct *led_workqueue;
struct work_struct tpd_led_work;
struct work_struct wlan_led_work;
@@ -879,10 +880,14 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct asus_wmi *asus = dev_get_drvdata(dev);
u32 cmd, mode, r, g, b, speed;
+ struct led_classdev *led;
+ struct asus_wmi *asus;
int err;
+ led = dev_get_drvdata(dev);
+ asus = container_of(led, struct asus_wmi, kbd_led);
+
if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
return -EINVAL;
@@ -1642,6 +1647,27 @@ static int micmute_led_set(struct led_classdev *led_cdev,
return err < 0 ? err : 0;
}
+static enum led_brightness camera_led_get(struct led_classdev *led_cdev)
+{
+ struct asus_wmi *asus;
+ u32 result;
+
+ asus = container_of(led_cdev, struct asus_wmi, camera_led);
+ asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CAMERA_LED, &result);
+
+ return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+}
+
+static int camera_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ int state = brightness != LED_OFF;
+ int err;
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CAMERA_LED, state, NULL);
+ return err < 0 ? err : 0;
+}
+
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
led_classdev_unregister(&asus->kbd_led);
@@ -1649,6 +1675,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
led_classdev_unregister(&asus->wlan_led);
led_classdev_unregister(&asus->lightbar_led);
led_classdev_unregister(&asus->micmute_led);
+ led_classdev_unregister(&asus->camera_led);
if (asus->led_workqueue)
destroy_workqueue(asus->led_workqueue);
@@ -1740,6 +1767,18 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CAMERA_LED)) {
+ asus->camera_led.name = "asus::camera";
+ asus->camera_led.max_brightness = 1;
+ asus->camera_led.brightness_get = camera_led_get;
+ asus->camera_led.brightness_set_blocking = camera_led_set;
+
+ rv = led_classdev_register(&asus->platform_device->dev,
+ &asus->camera_led);
+ if (rv)
+ goto error;
+ }
+
error:
if (rv)
asus_wmi_led_exit(asus);
diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index 195a8bf532cc..85a78ef91182 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -91,6 +91,19 @@ config DELL_RBTN
To compile this driver as a module, choose M here: the module will
be called dell-rbtn.