xref: /openbmc/linux/drivers/platform/x86/ideapad-laptop.c (revision 7df45f35313c1ae083dac72c066b3aebfc7fc0cd)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
4  *
5  *  Copyright © 2010 Intel Corporation
6  *  Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
7  */
8 
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 
11 #include <linux/acpi.h>
12 #include <linux/backlight.h>
13 #include <linux/bitfield.h>
14 #include <linux/bitops.h>
15 #include <linux/bug.h>
16 #include <linux/debugfs.h>
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <linux/dmi.h>
20 #include <linux/fb.h>
21 #include <linux/i8042.h>
22 #include <linux/init.h>
23 #include <linux/input.h>
24 #include <linux/input/sparse-keymap.h>
25 #include <linux/jiffies.h>
26 #include <linux/kernel.h>
27 #include <linux/leds.h>
28 #include <linux/module.h>
29 #include <linux/platform_device.h>
30 #include <linux/platform_profile.h>
31 #include <linux/rfkill.h>
32 #include <linux/seq_file.h>
33 #include <linux/sysfs.h>
34 #include <linux/types.h>
35 #include <linux/wmi.h>
36 #include "ideapad-laptop.h"
37 
38 #include <acpi/video.h>
39 
40 #include <dt-bindings/leds/common.h>
41 
42 #define IDEAPAD_RFKILL_DEV_NUM	3
43 
44 enum {
45 	CFG_CAP_BT_BIT       = 16,
46 	CFG_CAP_3G_BIT       = 17,
47 	CFG_CAP_WIFI_BIT     = 18,
48 	CFG_CAP_CAM_BIT      = 19,
49 
50 	/*
51 	 * These are OnScreenDisplay support bits that can be useful to determine
52 	 * whether a hotkey exists/should show OSD. But they aren't particularly
53 	 * meaningful since they were introduced later, i.e. 2010 IdeaPads
54 	 * don't have these, but they still have had OSD for hotkeys.
55 	 */
56 	CFG_OSD_NUMLK_BIT    = 27,
57 	CFG_OSD_CAPSLK_BIT   = 28,
58 	CFG_OSD_MICMUTE_BIT  = 29,
59 	CFG_OSD_TOUCHPAD_BIT = 30,
60 	CFG_OSD_CAM_BIT      = 31,
61 };
62 
63 enum {
64 	GBMD_CONSERVATION_STATE_BIT = 5,
65 };
66 
67 enum {
68 	SBMC_CONSERVATION_ON  = 3,
69 	SBMC_CONSERVATION_OFF = 5,
70 };
71 
72 enum {
73 	HALS_KBD_BL_SUPPORT_BIT       = 4,
74 	HALS_KBD_BL_STATE_BIT         = 5,
75 	HALS_USB_CHARGING_SUPPORT_BIT = 6,
76 	HALS_USB_CHARGING_STATE_BIT   = 7,
77 	HALS_FNLOCK_SUPPORT_BIT       = 9,
78 	HALS_FNLOCK_STATE_BIT         = 10,
79 	HALS_HOTKEYS_PRIMARY_BIT      = 11,
80 };
81 
82 enum {
83 	SALS_KBD_BL_ON        = 0x8,
84 	SALS_KBD_BL_OFF       = 0x9,
85 	SALS_USB_CHARGING_ON  = 0xa,
86 	SALS_USB_CHARGING_OFF = 0xb,
87 	SALS_FNLOCK_ON        = 0xe,
88 	SALS_FNLOCK_OFF       = 0xf,
89 };
90 
91 enum {
92 	VPCCMD_R_VPC1 = 0x10,
93 	VPCCMD_R_BL_MAX,
94 	VPCCMD_R_BL,
95 	VPCCMD_W_BL,
96 	VPCCMD_R_WIFI,
97 	VPCCMD_W_WIFI,
98 	VPCCMD_R_BT,
99 	VPCCMD_W_BT,
100 	VPCCMD_R_BL_POWER,
101 	VPCCMD_R_NOVO,
102 	VPCCMD_R_VPC2,
103 	VPCCMD_R_TOUCHPAD,
104 	VPCCMD_W_TOUCHPAD,
105 	VPCCMD_R_CAMERA,
106 	VPCCMD_W_CAMERA,
107 	VPCCMD_R_3G,
108 	VPCCMD_W_3G,
109 	VPCCMD_R_ODD, /* 0x21 */
110 	VPCCMD_W_FAN,
111 	VPCCMD_R_RF,
112 	VPCCMD_W_RF,
113 	VPCCMD_W_YMC = 0x2A,
114 	VPCCMD_R_FAN = 0x2B,
115 	VPCCMD_R_SPECIAL_BUTTONS = 0x31,
116 	VPCCMD_W_BL_POWER = 0x33,
117 };
118 
119 /*
120  * These correspond to the number of supported states - 1
121  * Future keyboard types may need a new system, if there's a collision
122  * KBD_BL_TRISTATE_AUTO has no way to report or set the auto state
123  * so it effectively has 3 states, but needs to handle 4
124  */
125 enum {
126 	KBD_BL_STANDARD      = 1,
127 	KBD_BL_TRISTATE      = 2,
128 	KBD_BL_TRISTATE_AUTO = 3,
129 };
130 
131 #define KBD_BL_QUERY_TYPE		0x1
132 #define KBD_BL_TRISTATE_TYPE		0x5
133 #define KBD_BL_TRISTATE_AUTO_TYPE	0x7
134 
135 #define KBD_BL_COMMAND_GET		0x2
136 #define KBD_BL_COMMAND_SET		0x3
137 #define KBD_BL_COMMAND_TYPE		GENMASK(7, 4)
138 
139 #define KBD_BL_GET_BRIGHTNESS		GENMASK(15, 1)
140 #define KBD_BL_SET_BRIGHTNESS		GENMASK(19, 16)
141 
142 #define KBD_BL_KBLC_CHANGED_EVENT	12
143 
144 struct ideapad_dytc_priv {
145 	enum platform_profile_option current_profile;
146 	struct platform_profile_handler pprof;
147 	struct mutex mutex; /* protects the DYTC interface */
148 	struct ideapad_private *priv;
149 };
150 
151 struct ideapad_rfk_priv {
152 	int dev;
153 	struct ideapad_private *priv;
154 };
155 
156 struct ideapad_private {
157 	struct acpi_device *adev;
158 	struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
159 	struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
160 	struct platform_device *platform_device;
161 	struct input_dev *inputdev;
162 	struct backlight_device *blightdev;
163 	struct ideapad_dytc_priv *dytc;
164 	struct dentry *debug;
165 	unsigned long cfg;
166 	unsigned long r_touchpad_val;
167 	struct {
168 		bool conservation_mode    : 1;
169 		bool dytc                 : 1;
170 		bool fan_mode             : 1;
171 		bool fn_lock              : 1;
172 		bool set_fn_lock_led      : 1;
173 		bool hw_rfkill_switch     : 1;
174 		bool kbd_bl               : 1;
175 		bool touchpad_ctrl_via_ec : 1;
176 		bool ctrl_ps2_aux_port    : 1;
177 		bool usb_charging         : 1;
178 		bool ymc_ec_trigger       : 1;
179 	} features;
180 	struct {
181 		bool initialized;
182 		int type;
183 		struct led_classdev led;
184 		unsigned int last_brightness;
185 	} kbd_bl;
186 };
187 
188 static bool no_bt_rfkill;
189 module_param(no_bt_rfkill, bool, 0444);
190 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
191 
192 static bool allow_v4_dytc;
193 module_param(allow_v4_dytc, bool, 0444);
194 MODULE_PARM_DESC(allow_v4_dytc,
195 	"Enable DYTC version 4 platform-profile support. "
196 	"If you need this please report this to: platform-driver-x86@vger.kernel.org");
197 
198 static bool hw_rfkill_switch;
199 module_param(hw_rfkill_switch, bool, 0444);
200 MODULE_PARM_DESC(hw_rfkill_switch,
201 	"Enable rfkill support for laptops with a hw on/off wifi switch/slider. "
202 	"If you need this please report this to: platform-driver-x86@vger.kernel.org");
203 
204 static bool set_fn_lock_led;
205 module_param(set_fn_lock_led, bool, 0444);
206 MODULE_PARM_DESC(set_fn_lock_led,
207 	"Enable driver based updates of the fn-lock LED on fn-lock changes. "
208 	"If you need this please report this to: platform-driver-x86@vger.kernel.org");
209 
210 static bool ctrl_ps2_aux_port;
211 module_param(ctrl_ps2_aux_port, bool, 0444);
212 MODULE_PARM_DESC(ctrl_ps2_aux_port,
213 	"Enable driver based PS/2 aux port en-/dis-abling on touchpad on/off toggle. "
214 	"If you need this please report this to: platform-driver-x86@vger.kernel.org");
215 
216 static bool touchpad_ctrl_via_ec;
217 module_param(touchpad_ctrl_via_ec, bool, 0444);
218 MODULE_PARM_DESC(touchpad_ctrl_via_ec,
219 	"Enable registering a 'touchpad' sysfs-attribute which can be used to manually "
220 	"tell the EC to enable/disable the touchpad. This may not work on all models.");
221 
222 static bool ymc_ec_trigger __read_mostly;
223 module_param(ymc_ec_trigger, bool, 0444);
224 MODULE_PARM_DESC(ymc_ec_trigger,
225 	"Enable EC triggering work-around to force emitting tablet mode events. "
226 	"If you need this please report this to: platform-driver-x86@vger.kernel.org");
227 
228 /*
229  * shared data
230  */
231 
232 static struct ideapad_private *ideapad_shared;
233 static DEFINE_MUTEX(ideapad_shared_mutex);
234 
ideapad_shared_init(struct ideapad_private * priv)235 static int ideapad_shared_init(struct ideapad_private *priv)
236 {
237 	int ret;
238 
239 	mutex_lock(&ideapad_shared_mutex);
240 
241 	if (!ideapad_shared) {
242 		ideapad_shared = priv;
243 		ret = 0;
244 	} else {
245 		dev_warn(&priv->adev->dev, "found multiple platform devices\n");
246 		ret = -EINVAL;
247 	}
248 
249 	mutex_unlock(&ideapad_shared_mutex);
250 
251 	return ret;
252 }
253 
ideapad_shared_exit(struct ideapad_private * priv)254 static void ideapad_shared_exit(struct ideapad_private *priv)
255 {
256 	mutex_lock(&ideapad_shared_mutex);
257 
258 	if (ideapad_shared == priv)
259 		ideapad_shared = NULL;
260 
261 	mutex_unlock(&ideapad_shared_mutex);
262 }
263 
264 /*
265  * ACPI Helpers
266  */
267 #define IDEAPAD_EC_TIMEOUT 200 /* in ms */
268 
269 /*
270  * Some models (e.g., ThinkBook since 2024) have a low tolerance for being
271  * polled too frequently. Doing so may break the state machine in the EC,
272  * resulting in a hard shutdown.
273  *
274  * It is also observed that frequent polls may disturb the ongoing operation
275  * and notably delay the availability of EC response.
276  *
277  * These values are used as the delay before the first poll and the interval
278  * between subsequent polls to solve the above issues.
279  */
280 #define IDEAPAD_EC_POLL_MIN_US 150
281 #define IDEAPAD_EC_POLL_MAX_US 300
282 
eval_int(acpi_handle handle,const char * name,unsigned long * res)283 static int eval_int(acpi_handle handle, const char *name, unsigned long *res)
284 {
285 	unsigned long long result;
286 	acpi_status status;
287 
288 	status = acpi_evaluate_integer(handle, (char *)name, NULL, &result);
289 	if (ACPI_FAILURE(status))
290 		return -EIO;
291 
292 	*res = result;
293 
294 	return 0;
295 }
296 
eval_int_with_arg(acpi_handle handle,const char * name,unsigned long arg,unsigned long * res)297 static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg,
298 			     unsigned long *res)
299 {
300 	struct acpi_object_list params;
301 	unsigned long long result;
302 	union acpi_object in_obj;
303 	acpi_status status;
304 
305 	params.count = 1;
306 	params.pointer = &in_obj;
307 	in_obj.type = ACPI_TYPE_INTEGER;
308 	in_obj.integer.value = arg;
309 
310 	status = acpi_evaluate_integer(handle, (char *)name, &params, &result);
311 	if (ACPI_FAILURE(status))
312 		return -EIO;
313 
314 	if (res)
315 		*res = result;
316 
317 	return 0;
318 }
319 
exec_simple_method(acpi_handle handle,const char * name,unsigned long arg)320 static int exec_simple_method(acpi_handle handle, const char *name, unsigned long arg)
321 {
322 	acpi_status status = acpi_execute_simple_method(handle, (char *)name, arg);
323 
324 	return ACPI_FAILURE(status) ? -EIO : 0;
325 }
326 
eval_gbmd(acpi_handle handle,unsigned long * res)327 static int eval_gbmd(acpi_handle handle, unsigned long *res)
328 {
329 	return eval_int(handle, "GBMD", res);
330 }
331 
exec_sbmc(acpi_handle handle,unsigned long arg)332 static int exec_sbmc(acpi_handle handle, unsigned long arg)
333 {
334 	return exec_simple_method(handle, "SBMC", arg);
335 }
336 
eval_hals(acpi_handle handle,unsigned long * res)337 static int eval_hals(acpi_handle handle, unsigned long *res)
338 {
339 	return eval_int(handle, "HALS", res);
340 }
341 
exec_sals(acpi_handle handle,unsigned long arg)342 static int exec_sals(acpi_handle handle, unsigned long arg)
343 {
344 	return exec_simple_method(handle, "SALS", arg);
345 }
346 
exec_kblc(acpi_handle handle,unsigned long arg)347 static int exec_kblc(acpi_handle handle, unsigned long arg)
348 {
349 	return exec_simple_method(handle, "KBLC", arg);
350 }
351 
eval_kblc(acpi_handle handle,unsigned long cmd,unsigned long * res)352 static int eval_kblc(acpi_handle handle, unsigned long cmd, unsigned long *res)
353 {
354 	return eval_int_with_arg(handle, "KBLC", cmd, res);
355 }
356 
eval_dytc(acpi_handle handle,unsigned long cmd,unsigned long * res)357 static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res)
358 {
359 	return eval_int_with_arg(handle, "DYTC", cmd, res);
360 }
361 
eval_vpcr(acpi_handle handle,unsigned long cmd,unsigned long * res)362 static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res)
363 {
364 	return eval_int_with_arg(handle, "VPCR", cmd, res);
365 }
366 
eval_vpcw(acpi_handle handle,unsigned long cmd,unsigned long data)367 static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data)
368 {
369 	struct acpi_object_list params;
370 	union acpi_object in_obj[2];
371 	acpi_status status;
372 
373 	params.count = 2;
374 	params.pointer = in_obj;
375 	in_obj[0].type = ACPI_TYPE_INTEGER;
376 	in_obj[0].integer.value = cmd;
377 	in_obj[1].type = ACPI_TYPE_INTEGER;
378 	in_obj[1].integer.value = data;
379 
380 	status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
381 	if (ACPI_FAILURE(status))
382 		return -EIO;
383 
384 	return 0;
385 }
386 
read_ec_data(acpi_handle handle,unsigned long cmd,unsigned long * data)387 static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data)
388 {
389 	unsigned long end_jiffies, val;
390 	int err;
391 
392 	err = eval_vpcw(handle, 1, cmd);
393 	if (err)
394 		return err;
395 
396 	end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
397 
398 	while (time_before(jiffies, end_jiffies)) {
399 		usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US);
400 
401 		err = eval_vpcr(handle, 1, &val);
402 		if (err)
403 			return err;
404 
405 		if (val == 0)
406 			return eval_vpcr(handle, 0, data);
407 	}
408 
409 	acpi_handle_err(handle, "timeout in %s\n", __func__);
410 
411 	return -ETIMEDOUT;
412 }
413 
write_ec_cmd(acpi_handle handle,unsigned long cmd,unsigned long data)414 static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data)
415 {
416 	unsigned long end_jiffies, val;
417 	int err;
418 
419 	err = eval_vpcw(handle, 0, data);
420 	if (err)
421 		return err;
422 
423 	err = eval_vpcw(handle, 1, cmd);
424 	if (err)
425 		return err;
426 
427 	end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
428 
429 	while (time_before(jiffies, end_jiffies)) {
430 		usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US);
431 
432 		err = eval_vpcr(handle, 1, &val);
433 		if (err)
434 			return err;
435 
436 		if (val == 0)
437 			return 0;
438 	}
439 
440 	acpi_handle_err(handle, "timeout in %s\n", __func__);
441 
442 	return -ETIMEDOUT;
443 }
444 
445 /*
446  * debugfs
447  */
debugfs_status_show(struct seq_file * s,void * data)448 static int debugfs_status_show(struct seq_file *s, void *data)
449 {
450 	struct ideapad_private *priv = s->private;
451 	unsigned long value;
452 
453 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
454 		seq_printf(s, "Backlight max:  %lu\n", value);
455 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
456 		seq_printf(s, "Backlight now:  %lu\n", value);
457 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
458 		seq_printf(s, "BL power value: %s (%lu)\n", value ? "on" : "off", value);
459 
460 	seq_puts(s, "=====================\n");
461 
462 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
463 		seq_printf(s, "Radio status: %s (%lu)\n", value ? "on" : "off", value);
464 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
465 		seq_printf(s, "Wifi status:  %s (%lu)\n", value ? "on" : "off", value);
466 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
467 		seq_printf(s, "BT status:    %s (%lu)\n", value ? "on" : "off", value);
468 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
469 		seq_printf(s, "3G status:    %s (%lu)\n", value ? "on" : "off", value);
470 
471 	seq_puts(s, "=====================\n");
472 
473 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
474 		seq_printf(s, "Touchpad status: %s (%lu)\n", value ? "on" : "off", value);
475 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
476 		seq_printf(s, "Camera status:   %s (%lu)\n", value ? "on" : "off", value);
477 
478 	seq_puts(s, "=====================\n");
479 
480 	if (!eval_gbmd(priv->adev->handle, &value))
481 		seq_printf(s, "GBMD: %#010lx\n", value);
482 	if (!eval_hals(priv->adev->handle, &value))
483 		seq_printf(s, "HALS: %#010lx\n", value);
484 
485 	return 0;
486 }
487 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
488 
debugfs_cfg_show(struct seq_file * s,void * data)489 static int debugfs_cfg_show(struct seq_file *s, void *data)
490 {
491 	struct ideapad_private *priv = s->private;
492 
493 	seq_printf(s, "_CFG: %#010lx\n\n", priv->cfg);
494 
495 	seq_puts(s, "Capabilities:");
496 	if (test_bit(CFG_CAP_BT_BIT, &priv->cfg))
497 		seq_puts(s, " bluetooth");
498 	if (test_bit(CFG_CAP_3G_BIT, &priv->cfg))
499 		seq_puts(s, " 3G");
500 	if (test_bit(CFG_CAP_WIFI_BIT, &priv->cfg))
501 		seq_puts(s, " wifi");
502 	if (test_bit(CFG_CAP_CAM_BIT, &priv->cfg))
503 		seq_puts(s, " camera");
504 	seq_puts(s, "\n");
505 
506 	seq_puts(s, "OSD support:");
507 	if (test_bit(CFG_OSD_NUMLK_BIT, &priv->cfg))
508 		seq_puts(s, " num-lock");
509 	if (test_bit(CFG_OSD_CAPSLK_BIT, &priv->cfg))
510 		seq_puts(s, " caps-lock");
511 	if (test_bit(CFG_OSD_MICMUTE_BIT, &priv->cfg))
512 		seq_puts(s, " mic-mute");
513 	if (test_bit(CFG_OSD_TOUCHPAD_BIT, &priv->cfg))
514 		seq_puts(s, " touchpad");
515 	if (test_bit(CFG_OSD_CAM_BIT, &priv->cfg))
516 		seq_puts(s, " camera");
517 	seq_puts(s, "\n");
518 
519 	seq_puts(s, "Graphics: ");
520 	switch (priv->cfg & 0x700) {
521 	case 0x100:
522 		seq_puts(s, "Intel");
523 		break;
524 	case 0x200:
525 		seq_puts(s, "ATI");
526 		break;
527 	case 0x300:
528 		seq_puts(s, "Nvidia");
529 		break;
530 	case 0x400:
531 		seq_puts(s, "Intel and ATI");
532 		break;
533 	case 0x500:
534 		seq_puts(s, "Intel and Nvidia");
535 		break;
536 	}
537 	seq_puts(s, "\n");
538 
539 	return 0;
540 }
541 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
542 
ideapad_debugfs_init(struct ideapad_private * priv)543 static void ideapad_debugfs_init(struct ideapad_private *priv)
544 {
545 	struct dentry *dir;
546 
547 	dir = debugfs_create_dir("ideapad", NULL);
548 	priv->debug = dir;
549 
550 	debugfs_create_file("cfg", 0444, dir, priv, &debugfs_cfg_fops);
551 	debugfs_create_file("status", 0444, dir, priv, &debugfs_status_fops);
552 }
553 
ideapad_debugfs_exit(struct ideapad_private * priv)554 static void ideapad_debugfs_exit(struct ideapad_private *priv)
555 {
556 	debugfs_remove_recursive(priv->debug);
557 	priv->debug = NULL;
558 }
559 
560 /*
561  * sysfs
562  */
camera_power_show(struct device * dev,struct device_attribute * attr,char * buf)563 static ssize_t camera_power_show(struct device *dev,
564 				 struct device_attribute *attr,
565 				 char *buf)
566 {
567 	struct ideapad_private *priv = dev_get_drvdata(dev);
568 	unsigned long result;
569 	int err;
570 
571 	err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result);
572 	if (err)
573 		return err;
574 
575 	return sysfs_emit(buf, "%d\n", !!result);
576 }
577 
camera_power_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)578 static ssize_t camera_power_store(struct device *dev,
579 				  struct device_attribute *attr,
580 				  const char *buf, size_t count)
581 {
582 	struct ideapad_private *priv = dev_get_drvdata(dev);
583 	bool state;
584 	int err;
585 
586 	err = kstrtobool(buf, &state);
587 	if (err)
588 		return err;
589 
590 	err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
591 	if (err)
592 		return err;
593 
594 	return count;
595 }
596 
597 static DEVICE_ATTR_RW(camera_power);
598 
conservation_mode_show(struct device * dev,struct device_attribute * attr,char * buf)599 static ssize_t conservation_mode_show(struct device *dev,
600 				      struct device_attribute *attr,
601 				      char *buf)
602 {
603 	struct ideapad_private *priv = dev_get_drvdata(dev);
604 	unsigned long result;
605 	int err;
606 
607 	err = eval_gbmd(priv->adev->handle, &result);
608 	if (err)
609 		return err;
610 
611 	return sysfs_emit(buf, "%d\n", !!test_bit(GBMD_CONSERVATION_STATE_BIT, &result));
612 }
613 
conservation_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)614 static ssize_t conservation_mode_store(struct device *dev,
615 				       struct device_attribute *attr,
616 				       const char *buf, size_t count)
617 {
618 	struct ideapad_private *priv = dev_get_drvdata(dev);
619 	bool state;
620 	int err;
621 
622 	err = kstrtobool(buf, &state);
623 	if (err)
624 		return err;
625 
626 	err = exec_sbmc(priv->adev->handle, state ? SBMC_CONSERVATION_ON : SBMC_CONSERVATION_OFF);
627 	if (err)
628 		return err;
629 
630 	return count;
631 }
632 
633 static DEVICE_ATTR_RW(conservation_mode);
634 
fan_mode_show(struct device * dev,struct device_attribute * attr,char * buf)635 static ssize_t fan_mode_show(struct device *dev,
636 			     struct device_attribute *attr,
637 			     char *buf)
638 {
639 	struct ideapad_private *priv = dev_get_drvdata(dev);
640 	unsigned long result;
641 	int err;
642 
643 	err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result);
644 	if (err)
645 		return err;
646 
647 	return sysfs_emit(buf, "%lu\n", result);
648 }
649 
fan_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)650 static ssize_t fan_mode_store(struct device *dev,
651 			      struct device_attribute *attr,
652 			      const char *buf, size_t count)
653 {
654 	struct ideapad_private *priv = dev_get_drvdata(dev);
655 	unsigned int state;
656 	int err;
657 
658 	err = kstrtouint(buf, 0, &state);
659 	if (err)
660 		return err;
661 
662 	if (state > 4 || state == 3)
663 		return -EINVAL;
664 
665 	err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
666 	if (err)
667 		return err;
668 
669 	return count;
670 }
671 
672 static DEVICE_ATTR_RW(fan_mode);
673 
fn_lock_show(struct device * dev,struct device_attribute * attr,char * buf)674 static ssize_t fn_lock_show(struct device *dev,
675 			    struct device_attribute *attr,
676 			    char *buf)
677 {
678 	struct ideapad_private *priv = dev_get_drvdata(dev);
679 	unsigned long hals;
680 	int err;
681 
682 	err = eval_hals(priv->adev->handle, &hals);
683 	if (err)
684 		return err;
685 
686 	return sysfs_emit(buf, "%d\n", !!test_bit(HALS_FNLOCK_STATE_BIT, &hals));
687 }
688 
fn_lock_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)689 static ssize_t fn_lock_store(struct device *dev,
690 			     struct device_attribute *attr,
691 			     const char *buf, size_t count)
692 {
693 	struct ideapad_private *priv = dev_get_drvdata(dev);
694 	bool state;
695 	int err;
696 
697 	err = kstrtobool(buf, &state);
698 	if (err)
699 		return err;
700 
701 	err = exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
702 	if (err)
703 		return err;
704 
705 	return count;
706 }
707 
708 static DEVICE_ATTR_RW(fn_lock);
709 
touchpad_show(struct device * dev,struct device_attribute * attr,char * buf)710 static ssize_t touchpad_show(struct device *dev,
711 			     struct device_attribute *attr,
712 			     char *buf)
713 {
714 	struct ideapad_private *priv = dev_get_drvdata(dev);
715 	unsigned long result;
716 	int err;
717 
718 	err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result);
719 	if (err)
720 		return err;
721 
722 	priv->r_touchpad_val = result;
723 
724 	return sysfs_emit(buf, "%d\n", !!result);
725 }
726 
touchpad_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)727 static ssize_t touchpad_store(struct device *dev,
728 			      struct device_attribute *attr,
729 			      const char *buf, size_t count)
730 {
731 	struct ideapad_private *priv = dev_get_drvdata(dev);
732 	bool state;
733 	int err;
734 
735 	err = kstrtobool(buf, &state);
736 	if (err)
737 		return err;
738 
739 	err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
740 	if (err)
741 		return err;
742 
743 	priv->r_touchpad_val = state;
744 
745 	return count;
746 }
747 
748 static DEVICE_ATTR_RW(touchpad);
749 
usb_charging_show(struct device * dev,struct device_attribute * attr,char * buf)750 static ssize_t usb_charging_show(struct device *dev,
751 				 struct device_attribute *attr,
752 				 char *buf)
753 {
754 	struct ideapad_private *priv = dev_get_drvdata(dev);
755 	unsigned long hals;
756 	int err;
757 
758 	err = eval_hals(priv->adev->handle, &hals);
759 	if (err)
760 		return err;
761 
762 	return sysfs_emit(buf, "%d\n", !!test_bit(HALS_USB_CHARGING_STATE_BIT, &hals));
763 }
764 
usb_charging_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)765 static ssize_t usb_charging_store(struct device *dev,
766 				  struct device_attribute *attr,
767 				  const char *buf, size_t count)
768 {
769 	struct ideapad_private *priv = dev_get_drvdata(dev);
770 	bool state;
771 	int err;
772 
773 	err = kstrtobool(buf, &state);
774 	if (err)
775 		return err;
776 
777 	err = exec_sals(priv->adev->handle, state ? SALS_USB_CHARGING_ON : SALS_USB_CHARGING_OFF);
778 	if (err)
779 		return err;
780 
781 	return count;
782 }
783 
784 static DEVICE_ATTR_RW(usb_charging);
785 
786 static struct attribute *ideapad_attributes[] = {
787 	&dev_attr_camera_power.attr,
788 	&dev_attr_conservation_mode.attr,
789 	&dev_attr_fan_mode.attr,
790 	&dev_attr_fn_lock.attr,
791 	&dev_attr_touchpad.attr,
792 	&dev_attr_usb_charging.attr,
793 	NULL
794 };
795 
ideapad_is_visible(struct kobject * kobj,struct attribute * attr,int idx)796 static umode_t ideapad_is_visible(struct kobject *kobj,
797 				  struct attribute *attr,
798 				  int idx)
799 {
800 	struct device *dev = kobj_to_dev(kobj);
801 	struct ideapad_private *priv = dev_get_drvdata(dev);
802 	bool supported = true;
803 
804 	if (attr == &dev_attr_camera_power.attr)
805 		supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg);
806 	else if (attr == &dev_attr_conservation_mode.attr)
807 		supported = priv->features.conservation_mode;
808 	else if (attr == &dev_attr_fan_mode.attr)
809 		supported = priv->features.fan_mode;
810 	else if (attr == &dev_attr_fn_lock.attr)
811 		supported = priv->features.fn_lock;
812 	else if (attr == &dev_attr_touchpad.attr)
813 		supported = priv->features.touchpad_ctrl_via_ec;
814 	else if (attr == &dev_attr_usb_charging.attr)
815 		supported = priv->features.usb_charging;
816 
817 	return supported ? attr->mode : 0;
818 }
819 
820 static const struct attribute_group ideapad_attribute_group = {
821 	.is_visible = ideapad_is_visible,
822 	.attrs = ideapad_attributes
823 };
824 
825 /*
826  * DYTC Platform profile
827  */
828 #define DYTC_CMD_QUERY        0 /* To get DYTC status - enable/revision */
829 #define DYTC_CMD_SET          1 /* To enable/disable IC function mode */
830 #define DYTC_CMD_GET          2 /* To get current IC function and mode */
831 #define DYTC_CMD_RESET    0x1ff /* To reset back to default */
832 
833 #define DYTC_QUERY_ENABLE_BIT 8  /* Bit        8 - 0 = disabled, 1 = enabled */
834 #define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
835 #define DYTC_QUERY_REV_BIT    28 /* Bits 28 - 31 - revision */
836 
837 #define DYTC_GET_FUNCTION_BIT 8  /* Bits  8-11 - function setting */
838 #define DYTC_GET_MODE_BIT     12 /* Bits 12-15 - mode setting */
839 
840 #define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - function setting */
841 #define DYTC_SET_MODE_BIT     16 /* Bits 16-19 - mode setting */
842 #define DYTC_SET_VALID_BIT    20 /* Bit     20 - 1 = on, 0 = off */
843 
844 #define DYTC_FUNCTION_STD     0  /* Function = 0, standard mode */
845 #define DYTC_FUNCTION_CQL     1  /* Function = 1, lap mode */
846 #define DYTC_FUNCTION_MMC     11 /* Function = 11, desk mode */
847 
848 #define DYTC_MODE_PERFORM     2  /* High power mode aka performance */
849 #define DYTC_MODE_LOW_POWER       3  /* Low power mode aka quiet */
850 #define DYTC_MODE_BALANCE   0xF  /* Default mode aka balanced */
851 
852 #define DYTC_SET_COMMAND(function, mode, on) \
853 	(DYTC_CMD_SET | (function) << DYTC_SET_FUNCTION_BIT | \
854 	 (mode) << DYTC_SET_MODE_BIT | \
855 	 (on) << DYTC_SET_VALID_BIT)
856 
857 #define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0)
858 
859 #define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1)
860 
convert_dytc_to_profile(int dytcmode,enum platform_profile_option * profile)861 static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
862 {
863 	switch (dytcmode) {
864 	case DYTC_MODE_LOW_POWER:
865 		*profile = PLATFORM_PROFILE_LOW_POWER;
866 		break;
867 	case DYTC_MODE_BALANCE:
868 		*profile =  PLATFORM_PROFILE_BALANCED;
869 		break;
870 	case DYTC_MODE_PERFORM:
871 		*profile =  PLATFORM_PROFILE_PERFORMANCE;
872 		break;
873 	default: /* Unknown mode */
874 		return -EINVAL;
875 	}
876 
877 	return 0;
878 }
879 
convert_profile_to_dytc(enum platform_profile_option profile,int * perfmode)880 static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode)
881 {
882 	switch (profile) {
883 	case PLATFORM_PROFILE_LOW_POWER:
884 		*perfmode = DYTC_MODE_LOW_POWER;
885 		break;
886 	case PLATFORM_PROFILE_BALANCED:
887 		*perfmode = DYTC_MODE_BALANCE;
888 		break;
889 	case PLATFORM_PROFILE_PERFORMANCE:
890 		*perfmode = DYTC_MODE_PERFORM;
891 		break;
892 	default: /* Unknown profile */
893 		return -EOPNOTSUPP;
894 	}
895 
896 	return 0;
897 }
898 
899 /*
900  * dytc_profile_get: Function to register with platform_profile
901  * handler. Returns current platform profile.
902  */
dytc_profile_get(struct platform_profile_handler * pprof,enum platform_profile_option * profile)903 static int dytc_profile_get(struct platform_profile_handler *pprof,
904 			    enum platform_profile_option *profile)
905 {
906 	struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
907 
908 	*profile = dytc->current_profile;
909 	return 0;
910 }
911 
912 /*
913  * Helper function - check if we are in CQL mode and if we are
914  *  - disable CQL,
915  *  - run the command
916  *  - enable CQL
917  *  If not in CQL mode, just run the command
918  */
dytc_cql_command(struct ideapad_private * priv,unsigned long cmd,unsigned long * output)919 static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
920 			    unsigned long *output)
921 {
922 	int err, cmd_err, cur_funcmode;
923 
924 	/* Determine if we are in CQL mode. This alters the commands we do */
925 	err = eval_dytc(priv->adev->handle, DYTC_CMD_GET, output);
926 	if (err)
927 		return err;
928 
929 	cur_funcmode = (*output >> DYTC_GET_FUNCTION_BIT) & 0xF;
930 	/* Check if we're OK to return immediately */
931 	if (cmd == DYTC_CMD_GET && cur_funcmode != DYTC_FUNCTION_CQL)
932 		return 0;
933 
934 	if (cur_funcmode == DYTC_FUNCTION_CQL) {
935 		err = eval_dytc(priv->adev->handle, DYTC_DISABLE_CQL, NULL);
936 		if (err)
937 			return err;
938 	}
939 
940 	cmd_err = eval_dytc(priv->adev->handle, cmd, output);
941 	/* Check return condition after we've restored CQL state */
942 
943 	if (cur_funcmode == DYTC_FUNCTION_CQL) {
944 		err = eval_dytc(priv->adev->handle, DYTC_ENABLE_CQL, NULL);
945 		if (err)
946 			return err;
947 	}
948 
949 	return cmd_err;
950 }
951 
952 /*
953  * dytc_profile_set: Function to register with platform_profile
954  * handler. Sets current platform profile.
955  */
dytc_profile_set(struct platform_profile_handler * pprof,enum platform_profile_option profile)956 static int dytc_profile_set(struct platform_profile_handler *pprof,
957 			    enum platform_profile_option profile)
958 {
959 	struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
960 	struct ideapad_private *priv = dytc->priv;
961 	unsigned long output;
962 	int err;
963 
964 	err = mutex_lock_interruptible(&dytc->mutex);
965 	if (err)
966 		return err;
967 
968 	if (profile == PLATFORM_PROFILE_BALANCED) {
969 		/* To get back to balanced mode we just issue a reset command */
970 		err = eval_dytc(priv->adev->handle, DYTC_CMD_RESET, NULL);
971 		if (err)
972 			goto unlock;
973 	} else {
974 		int perfmode;
975 
976 		err = convert_profile_to_dytc(profile, &perfmode);
977 		if (err)
978 			goto unlock;
979 
980 		/* Determine if we are in CQL mode. This alters the commands we do */
981 		err = dytc_cql_command(priv, DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1),
982 				       &output);
983 		if (err)
984 			goto unlock;
985 	}
986 
987 	/* Success - update current profile */
988 	dytc->current_profile = profile;
989 
990 unlock:
991 	mutex_unlock(&dytc->mutex);
992 
993 	return err;
994 }
995 
dytc_profile_refresh(struct ideapad_private * priv)996 static void dytc_profile_refresh(struct ideapad_private *priv)
997 {
998 	enum platform_profile_option profile;
999 	unsigned long output;
1000 	int err, perfmode;
1001 
1002 	mutex_lock(&priv->dytc->mutex);
1003 	err = dytc_cql_command(priv, DYTC_CMD_GET, &output);
1004 	mutex_unlock(&priv->dytc->mutex);
1005 	if (err)
1006 		return;
1007 
1008 	perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
1009 
1010 	if (convert_dytc_to_profile(perfmode, &profile))
1011 		return;
1012 
1013 	if (profile != priv->dytc->current_profile) {
1014 		priv->dytc->current_profile = profile;
1015 		platform_profile_notify();
1016 	}
1017 }
1018 
1019 static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
1020 	{
1021 		/* Ideapad 5 Pro 16ACH6 */
1022 		.matches = {
1023 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1024 			DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
1025 		}
1026 	},
1027 	{
1028 		/* Ideapad 5 15ITL05 */
1029 		.matches = {
1030 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1031 			DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
1032 		}
1033 	},
1034 	{}
1035 };
1036 
ideapad_dytc_profile_init(struct ideapad_private * priv)1037 static int ideapad_dytc_profile_init(struct ideapad_private *priv)
1038 {
1039 	int err, dytc_version;
1040 	unsigned long output;
1041 
1042 	if (!priv->features.dytc)
1043 		return -ENODEV;
1044 
1045 	err = eval_dytc(priv->adev->handle, DYTC_CMD_QUERY, &output);
1046 	/* For all other errors we can flag the failure */
1047 	if (err)
1048 		return err;
1049 
1050 	/* Check DYTC is enabled and supports mode setting */
1051 	if (!test_bit(DYTC_QUERY_ENABLE_BIT, &output)) {
1052 		dev_info(&priv->platform_device->dev, "DYTC_QUERY_ENABLE_BIT returned false\n");
1053 		return -ENODEV;
1054 	}
1055 
1056 	dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
1057 
1058 	if (dytc_version < 4) {
1059 		dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
1060 		return -ENODEV;
1061 	}
1062 
1063 	if (dytc_version < 5 &&
1064 	    !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
1065 		dev_info(&priv->platform_device->dev,
1066 			 "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
1067 		return -ENODEV;
1068 	}
1069 
1070 	priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
1071 	if (!priv->dytc)
1072 		return -ENOMEM;
1073 
1074 	mutex_init(&priv->dytc->mutex);
1075 
1076 	priv->dytc->priv = priv;
1077 	priv->dytc->pprof.profile_get = dytc_profile_get;
1078 	priv->dytc->pprof.profile_set = dytc_profile_set;
1079 
1080 	/* Setup supported modes */
1081 	set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
1082 	set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
1083 	set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
1084 
1085 	/* Create platform_profile structure and register */
1086 	err = platform_profile_register(&priv->dytc->pprof);
1087 	if (err)
1088 		goto pp_reg_failed;
1089 
1090 	/* Ensure initial values are correct */
1091 	dytc_profile_refresh(priv);
1092 
1093 	return 0;
1094 
1095 pp_reg_failed:
1096 	mutex_destroy(&priv->dytc->mutex);
1097 	kfree(priv->dytc);
1098 	priv->dytc = NULL;
1099 
1100 	return err;
1101 }
1102 
ideapad_dytc_profile_exit(struct ideapad_private * priv)1103 static void ideapad_dytc_profile_exit(struct ideapad_private *priv)
1104 {
1105 	if (!priv->dytc)
1106 		return;
1107 
1108 	platform_profile_remove();
1109 	mutex_destroy(&priv->dytc->mutex);
1110 	kfree(priv->dytc);
1111 
1112 	priv->dytc = NULL;
1113 }
1114 
1115 /*
1116  * Rfkill
1117  */
1118 struct ideapad_rfk_data {
1119 	char *name;
1120 	int cfgbit;
1121 	int opcode;
1122 	int type;
1123 };
1124 
1125 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
1126 	{ "ideapad_wlan",      CFG_CAP_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
1127 	{ "ideapad_bluetooth", CFG_CAP_BT_BIT,   VPCCMD_W_BT,   RFKILL_TYPE_BLUETOOTH },
1128 	{ "ideapad_3g",        CFG_CAP_3G_BIT,   VPCCMD_W_3G,   RFKILL_TYPE_WWAN },
1129 };
1130 
ideapad_rfk_set(void * data,bool blocked)1131 static int ideapad_rfk_set(void *data, bool blocked)
1132 {
1133 	struct ideapad_rfk_priv *priv = data;
1134 	int opcode = ideapad_rfk_data[priv->dev].opcode;
1135 
1136 	return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
1137 }
1138 
1139 static const struct rfkill_ops ideapad_rfk_ops = {
1140 	.set_block = ideapad_rfk_set,
1141 };
1142 
ideapad_sync_rfk_state(struct ideapad_private * priv)1143 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
1144 {
1145 	unsigned long hw_blocked = 0;
1146 	int i;
1147 
1148 	if (priv->features.hw_rfkill_switch) {
1149 		if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
1150 			return;
1151 		hw_blocked = !hw_blocked;
1152 	}
1153 
1154 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1155 		if (priv->rfk[i])
1156 			rfkill_set_hw_state(priv->rfk[i], hw_blocked);
1157 }
1158 
ideapad_register_rfkill(struct ideapad_private * priv,int dev)1159 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
1160 {
1161 	unsigned long rf_enabled;
1162 	int err;
1163 
1164 	if (no_bt_rfkill && ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH) {
1165 		/* Force to enable bluetooth when no_bt_rfkill=1 */
1166 		write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1);
1167 		return 0;
1168 	}
1169 
1170 	priv->rfk_priv[dev].dev = dev;
1171 	priv->rfk_priv[dev].priv = priv;
1172 
1173 	priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
1174 				      &priv->platform_device->dev,
1175 				      ideapad_rfk_data[dev].type,
1176 				      &ideapad_rfk_ops,
1177 				      &priv->rfk_priv[dev]);
1178 	if (!priv->rfk[dev])
1179 		return -ENOMEM;
1180 
1181 	err = read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode - 1, &rf_enabled);
1182 	if (err)
1183 		rf_enabled = 1;
1184 
1185 	rfkill_init_sw_state(priv->rfk[dev], !rf_enabled);
1186 
1187 	err = rfkill_register(priv->rfk[dev]);
1188 	if (err)
1189 		rfkill_destroy(priv->rfk[dev]);
1190 
1191 	return err;
1192 }
1193 
ideapad_unregister_rfkill(struct ideapad_private * priv,int dev)1194 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
1195 {
1196 	if (!priv->rfk[dev])
1197 		return;
1198 
1199 	rfkill_unregister(priv->rfk[dev]);
1200 	rfkill_destroy(priv->rfk[dev]);
1201 }
1202 
1203 /*
1204  * Platform device
1205  */
ideapad_sysfs_init(struct ideapad_private * priv)1206 static int ideapad_sysfs_init(struct ideapad_private *priv)
1207 {
1208 	return device_add_group(&priv->platform_device->dev,
1209 				&ideapad_attribute_group);
1210 }
1211 
ideapad_sysfs_exit(struct ideapad_private * priv)1212 static void ideapad_sysfs_exit(struct ideapad_private *priv)
1213 {
1214 	device_remove_group(&priv->platform_device->dev,
1215 			    &ideapad_attribute_group);
1216 }
1217 
1218 /*
1219  * input device
1220  */
1221 #define IDEAPAD_WMI_KEY 0x100
1222 
1223 static const struct key_entry ideapad_keymap[] = {
1224 	{ KE_KEY,   6, { KEY_SWITCHVIDEOMODE } },
1225 	{ KE_KEY,   7, { KEY_CAMERA } },
1226 	{ KE_KEY,   8, { KEY_MICMUTE } },
1227 	{ KE_KEY,  11, { KEY_F16 } },
1228 	{ KE_KEY,  13, { KEY_WLAN } },
1229 	{ KE_KEY,  16, { KEY_PROG1 } },
1230 	{ KE_KEY,  17, { KEY_PROG2 } },
1231 	{ KE_KEY,  64, { KEY_PROG3 } },
1232 	{ KE_KEY,  65, { KEY_PROG4 } },
1233 	{ KE_KEY,  66, { KEY_TOUCHPAD_OFF } },
1234 	{ KE_KEY,  67, { KEY_TOUCHPAD_ON } },
1235 	{ KE_KEY, 128, { KEY_ESC } },
1236 
1237 	/*
1238 	 * WMI keys
1239 	 */
1240 
1241 	/* FnLock (handled by the firmware) */
1242 	{ KE_IGNORE,	0x02 | IDEAPAD_WMI_KEY },
1243 	/* Esc (handled by the firmware) */
1244 	{ KE_IGNORE,	0x03 | IDEAPAD_WMI_KEY },
1245 	/* Customizable Lenovo Hotkey ("star" with 'S' inside) */
1246 	{ KE_KEY,	0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
1247 	{ KE_KEY,	0x04 | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
1248 	/* Lenovo Support */
1249 	{ KE_KEY,	0x07 | IDEAPAD_WMI_KEY, { KEY_HELP } },
1250 	{ KE_KEY,	0x0e | IDEAPAD_WMI_KEY, { KEY_PICKUP_PHONE } },
1251 	{ KE_KEY,	0x0f | IDEAPAD_WMI_KEY, { KEY_HANGUP_PHONE } },
1252 	/* Dark mode toggle */
1253 	{ KE_KEY,	0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
1254 	/* Sound profile switch */
1255 	{ KE_KEY,	0x12 | IDEAPAD_WMI_KEY, { KEY_PROG2 } },
1256 	/* Lenovo Virtual Background application */
1257 	{ KE_KEY,	0x28 | IDEAPAD_WMI_KEY, { KEY_PROG3 } },
1258 	/* Lenovo Support */
1259 	{ KE_KEY,	0x27 | IDEAPAD_WMI_KEY, { KEY_HELP } },
1260 	/* Refresh Rate Toggle */
1261 	{ KE_KEY,	0x0a | IDEAPAD_WMI_KEY, { KEY_DISPLAYTOGGLE } },
1262 	/* Specific to some newer models */
1263 	{ KE_KEY,	0x3e | IDEAPAD_WMI_KEY, { KEY_MICMUTE } },
1264 	{ KE_KEY,	0x3f | IDEAPAD_WMI_KEY, { KEY_RFKILL } },
1265 
1266 	{ KE_END },
1267 };
1268 
ideapad_input_init(struct ideapad_private * priv)1269 static int ideapad_input_init(struct ideapad_private *priv)
1270 {
1271 	struct input_dev *inputdev;
1272 	int err;
1273 
1274 	inputdev = input_allocate_device();
1275 	if (!inputdev)
1276 		return -ENOMEM;
1277 
1278 	inputdev->name = "Ideapad extra buttons";
1279 	inputdev->phys = "ideapad/input0";
1280 	inputdev->id.bustype = BUS_HOST;
1281 	inputdev->dev.parent = &priv->platform_device->dev;
1282 
1283 	err = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
1284 	if (err) {
1285 		dev_err(&priv->platform_device->dev,
1286 			"Could not set up input device keymap: %d\n", err);
1287 		goto err_free_dev;
1288 	}
1289 
1290 	err = input_register_device(inputdev);
1291 	if (err) {
1292 		dev_err(&priv->platform_device->dev,
1293 			"Could not register input device: %d\n", err);
1294 		goto err_free_dev;
1295 	}
1296 
1297 	priv->inputdev = inputdev;
1298 
1299 	return 0;
1300 
1301 err_free_dev:
1302 	input_free_device(inputdev);
1303 
1304 	return err;
1305 }
1306 
ideapad_input_exit(struct ideapad_private * priv)1307 static void ideapad_input_exit(struct ideapad_private *priv)
1308 {
1309 	input_unregister_device(priv->inputdev);
1310 	priv->inputdev = NULL;
1311 }
1312 
ideapad_input_report(struct ideapad_private * priv,unsigned long scancode)1313 static void ideapad_input_report(struct ideapad_private *priv,
1314 				 unsigned long scancode)
1315 {
1316 	sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
1317 }
1318 
ideapad_input_novokey(struct ideapad_private * priv)1319 static void ideapad_input_novokey(struct ideapad_private *priv)
1320 {
1321 	unsigned long long_pressed;
1322 
1323 	if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
1324 		return;
1325 
1326 	if (long_pressed)
1327 		ideapad_input_report(priv, 17);
1328 	else
1329 		ideapad_input_report(priv, 16);
1330 }
1331 
ideapad_check_special_buttons(struct ideapad_private * priv)1332 static void ideapad_check_special_buttons(struct ideapad_private *priv)
1333 {
1334 	unsigned long bit, value;
1335 
1336 	if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value))
1337 		return;
1338 
1339 	for_each_set_bit (bit, &value, 16) {
1340 		switch (bit) {
1341 		case 6:	/* Z570 */
1342 		case 0:	/* Z580 */
1343 			/* Thermal Management button */
1344 			ideapad_input_report(priv, 65);
1345 			break;
1346 		case 1:
1347 			/* OneKey Theater button */
1348 			ideapad_input_report(priv, 64);
1349 			break;
1350 		default:
1351 			dev_info(&priv->platform_device->dev,
1352 				 "Unknown special button: %lu\n", bit);
1353 			break;
1354 		}
1355 	}
1356 }
1357 
1358 /*
1359  * backlight
1360  */
ideapad_backlight_get_brightness(struct backlight_device * blightdev)1361 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
1362 {
1363 	struct ideapad_private *priv = bl_get_data(blightdev);
1364 	unsigned long now;
1365 	int err;
1366 
1367 	err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1368 	if (err)
1369 		return err;
1370 
1371 	return now;
1372 }
1373 
ideapad_backlight_update_status(struct backlight_device * blightdev)1374 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
1375 {
1376 	struct ideapad_private *priv = bl_get_data(blightdev);
1377 	int err;
1378 
1379 	err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
1380 			   blightdev->props.brightness);
1381 	if (err)
1382 		return err;
1383 
1384 	err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
1385 			   blightdev->props.power != FB_BLANK_POWERDOWN);
1386 	if (err)
1387 		return err;
1388 
1389 	return 0;
1390 }
1391 
1392 static const struct backlight_ops ideapad_backlight_ops = {
1393 	.get_brightness = ideapad_backlight_get_brightness,
1394 	.update_status = ideapad_backlight_update_status,
1395 };
1396 
ideapad_backlight_init(struct ideapad_private * priv)1397 static int ideapad_backlight_init(struct ideapad_private *priv)
1398 {
1399 	struct backlight_device *blightdev;
1400 	struct backlight_properties props;
1401 	unsigned long max, now, power;
1402 	int err;
1403 
1404 	err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max);
1405 	if (err)
1406 		return err;
1407 
1408 	err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1409 	if (err)
1410 		return err;
1411 
1412 	err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power);
1413 	if (err)
1414 		return err;
1415 
1416 	memset(&props, 0, sizeof(props));
1417 
1418 	props.max_brightness = max;
1419 	props.type = BACKLIGHT_PLATFORM;
1420 
1421 	blightdev = backlight_device_register("ideapad",
1422 					      &priv->platform_device->dev,
1423 					      priv,
1424 					      &ideapad_backlight_ops,
1425 					      &props);
1426 	if (IS_ERR(blightdev)) {
1427 		err = PTR_ERR(blightdev);
1428 		dev_err(&priv->platform_device->dev,
1429 			"Could not register backlight device: %d\n", err);
1430 		return err;
1431 	}
1432 
1433 	priv->blightdev = blightdev;
1434 	blightdev->props.brightness = now;
1435 	blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1436 
1437 	backlight_update_status(blightdev);
1438 
1439 	return 0;
1440 }
1441 
ideapad_backlight_exit(struct ideapad_private * priv)1442 static void ideapad_backlight_exit(struct ideapad_private *priv)
1443 {
1444 	backlight_device_unregister(priv->blightdev);
1445 	priv->blightdev = NULL;
1446 }
1447 
ideapad_backlight_notify_power(struct ideapad_private * priv)1448 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
1449 {
1450 	struct backlight_device *blightdev = priv->blightdev;
1451 	unsigned long power;
1452 
1453 	if (!blightdev)
1454 		return;
1455 
1456 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
1457 		return;
1458 
1459 	blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1460 }
1461 
ideapad_backlight_notify_brightness(struct ideapad_private * priv)1462 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
1463 {
1464 	unsigned long now;
1465 
1466 	/* if we control brightness via acpi video driver */
1467 	if (!priv->blightdev)
1468 		read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1469 	else
1470 		backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
1471 }
1472 
1473 /*
1474  * keyboard backlight
1475  */
ideapad_kbd_bl_check_tristate(int type)1476 static int ideapad_kbd_bl_check_tristate(int type)
1477 {
1478 	return (type == KBD_BL_TRISTATE) || (type == KBD_BL_TRISTATE_AUTO);
1479 }
1480 
ideapad_kbd_bl_brightness_get(struct ideapad_private * priv)1481 static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv)
1482 {
1483 	unsigned long value;
1484 	int err;
1485 
1486 	if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) {
1487 		err = eval_kblc(priv->adev->handle,
1488 				FIELD_PREP(KBD_BL_COMMAND_TYPE, priv->kbd_bl.type) |
1489 				KBD_BL_COMMAND_GET,
1490 				&value);
1491 
1492 		if (err)
1493 			return err;
1494 
1495 		/* Convert returned value to brightness level */
1496 		value = FIELD_GET(KBD_BL_GET_BRIGHTNESS, value);
1497 
1498 		/* Off, low or high */
1499 		if (value <= priv->kbd_bl.led.max_brightness)
1500 			return value;
1501 
1502 		/* Auto, report as off */
1503 		if (value == priv->kbd_bl.led.max_brightness + 1)
1504 			return 0;
1505 
1506 		/* Unknown value */
1507 		dev_warn(&priv->platform_device->dev,
1508 			 "Unknown keyboard backlight value: %lu", value);
1509 		return -EINVAL;
1510 	}
1511 
1512 	err = eval_hals(priv->adev->handle, &value);
1513 	if (err)
1514 		return err;
1515 
1516 	return !!test_bit(HALS_KBD_BL_STATE_BIT, &value);
1517 }
1518 
ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev * led_cdev)1519 static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev)
1520 {
1521 	struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1522 
1523 	return ideapad_kbd_bl_brightness_get(priv);
1524 }
1525 
ideapad_kbd_bl_brightness_set(struct ideapad_private * priv,unsigned int brightness)1526 static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness)
1527 {
1528 	int err;
1529 	unsigned long value;
1530 	int type = priv->kbd_bl.type;
1531 
1532 	if (ideapad_kbd_bl_check_tristate(type)) {
1533 		if (brightness > priv->kbd_bl.led.max_brightness)
1534 			return -EINVAL;
1535 
1536 		value = FIELD_PREP(KBD_BL_SET_BRIGHTNESS, brightness) |
1537 			FIELD_PREP(KBD_BL_COMMAND_TYPE, type) |
1538 			KBD_BL_COMMAND_SET;
1539 		err = exec_kblc(priv->adev->handle, value);
1540 	} else {
1541 		err = exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF);
1542 	}
1543 
1544 	if (err)
1545 		return err;
1546 
1547 	priv->kbd_bl.last_brightness = brightness;
1548 
1549 	return 0;
1550 }
1551 
ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1552 static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev,
1553 						  enum led_brightness brightness)
1554 {
1555 	struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1556 
1557 	return ideapad_kbd_bl_brightness_set(priv, brightness);
1558 }
1559 
ideapad_kbd_bl_notify(struct ideapad_private * priv)1560 static void ideapad_kbd_bl_notify(struct ideapad_private *priv)
1561 {
1562 	int brightness;
1563 
1564 	if (!priv->kbd_bl.initialized)
1565 		return;
1566 
1567 	brightness = ideapad_kbd_bl_brightness_get(priv);
1568 	if (brightness < 0)
1569 		return;
1570 
1571 	if (brightness == priv->kbd_bl.last_brightness)
1572 		return;
1573 
1574 	priv->kbd_bl.last_brightness = brightness;
1575 
1576 	led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness);
1577 }
1578 
ideapad_kbd_bl_init(struct ideapad_private * priv)1579 static int ideapad_kbd_bl_init(struct ideapad_private *priv)
1580 {
1581 	int brightness, err;
1582 
1583 	if (!priv->features.kbd_bl)
1584 		return -ENODEV;
1585 
1586 	if (WARN_ON(priv->kbd_bl.initialized))
1587 		return -EEXIST;
1588 
1589 	if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) {
1590 		priv->kbd_bl.led.max_brightness = 2;
1591 	} else {
1592 		priv->kbd_bl.led.max_brightness = 1;
1593 	}
1594 
1595 	brightness = ideapad_kbd_bl_brightness_get(priv);
1596 	if (brightness < 0)
1597 		return brightness;
1598 
1599 	priv->kbd_bl.last_brightness = brightness;
1600 	priv->kbd_bl.led.name                    = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
1601 	priv->kbd_bl.led.brightness_get          = ideapad_kbd_bl_led_cdev_brightness_get;
1602 	priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
1603 	priv->kbd_bl.led.flags                   = LED_BRIGHT_HW_CHANGED;
1604 
1605 	err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led);
1606 	if (err)
1607 		return err;
1608 
1609 	priv->kbd_bl.initialized = true;
1610 
1611 	return 0;
1612 }
1613 
ideapad_kbd_bl_exit(struct ideapad_private * priv)1614 static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
1615 {
1616 	if (!priv->kbd_bl.initialized)
1617 		return;
1618 
1619 	priv->kbd_bl.initialized = false;
1620 
1621 	led_classdev_unregister(&priv->kbd_bl.led);
1622 }
1623 
1624 /*
1625  * module init/exit
1626  */
ideapad_sync_touchpad_state(struct ideapad_private * priv,bool send_events)1627 static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_events)
1628 {
1629 	unsigned long value;
1630 	unsigned char param;
1631 	int ret;
1632 
1633 	/* Without reading from EC touchpad LED doesn't switch state */
1634 	ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value);
1635 	if (ret)
1636 		return;
1637 
1638 	/*
1639 	 * Some IdeaPads don't really turn off touchpad - they only
1640 	 * switch the LED state. We (de)activate KBC AUX port to turn
1641 	 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
1642 	 * KEY_TOUCHPAD_ON to not to get out of sync with LED
1643 	 */
1644 	if (priv->features.ctrl_ps2_aux_port)
1645 		i8042_command(&param, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
1646 
1647 	/*
1648 	 * On older models the EC controls the touchpad and toggles it on/off
1649 	 * itself, in this case we report KEY_TOUCHPAD_ON/_OFF. Some models do
1650 	 * an acpi-notify with VPC bit 5 set on resume, so this function get
1651 	 * called with send_events=true on every resume. Therefor if the EC did
1652 	 * not toggle, do nothing to avoid sending spurious KEY_TOUCHPAD_TOGGLE.
1653 	 */
1654 	if (send_events && value != priv->r_touchpad_val) {
1655 		ideapad_input_report(priv, value ? 67 : 66);
1656 		sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
1657 	}
1658 
1659 	priv->r_touchpad_val = value;
1660 }
1661 
1662 static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] = {
1663 	{
1664 		/* Lenovo Yoga 7 14ARB7 */
1665 		.matches = {
1666 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1667 			DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
1668 		},
1669 	},
1670 	{
1671 		/* Lenovo Yoga 7 14ACN6 */
1672 		.matches = {
1673 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1674 			DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
1675 		},
1676 	},
1677 	{ }
1678 };
1679 
ideapad_laptop_trigger_ec(void)1680 static void ideapad_laptop_trigger_ec(void)
1681 {
1682 	struct ideapad_private *priv;
1683 	int ret;
1684 
1685 	guard(mutex)(&ideapad_shared_mutex);
1686 
1687 	priv = ideapad_shared;
1688 	if (!priv)
1689 		return;
1690 
1691 	if (!priv->features.ymc_ec_trigger)
1692 		return;
1693 
1694 	ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1);
1695 	if (ret)
1696 		dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret);
1697 }
1698 
ideapad_laptop_nb_notify(struct notifier_block * nb,unsigned long action,void * data)1699 static int ideapad_laptop_nb_notify(struct notifier_block *nb,
1700 				    unsigned long action, void *data)
1701 {
1702 	switch (action) {
1703 	case IDEAPAD_LAPTOP_YMC_EVENT:
1704 		ideapad_laptop_trigger_ec();
1705 		break;
1706 	}
1707 
1708 	return 0;
1709 }
1710 
1711 static struct notifier_block ideapad_laptop_notifier = {
1712 	.notifier_call = ideapad_laptop_nb_notify,
1713 };
1714 
1715 static BLOCKING_NOTIFIER_HEAD(ideapad_laptop_chain_head);
1716 
ideapad_laptop_register_notifier(struct notifier_block * nb)1717 int ideapad_laptop_register_notifier(struct notifier_block *nb)
1718 {
1719 	return blocking_notifier_chain_register(&ideapad_laptop_chain_head, nb);
1720 }
1721 EXPORT_SYMBOL_NS_GPL(ideapad_laptop_register_notifier, IDEAPAD_LAPTOP);
1722 
ideapad_laptop_unregister_notifier(struct notifier_block * nb)1723 int ideapad_laptop_unregister_notifier(struct notifier_block *nb)
1724 {
1725 	return blocking_notifier_chain_unregister(&ideapad_laptop_chain_head, nb);
1726 }
1727 EXPORT_SYMBOL_NS_GPL(ideapad_laptop_unregister_notifier, IDEAPAD_LAPTOP);
1728 
ideapad_laptop_call_notifier(unsigned long action,void * data)1729 void ideapad_laptop_call_notifier(unsigned long action, void *data)
1730 {
1731 	blocking_notifier_call_chain(&ideapad_laptop_chain_head, action, data);
1732 }
1733 EXPORT_SYMBOL_NS_GPL(ideapad_laptop_call_notifier, IDEAPAD_LAPTOP);
1734 
ideapad_acpi_notify(acpi_handle handle,u32 event,void * data)1735 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
1736 {
1737 	struct ideapad_private *priv = data;
1738 	unsigned long vpc1, vpc2, bit;
1739 
1740 	if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
1741 		return;
1742 
1743 	if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
1744 		return;
1745 
1746 	vpc1 = (vpc2 << 8) | vpc1;
1747 
1748 	for_each_set_bit (bit, &vpc1, 16) {
1749 		switch (bit) {
1750 		case 13:
1751 		case 11:
1752 		case 8:
1753 		case 7:
1754 		case 6:
1755 			ideapad_input_report(priv, bit);
1756 			break;
1757 		case 10:
1758 			/*
1759 			 * This event gets send on a Yoga 300-11IBR when the EC
1760 			 * believes that the device has changed between laptop/
1761 			 * tent/stand/tablet mode. The EC relies on getting
1762 			 * angle info from 2 accelerometers through a special
1763 			 * windows service calling a DSM on the DUAL250E ACPI-
1764 			 * device. Linux does not do this, making the laptop/
1765 			 * tent/stand/tablet mode info unreliable, so we simply
1766 			 * ignore these events.
1767 			 */
1768 			break;
1769 		case 9:
1770 			ideapad_sync_rfk_state(priv);
1771 			break;
1772 		case 5:
1773 			ideapad_sync_touchpad_state(priv, true);
1774 			break;
1775 		case 4:
1776 			ideapad_backlight_notify_brightness(priv);
1777 			break;
1778 		case 3:
1779 			ideapad_input_novokey(priv);
1780 			break;
1781 		case 2:
1782 			ideapad_backlight_notify_power(priv);
1783 			break;
1784 		case KBD_BL_KBLC_CHANGED_EVENT:
1785 		case 1:
1786 			/*
1787 			 * Some IdeaPads report event 1 every ~20
1788 			 * seconds while on battery power; some
1789 			 * report this when changing to/from tablet
1790 			 * mode; some report this when the keyboard
1791 			 * backlight has changed.
1792 			 */
1793 			ideapad_kbd_bl_notify(priv);
1794 			break;
1795 		case 0:
1796 			ideapad_check_special_buttons(priv);
1797 			break;
1798 		default:
1799 			dev_info(&priv->platform_device->dev,
1800 				 "Unknown event: %lu\n", bit);
1801 		}
1802 	}
1803 }
1804 
1805 /* On some models we need to call exec_sals(SALS_FNLOCK_ON/OFF) to set the LED */
1806 static const struct dmi_system_id set_fn_lock_led_list[] = {
1807 	{
1808 		/* https://bugzilla.kernel.org/show_bug.cgi?id=212671 */
1809 		.matches = {
1810 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1811 			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion R7000P2020H"),
1812 		}
1813 	},
1814 	{
1815 		.matches = {
1816 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1817 			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion 5 15ARH05"),
1818 		}
1819 	},
1820 	{}
1821 };
1822 
1823 /*
1824  * Some ideapads have a hardware rfkill switch, but most do not have one.
1825  * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
1826  * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
1827  * There used to be a long list of DMI ids for models without a hw rfkill
1828  * switch here, but that resulted in playing whack a mole.
1829  * More importantly wrongly reporting the wifi radio as hw-blocked, results in
1830  * non working wifi. Whereas not reporting it hw-blocked, when it actually is
1831  * hw-blocked results in an empty SSID list, which is a much more benign
1832  * failure mode.
1833  * So the default now is the much safer option of assuming there is no
1834  * hardware rfkill switch. This default also actually matches most hardware,
1835  * since having a hw rfkill switch is quite rare on modern hardware, so this
1836  * also leads to a much shorter list.
1837  */
1838 static const struct dmi_system_id hw_rfkill_list[] = {
1839 	{}
1840 };
1841 
1842 /*
1843  * On some models the EC toggles the touchpad muted LED on touchpad toggle
1844  * hotkey presses, but the EC does not actually disable the touchpad itself.
1845  * On these models the driver needs to explicitly enable/disable the i8042
1846  * (PS/2) aux port.
1847  */
1848 static const struct dmi_system_id ctrl_ps2_aux_port_list[] = {
1849 	{
1850 	/* Lenovo Ideapad Z570 */
1851 	.matches = {
1852 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1853 		DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
1854 		},
1855 	},
1856 	{}
1857 };
1858 
ideapad_check_features(struct ideapad_private * priv)1859 static void ideapad_check_features(struct ideapad_private *priv)
1860 {
1861 	acpi_handle handle = priv->adev->handle;
1862 	unsigned long val;
1863 
1864 	priv->features.set_fn_lock_led =
1865 		set_fn_lock_led || dmi_check_system(set_fn_lock_led_list);
1866 	priv->features.hw_rfkill_switch =
1867 		hw_rfkill_switch || dmi_check_system(hw_rfkill_list);
1868 	priv->features.ctrl_ps2_aux_port =
1869 		ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list);
1870 	priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec;
1871 	priv->features.ymc_ec_trigger =
1872 		ymc_ec_trigger || dmi_check_system(ymc_ec_trigger_quirk_dmi_table);
1873 
1874 	if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
1875 		priv->features.fan_mode = true;
1876 
1877 	if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC"))
1878 		priv->features.conservation_mode = true;
1879 
1880 	if (acpi_has_method(handle, "DYTC"))
1881 		priv->features.dytc = true;
1882 
1883 	if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) {
1884 		if (!eval_hals(handle, &val)) {
1885 			if (test_bit(HALS_FNLOCK_SUPPORT_BIT, &val))
1886 				priv->features.fn_lock = true;
1887 
1888 			if (test_bit(HALS_KBD_BL_SUPPORT_BIT, &val)) {
1889 				priv->features.kbd_bl = true;
1890 				priv->kbd_bl.type = KBD_BL_STANDARD;
1891 			}
1892 
1893 			if (test_bit(HALS_USB_CHARGING_SUPPORT_BIT, &val))
1894 				priv->features.usb_charging = true;
1895 		}
1896 	}
1897 
1898 	if (acpi_has_method(handle, "KBLC")) {
1899 		if (!eval_kblc(priv->adev->handle, KBD_BL_QUERY_TYPE, &val)) {
1900 			if (val == KBD_BL_TRISTATE_TYPE) {
1901 				priv->features.kbd_bl = true;
1902 				priv->kbd_bl.type = KBD_BL_TRISTATE;
1903 			} else if (val == KBD_BL_TRISTATE_AUTO_TYPE) {
1904 				priv->features.kbd_bl = true;
1905 				priv->kbd_bl.type = KBD_BL_TRISTATE_AUTO;
1906 			} else {
1907 				dev_warn(&priv->platform_device->dev,
1908 					 "Unknown keyboard type: %lu",
1909 					 val);
1910 			}
1911 		}
1912 	}
1913 }
1914 
1915 #if IS_ENABLED(CONFIG_ACPI_WMI)
1916 /*
1917  * WMI driver
1918  */
1919 enum ideapad_wmi_event_type {
1920 	IDEAPAD_WMI_EVENT_ESC,
1921 	IDEAPAD_WMI_EVENT_FN_KEYS,
1922 };
1923 
1924 struct ideapad_wmi_private {
1925 	enum ideapad_wmi_event_type event;
1926 };
1927 
ideapad_wmi_probe(struct wmi_device * wdev,const void * context)1928 static int ideapad_wmi_probe(struct wmi_device *wdev, const void *context)
1929 {
1930 	struct ideapad_wmi_private *wpriv;
1931 
1932 	wpriv = devm_kzalloc(&wdev->dev, sizeof(*wpriv), GFP_KERNEL);
1933 	if (!wpriv)
1934 		return -ENOMEM;
1935 
1936 	*wpriv = *(const struct ideapad_wmi_private *)context;
1937 
1938 	dev_set_drvdata(&wdev->dev, wpriv);
1939 	return 0;
1940 }
1941 
ideapad_wmi_notify(struct wmi_device * wdev,union acpi_object * data)1942 static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
1943 {
1944 	struct ideapad_wmi_private *wpriv = dev_get_drvdata(&wdev->dev);
1945 	struct ideapad_private *priv;
1946 	unsigned long result;
1947 
1948 	mutex_lock(&ideapad_shared_mutex);
1949 
1950 	priv = ideapad_shared;
1951 	if (!priv)
1952 		goto unlock;
1953 
1954 	switch (wpriv->event) {
1955 	case IDEAPAD_WMI_EVENT_ESC:
1956 		ideapad_input_report(priv, 128);
1957 		break;
1958 	case IDEAPAD_WMI_EVENT_FN_KEYS:
1959 		if (priv->features.set_fn_lock_led &&
1960 		    !eval_hals(priv->adev->handle, &result)) {
1961 			bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
1962 
1963 			exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
1964 		}
1965 
1966 		if (data->type != ACPI_TYPE_INTEGER) {
1967 			dev_warn(&wdev->dev,
1968 				 "WMI event data is not an integer\n");
1969 			break;
1970 		}
1971 
1972 		dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n",
1973 			data->integer.value);
1974 
1975 		ideapad_input_report(priv,
1976 				     data->integer.value | IDEAPAD_WMI_KEY);
1977 
1978 		break;
1979 	}
1980 unlock:
1981 	mutex_unlock(&ideapad_shared_mutex);
1982 }
1983 
1984 static const struct ideapad_wmi_private ideapad_wmi_context_esc = {
1985 	.event = IDEAPAD_WMI_EVENT_ESC
1986 };
1987 
1988 static const struct ideapad_wmi_private ideapad_wmi_context_fn_keys = {
1989 	.event = IDEAPAD_WMI_EVENT_FN_KEYS
1990 };
1991 
1992 static const struct wmi_device_id ideapad_wmi_ids[] = {
1993 	{ "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", &ideapad_wmi_context_esc }, /* Yoga 3 */
1994 	{ "56322276-8493-4CE8-A783-98C991274F5E", &ideapad_wmi_context_esc }, /* Yoga 700 */
1995 	{ "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", &ideapad_wmi_context_fn_keys }, /* Legion 5 */
1996 	{},
1997 };
1998 MODULE_DEVICE_TABLE(wmi, ideapad_wmi_ids);
1999 
2000 static struct wmi_driver ideapad_wmi_driver = {
2001 	.driver = {
2002 		.name = "ideapad_wmi",
2003 	},
2004 	.id_table = ideapad_wmi_ids,
2005 	.probe = ideapad_wmi_probe,
2006 	.notify = ideapad_wmi_notify,
2007 };
2008 
ideapad_wmi_driver_register(void)2009 static int ideapad_wmi_driver_register(void)
2010 {
2011 	return wmi_driver_register(&ideapad_wmi_driver);
2012 }
2013 
ideapad_wmi_driver_unregister(void)2014 static void ideapad_wmi_driver_unregister(void)
2015 {
2016 	return wmi_driver_unregister(&ideapad_wmi_driver);
2017 }
2018 
2019 #else
ideapad_wmi_driver_register(void)2020 static inline int ideapad_wmi_driver_register(void) { return 0; }
ideapad_wmi_driver_unregister(void)2021 static inline void ideapad_wmi_driver_unregister(void) { }
2022 #endif
2023 
2024 /*
2025  * ACPI driver
2026  */
ideapad_acpi_add(struct platform_device * pdev)2027 static int ideapad_acpi_add(struct platform_device *pdev)
2028 {
2029 	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
2030 	struct ideapad_private *priv;
2031 	acpi_status status;
2032 	unsigned long cfg;
2033 	int err, i;
2034 
2035 	if (!adev || eval_int(adev->handle, "_CFG", &cfg))
2036 		return -ENODEV;
2037 
2038 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
2039 	if (!priv)
2040 		return -ENOMEM;
2041 
2042 	dev_set_drvdata(&pdev->dev, priv);
2043 
2044 	priv->cfg = cfg;
2045 	priv->adev = adev;
2046 	priv->platform_device = pdev;
2047 
2048 	ideapad_check_features(priv);
2049 
2050 	err = ideapad_sysfs_init(priv);
2051 	if (err)
2052 		return err;
2053 
2054 	ideapad_debugfs_init(priv);
2055 
2056 	err = ideapad_input_init(priv);
2057 	if (err)
2058 		goto input_failed;
2059 
2060 	err = ideapad_kbd_bl_init(priv);
2061 	if (err) {
2062 		if (err != -ENODEV)
2063 			dev_warn(&pdev->dev, "Could not set up keyboard backlight LED: %d\n", err);
2064 		else
2065 			dev_info(&pdev->dev, "Keyboard backlight control not available\n");
2066 	}
2067 
2068 	/*
2069 	 * On some models without a hw-switch (the yoga 2 13 at least)
2070 	 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
2071 	 */
2072 	if (!priv->features.hw_rfkill_switch)
2073 		write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
2074 
2075 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
2076 		if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
2077 			ideapad_register_rfkill(priv, i);
2078 
2079 	ideapad_sync_rfk_state(priv);
2080 	ideapad_sync_touchpad_state(priv, false);
2081 
2082 	err = ideapad_dytc_profile_init(priv);
2083 	if (err) {
2084 		if (err != -ENODEV)
2085 			dev_warn(&pdev->dev, "Could not set up DYTC interface: %d\n", err);
2086 		else
2087 			dev_info(&pdev->dev, "DYTC interface is not available\n");
2088 	}
2089 
2090 	if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
2091 		err = ideapad_backlight_init(priv);
2092 		if (err && err != -ENODEV)
2093 			goto backlight_failed;
2094 	}
2095 
2096 	status = acpi_install_notify_handler(adev->handle,
2097 					     ACPI_DEVICE_NOTIFY,
2098 					     ideapad_acpi_notify, priv);
2099 	if (ACPI_FAILURE(status)) {
2100 		err = -EIO;
2101 		goto notification_failed;
2102 	}
2103 
2104 	err = ideapad_shared_init(priv);
2105 	if (err)
2106 		goto shared_init_failed;
2107 
2108 	ideapad_laptop_register_notifier(&ideapad_laptop_notifier);
2109 
2110 	return 0;
2111 
2112 shared_init_failed:
2113 	acpi_remove_notify_handler(priv->adev->handle,
2114 				   ACPI_DEVICE_NOTIFY,
2115 				   ideapad_acpi_notify);
2116 
2117 notification_failed:
2118 	ideapad_backlight_exit(priv);
2119 
2120 backlight_failed:
2121 	ideapad_dytc_profile_exit(priv);
2122 
2123 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
2124 		ideapad_unregister_rfkill(priv, i);
2125 
2126 	ideapad_kbd_bl_exit(priv);
2127 	ideapad_input_exit(priv);
2128 
2129 input_failed:
2130 	ideapad_debugfs_exit(priv);
2131 	ideapad_sysfs_exit(priv);
2132 
2133 	return err;
2134 }
2135 
ideapad_acpi_remove(struct platform_device * pdev)2136 static void ideapad_acpi_remove(struct platform_device *pdev)
2137 {
2138 	struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
2139 	int i;
2140 
2141 	ideapad_laptop_unregister_notifier(&ideapad_laptop_notifier);
2142 
2143 	ideapad_shared_exit(priv);
2144 
2145 	acpi_remove_notify_handler(priv->adev->handle,
2146 				   ACPI_DEVICE_NOTIFY,
2147 				   ideapad_acpi_notify);
2148 
2149 	ideapad_backlight_exit(priv);
2150 	ideapad_dytc_profile_exit(priv);
2151 
2152 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
2153 		ideapad_unregister_rfkill(priv, i);
2154 
2155 	ideapad_kbd_bl_exit(priv);
2156 	ideapad_input_exit(priv);
2157 	ideapad_debugfs_exit(priv);
2158 	ideapad_sysfs_exit(priv);
2159 }
2160 
2161 #ifdef CONFIG_PM_SLEEP
ideapad_acpi_resume(struct device * dev)2162 static int ideapad_acpi_resume(struct device *dev)
2163 {
2164 	struct ideapad_private *priv = dev_get_drvdata(dev);
2165 
2166 	ideapad_sync_rfk_state(priv);
2167 	ideapad_sync_touchpad_state(priv, false);
2168 
2169 	if (priv->dytc)
2170 		dytc_profile_refresh(priv);
2171 
2172 	return 0;
2173 }
2174 #endif
2175 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
2176 
2177 static const struct acpi_device_id ideapad_device_ids[] = {
2178 	{"VPC2004", 0},
2179 	{"", 0},
2180 };
2181 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
2182 
2183 static struct platform_driver ideapad_acpi_driver = {
2184 	.probe = ideapad_acpi_add,
2185 	.remove_new = ideapad_acpi_remove,
2186 	.driver = {
2187 		.name   = "ideapad_acpi",
2188 		.pm     = &ideapad_pm,
2189 		.acpi_match_table = ACPI_PTR(ideapad_device_ids),
2190 	},
2191 };
2192 
ideapad_laptop_init(void)2193 static int __init ideapad_laptop_init(void)
2194 {
2195 	int err;
2196 
2197 	err = ideapad_wmi_driver_register();
2198 	if (err)
2199 		return err;
2200 
2201 	err = platform_driver_register(&ideapad_acpi_driver);
2202 	if (err) {
2203 		ideapad_wmi_driver_unregister();
2204 		return err;
2205 	}
2206 
2207 	return 0;
2208 }
module_init(ideapad_laptop_init)2209 module_init(ideapad_laptop_init)
2210 
2211 static void __exit ideapad_laptop_exit(void)
2212 {
2213 	ideapad_wmi_driver_unregister();
2214 	platform_driver_unregister(&ideapad_acpi_driver);
2215 }
2216 module_exit(ideapad_laptop_exit)
2217 
2218 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
2219 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
2220 MODULE_LICENSE("GPL");
2221