Skip to content

Commit cde7886

Browse files
soyersoyerij-intel
authored andcommitted
platform/x86: ideapad-laptop: move ymc_trigger_ec from lenovo-ymc
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 <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/d980ab3ac32b5e554f456b0ff17279bfdbe2a203.1721898747.git.soyer@irl.hu Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 613e390 commit cde7886

File tree

4 files changed

+56
-58
lines changed

4 files changed

+56
-58
lines changed

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ config LENOVO_YMC
477477
tristate "Lenovo Yoga Tablet Mode Control"
478478
depends on ACPI_WMI
479479
depends on INPUT
480+
depends on IDEAPAD_LAPTOP
480481
select INPUT_SPARSEKMAP
481482
help
482483
This driver maps the Tablet Mode Control switch to SW_TABLET_MODE input

drivers/platform/x86/ideapad-laptop.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ struct ideapad_private {
146146
bool touchpad_ctrl_via_ec : 1;
147147
bool ctrl_ps2_aux_port : 1;
148148
bool usb_charging : 1;
149+
bool ymc_ec_trigger : 1;
149150
} features;
150151
struct {
151152
bool initialized;
@@ -194,6 +195,12 @@ MODULE_PARM_DESC(touchpad_ctrl_via_ec,
194195
"Enable registering a 'touchpad' sysfs-attribute which can be used to manually "
195196
"tell the EC to enable/disable the touchpad. This may not work on all models.");
196197

198+
static bool ymc_ec_trigger __read_mostly;
199+
module_param(ymc_ec_trigger, bool, 0444);
200+
MODULE_PARM_DESC(ymc_ec_trigger,
201+
"Enable EC triggering work-around to force emitting tablet mode events. "
202+
"If you need this please report this to: [email protected]");
203+
197204
/*
198205
* shared data
199206
*/
@@ -1592,10 +1599,50 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
15921599
priv->r_touchpad_val = value;
15931600
}
15941601

1602+
static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] = {
1603+
{
1604+
/* Lenovo Yoga 7 14ARB7 */
1605+
.matches = {
1606+
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1607+
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
1608+
},
1609+
},
1610+
{
1611+
/* Lenovo Yoga 7 14ACN6 */
1612+
.matches = {
1613+
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1614+
DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
1615+
},
1616+
},
1617+
{ }
1618+
};
1619+
1620+
static void ideapad_laptop_trigger_ec(void)
1621+
{
1622+
struct ideapad_private *priv;
1623+
int ret;
1624+
1625+
guard(mutex)(&ideapad_shared_mutex);
1626+
1627+
priv = ideapad_shared;
1628+
if (!priv)
1629+
return;
1630+
1631+
if (!priv->features.ymc_ec_trigger)
1632+
return;
1633+
1634+
ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1);
1635+
if (ret)
1636+
dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret);
1637+
}
1638+
15951639
static int ideapad_laptop_nb_notify(struct notifier_block *nb,
15961640
unsigned long action, void *data)
15971641
{
15981642
switch (action) {
1643+
case IDEAPAD_LAPTOP_YMC_EVENT:
1644+
ideapad_laptop_trigger_ec();
1645+
break;
15991646
}
16001647

16011648
return 0;
@@ -1761,6 +1808,8 @@ static void ideapad_check_features(struct ideapad_private *priv)
17611808
priv->features.ctrl_ps2_aux_port =
17621809
ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list);
17631810
priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec;
1811+
priv->features.ymc_ec_trigger =
1812+
ymc_ec_trigger || dmi_check_system(ymc_ec_trigger_quirk_dmi_table);
17641813

17651814
if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
17661815
priv->features.fan_mode = true;

drivers/platform/x86/ideapad-laptop.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#include <linux/errno.h>
1515
#include <linux/notifier.h>
1616

17+
enum ideapad_laptop_notifier_actions {
18+
IDEAPAD_LAPTOP_YMC_EVENT,
19+
};
20+
1721
int ideapad_laptop_register_notifier(struct notifier_block *nb);
1822
int ideapad_laptop_unregister_notifier(struct notifier_block *nb);
1923
void ideapad_laptop_call_notifier(unsigned long action, void *data);

drivers/platform/x86/lenovo-ymc.c

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,10 @@
2020
#define LENOVO_YMC_QUERY_INSTANCE 0
2121
#define LENOVO_YMC_QUERY_METHOD 0x01
2222

23-
static bool ec_trigger __read_mostly;
24-
module_param(ec_trigger, bool, 0444);
25-
MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
26-
2723
static bool force;
2824
module_param(force, bool, 0444);
2925
MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
3026

31-
static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
32-
{
33-
/* Lenovo Yoga 7 14ARB7 */
34-
.matches = {
35-
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
36-
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
37-
},
38-
},
39-
{
40-
/* Lenovo Yoga 7 14ACN6 */
41-
.matches = {
42-
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
43-
DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
44-
},
45-
},
46-
{ }
47-
};
48-
4927
static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
5028
{
5129
.matches = {
@@ -62,21 +40,8 @@ static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
6240

6341
struct lenovo_ymc_private {
6442
struct input_dev *input_dev;
65-
struct acpi_device *ec_acpi_dev;
6643
};
6744

68-
static void lenovo_ymc_trigger_ec(struct wmi_device *wdev, struct lenovo_ymc_private *priv)
69-
{
70-
int err;
71-
72-
if (!priv->ec_acpi_dev)
73-
return;
74-
75-
err = write_ec_cmd(priv->ec_acpi_dev->handle, VPCCMD_W_YMC, 1);
76-
if (err)
77-
dev_warn(&wdev->dev, "Could not write YMC: %d\n", err);
78-
}
79-
8045
static const struct key_entry lenovo_ymc_keymap[] = {
8146
/* Laptop */
8247
{ KE_SW, 0x01, { .sw = { SW_TABLET_MODE, 0 } } },
@@ -125,11 +90,9 @@ static void lenovo_ymc_notify(struct wmi_device *wdev, union acpi_object *data)
12590

12691
free_obj:
12792
kfree(obj);
128-
lenovo_ymc_trigger_ec(wdev, priv);
93+
ideapad_laptop_call_notifier(IDEAPAD_LAPTOP_YMC_EVENT, &code);
12994
}
13095

131-
static void acpi_dev_put_helper(void *p) { acpi_dev_put(p); }
132-
13396
static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
13497
{
13598
struct lenovo_ymc_private *priv;
@@ -143,29 +106,10 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
143106
return -ENODEV;
144107
}
145108

146-
ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
147-
148109
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
149110
if (!priv)
150111
return -ENOMEM;
151112

152-
if (ec_trigger) {
153-
pr_debug("Lenovo YMC enable EC triggering.\n");
154-
priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VPC2004", NULL, -1);
155-
156-
if (!priv->ec_acpi_dev) {
157-
dev_err(&wdev->dev, "Could not find EC ACPI device.\n");
158-
return -ENODEV;
159-
}
160-
err = devm_add_action_or_reset(&wdev->dev,
161-
acpi_dev_put_helper, priv->ec_acpi_dev);
162-
if (err) {
163-
dev_err(&wdev->dev,
164-
"Could not clean up EC ACPI device: %d\n", err);
165-
return err;
166-
}
167-
}
168-
169113
input_dev = devm_input_allocate_device(&wdev->dev);
170114
if (!input_dev)
171115
return -ENOMEM;
@@ -192,7 +136,6 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
192136
dev_set_drvdata(&wdev->dev, priv);
193137

194138
/* Report the state for the first time on probe */
195-
lenovo_ymc_trigger_ec(wdev, priv);
196139
lenovo_ymc_notify(wdev, NULL);
197140
return 0;
198141
}
@@ -217,3 +160,4 @@ module_wmi_driver(lenovo_ymc_driver);
217160
MODULE_AUTHOR("Gergo Koteles <[email protected]>");
218161
MODULE_DESCRIPTION("Lenovo Yoga Mode Control driver");
219162
MODULE_LICENSE("GPL");
163+
MODULE_IMPORT_NS(IDEAPAD_LAPTOP);

0 commit comments

Comments
 (0)