platform/x86: ideapad-laptop: move ymc_trigger_ec from lenovo-ymc
[ Upstream commit cde7886b35176d56e72bfc68dc104fa08e7b072c ] Some models need to trigger the EC after each YMC event for the yoga mode control to work properly. EC triggering consist of a VPC call from the lenovo-ymc module. Except for this, all VPC calls are in the ideapad-laptop module. Since ideapad-laptop has a notification chain, a new YMC_EVENT action can be added and triggered from the lenovo-ymc module. Then the ideapad-laptop can trigger the EC. If the triggering is in the ideapad-laptop module, then the ec_trigger module parameter should be there as well. Move the ymc_trigger_ec functionality and the ec_trigger module parameter to the ideapad-laptop module. Signed-off-by: Gergo Koteles <soyer@irl.hu> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/d980ab3ac32b5e554f456b0ff17279bfdbe2a203.1721898747.git.soyer@irl.hu Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Stable-dep-of: 5808c3421695 ("platform/x86: ideapad-laptop: use usleep_range() for EC polling") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d19ae7b033
commit
f8761b11f1
@@ -466,6 +466,7 @@ config LENOVO_YMC
|
||||
tristate "Lenovo Yoga Tablet Mode Control"
|
||||
depends on ACPI_WMI
|
||||
depends on INPUT
|
||||
depends on IDEAPAD_LAPTOP
|
||||
select INPUT_SPARSEKMAP
|
||||
help
|
||||
This driver maps the Tablet Mode Control switch to SW_TABLET_MODE input
|
||||
|
@@ -145,6 +145,7 @@ struct ideapad_private {
|
||||
bool touchpad_ctrl_via_ec : 1;
|
||||
bool ctrl_ps2_aux_port : 1;
|
||||
bool usb_charging : 1;
|
||||
bool ymc_ec_trigger : 1;
|
||||
} features;
|
||||
struct {
|
||||
bool initialized;
|
||||
@@ -188,6 +189,12 @@ MODULE_PARM_DESC(touchpad_ctrl_via_ec,
|
||||
"Enable registering a 'touchpad' sysfs-attribute which can be used to manually "
|
||||
"tell the EC to enable/disable the touchpad. This may not work on all models.");
|
||||
|
||||
static bool ymc_ec_trigger __read_mostly;
|
||||
module_param(ymc_ec_trigger, bool, 0444);
|
||||
MODULE_PARM_DESC(ymc_ec_trigger,
|
||||
"Enable EC triggering work-around to force emitting tablet mode events. "
|
||||
"If you need this please report this to: platform-driver-x86@vger.kernel.org");
|
||||
|
||||
/*
|
||||
* shared data
|
||||
*/
|
||||
@@ -1501,10 +1508,50 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
|
||||
priv->r_touchpad_val = value;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] = {
|
||||
{
|
||||
/* Lenovo Yoga 7 14ARB7 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Yoga 7 14ACN6 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static void ideapad_laptop_trigger_ec(void)
|
||||
{
|
||||
struct ideapad_private *priv;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&ideapad_shared_mutex);
|
||||
|
||||
priv = ideapad_shared;
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
if (!priv->features.ymc_ec_trigger)
|
||||
return;
|
||||
|
||||
ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1);
|
||||
if (ret)
|
||||
dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret);
|
||||
}
|
||||
|
||||
static int ideapad_laptop_nb_notify(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
switch (action) {
|
||||
case IDEAPAD_LAPTOP_YMC_EVENT:
|
||||
ideapad_laptop_trigger_ec();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1670,6 +1717,8 @@ static void ideapad_check_features(struct ideapad_private *priv)
|
||||
priv->features.ctrl_ps2_aux_port =
|
||||
ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list);
|
||||
priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec;
|
||||
priv->features.ymc_ec_trigger =
|
||||
ymc_ec_trigger || dmi_check_system(ymc_ec_trigger_quirk_dmi_table);
|
||||
|
||||
if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
|
||||
priv->features.fan_mode = true;
|
||||
|
@@ -14,6 +14,10 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
enum ideapad_laptop_notifier_actions {
|
||||
IDEAPAD_LAPTOP_YMC_EVENT,
|
||||
};
|
||||
|
||||
int ideapad_laptop_register_notifier(struct notifier_block *nb);
|
||||
int ideapad_laptop_unregister_notifier(struct notifier_block *nb);
|
||||
void ideapad_laptop_call_notifier(unsigned long action, void *data);
|
||||
|
@@ -20,32 +20,10 @@
|
||||
#define LENOVO_YMC_QUERY_INSTANCE 0
|
||||
#define LENOVO_YMC_QUERY_METHOD 0x01
|
||||
|
||||
static bool ec_trigger __read_mostly;
|
||||
module_param(ec_trigger, bool, 0444);
|
||||
MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
|
||||
|
||||
static bool force;
|
||||
module_param(force, bool, 0444);
|
||||
MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
|
||||
|
||||
static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
|
||||
{
|
||||
/* Lenovo Yoga 7 14ARB7 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Yoga 7 14ACN6 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
|
||||
{
|
||||
.matches = {
|
||||
@@ -62,21 +40,8 @@ static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
|
||||
|
||||
struct lenovo_ymc_private {
|
||||
struct input_dev *input_dev;
|
||||
struct acpi_device *ec_acpi_dev;
|
||||
};
|
||||
|
||||
static void lenovo_ymc_trigger_ec(struct wmi_device *wdev, struct lenovo_ymc_private *priv)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!priv->ec_acpi_dev)
|
||||
return;
|
||||
|
||||
err = write_ec_cmd(priv->ec_acpi_dev->handle, VPCCMD_W_YMC, 1);
|
||||
if (err)
|
||||
dev_warn(&wdev->dev, "Could not write YMC: %d\n", err);
|
||||
}
|
||||
|
||||
static const struct key_entry lenovo_ymc_keymap[] = {
|
||||
/* Ignore the uninitialized state */
|
||||
{ KE_IGNORE, 0x00 },
|
||||
@@ -127,11 +92,9 @@ static void lenovo_ymc_notify(struct wmi_device *wdev, union acpi_object *data)
|
||||
|
||||
free_obj:
|
||||
kfree(obj);
|
||||
lenovo_ymc_trigger_ec(wdev, priv);
|
||||
ideapad_laptop_call_notifier(IDEAPAD_LAPTOP_YMC_EVENT, &code);
|
||||
}
|
||||
|
||||
static void acpi_dev_put_helper(void *p) { acpi_dev_put(p); }
|
||||
|
||||
static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
|
||||
{
|
||||
struct lenovo_ymc_private *priv;
|
||||
@@ -145,29 +108,10 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
|
||||
|
||||
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (ec_trigger) {
|
||||
pr_debug("Lenovo YMC enable EC triggering.\n");
|
||||
priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VPC2004", NULL, -1);
|
||||
|
||||
if (!priv->ec_acpi_dev) {
|
||||
dev_err(&wdev->dev, "Could not find EC ACPI device.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
err = devm_add_action_or_reset(&wdev->dev,
|
||||
acpi_dev_put_helper, priv->ec_acpi_dev);
|
||||
if (err) {
|
||||
dev_err(&wdev->dev,
|
||||
"Could not clean up EC ACPI device: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
input_dev = devm_input_allocate_device(&wdev->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
@@ -194,7 +138,6 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
|
||||
dev_set_drvdata(&wdev->dev, priv);
|
||||
|
||||
/* Report the state for the first time on probe */
|
||||
lenovo_ymc_trigger_ec(wdev, priv);
|
||||
lenovo_ymc_notify(wdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -219,3 +162,4 @@ module_wmi_driver(lenovo_ymc_driver);
|
||||
MODULE_AUTHOR("Gergo Koteles <soyer@irl.hu>");
|
||||
MODULE_DESCRIPTION("Lenovo Yoga Mode Control driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS(IDEAPAD_LAPTOP);
|
||||
|
Reference in New Issue
Block a user