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/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/acpi.h>
16 #include <linux/rfkill.h>
17 #include <linux/platform_device.h>
18 #include <linux/input.h>
19 #include <linux/input/sparse-keymap.h>
20 #include <linux/backlight.h>
21 #include <linux/fb.h>
22 #include <linux/debugfs.h>
23 #include <linux/seq_file.h>
24 #include <linux/i8042.h>
25 #include <linux/dmi.h>
26 #include <linux/device.h>
27 #include <acpi/video.h>
28 
29 #define IDEAPAD_RFKILL_DEV_NUM	(3)
30 
31 #define BM_CONSERVATION_BIT (5)
32 #define HA_FNLOCK_BIT       (10)
33 
34 #define CFG_BT_BIT	(16)
35 #define CFG_3G_BIT	(17)
36 #define CFG_WIFI_BIT	(18)
37 #define CFG_CAMERA_BIT	(19)
38 
39 #if IS_ENABLED(CONFIG_ACPI_WMI)
40 static const char *const ideapad_wmi_fnesc_events[] = {
41 	"26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
42 	"56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
43 };
44 #endif
45 
46 enum {
47 	BMCMD_CONSERVATION_ON = 3,
48 	BMCMD_CONSERVATION_OFF = 5,
49 	HACMD_FNLOCK_ON = 0xe,
50 	HACMD_FNLOCK_OFF = 0xf,
51 };
52 
53 enum {
54 	VPCCMD_R_VPC1 = 0x10,
55 	VPCCMD_R_BL_MAX,
56 	VPCCMD_R_BL,
57 	VPCCMD_W_BL,
58 	VPCCMD_R_WIFI,
59 	VPCCMD_W_WIFI,
60 	VPCCMD_R_BT,
61 	VPCCMD_W_BT,
62 	VPCCMD_R_BL_POWER,
63 	VPCCMD_R_NOVO,
64 	VPCCMD_R_VPC2,
65 	VPCCMD_R_TOUCHPAD,
66 	VPCCMD_W_TOUCHPAD,
67 	VPCCMD_R_CAMERA,
68 	VPCCMD_W_CAMERA,
69 	VPCCMD_R_3G,
70 	VPCCMD_W_3G,
71 	VPCCMD_R_ODD, /* 0x21 */
72 	VPCCMD_W_FAN,
73 	VPCCMD_R_RF,
74 	VPCCMD_W_RF,
75 	VPCCMD_R_FAN = 0x2B,
76 	VPCCMD_R_SPECIAL_BUTTONS = 0x31,
77 	VPCCMD_W_BL_POWER = 0x33,
78 };
79 
80 struct ideapad_rfk_priv {
81 	int dev;
82 	struct ideapad_private *priv;
83 };
84 
85 struct ideapad_private {
86 	struct acpi_device *adev;
87 	struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
88 	struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
89 	struct platform_device *platform_device;
90 	struct input_dev *inputdev;
91 	struct backlight_device *blightdev;
92 	struct dentry *debug;
93 	unsigned long cfg;
94 	bool has_hw_rfkill_switch;
95 	bool has_touchpad_switch;
96 	const char *fnesc_guid;
97 };
98 
99 static bool no_bt_rfkill;
100 module_param(no_bt_rfkill, bool, 0444);
101 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
102 
103 /*
104  * ACPI Helpers
105  */
106 #define IDEAPAD_EC_TIMEOUT (200) /* in ms */
107 
108 static int read_method_int(acpi_handle handle, const char *method, int *val)
109 {
110 	acpi_status status;
111 	unsigned long long result;
112 
113 	status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
114 	if (ACPI_FAILURE(status)) {
115 		*val = -1;
116 		return -1;
117 	}
118 	*val = result;
119 	return 0;
120 
121 }
122 
123 static int method_gbmd(acpi_handle handle, unsigned long *ret)
124 {
125 	int result, val;
126 
127 	result = read_method_int(handle, "GBMD", &val);
128 	*ret = val;
129 	return result;
130 }
131 
132 static int method_int1(acpi_handle handle, char *method, int cmd)
133 {
134 	acpi_status status;
135 
136 	status = acpi_execute_simple_method(handle, method, cmd);
137 	return ACPI_FAILURE(status) ? -1 : 0;
138 }
139 
140 static int method_vpcr(acpi_handle handle, int cmd, int *ret)
141 {
142 	acpi_status status;
143 	unsigned long long result;
144 	struct acpi_object_list params;
145 	union acpi_object in_obj;
146 
147 	params.count = 1;
148 	params.pointer = &in_obj;
149 	in_obj.type = ACPI_TYPE_INTEGER;
150 	in_obj.integer.value = cmd;
151 
152 	status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
153 
154 	if (ACPI_FAILURE(status)) {
155 		*ret = -1;
156 		return -1;
157 	}
158 	*ret = result;
159 	return 0;
160 
161 }
162 
163 static int method_vpcw(acpi_handle handle, int cmd, int data)
164 {
165 	struct acpi_object_list params;
166 	union acpi_object in_obj[2];
167 	acpi_status status;
168 
169 	params.count = 2;
170 	params.pointer = in_obj;
171 	in_obj[0].type = ACPI_TYPE_INTEGER;
172 	in_obj[0].integer.value = cmd;
173 	in_obj[1].type = ACPI_TYPE_INTEGER;
174 	in_obj[1].integer.value = data;
175 
176 	status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
177 	if (status != AE_OK)
178 		return -1;
179 	return 0;
180 }
181 
182 static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
183 {
184 	int val;
185 	unsigned long int end_jiffies;
186 
187 	if (method_vpcw(handle, 1, cmd))
188 		return -1;
189 
190 	for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
191 	     time_before(jiffies, end_jiffies);) {
192 		schedule();
193 		if (method_vpcr(handle, 1, &val))
194 			return -1;
195 		if (val == 0) {
196 			if (method_vpcr(handle, 0, &val))
197 				return -1;
198 			*data = val;
199 			return 0;
200 		}
201 	}
202 	pr_err("timeout in %s\n", __func__);
203 	return -1;
204 }
205 
206 static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
207 {
208 	int val;
209 	unsigned long int end_jiffies;
210 
211 	if (method_vpcw(handle, 0, data))
212 		return -1;
213 	if (method_vpcw(handle, 1, cmd))
214 		return -1;
215 
216 	for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
217 	     time_before(jiffies, end_jiffies);) {
218 		schedule();
219 		if (method_vpcr(handle, 1, &val))
220 			return -1;
221 		if (val == 0)
222 			return 0;
223 	}
224 	pr_err("timeout in %s\n", __func__);
225 	return -1;
226 }
227 
228 /*
229  * debugfs
230  */
231 static int debugfs_status_show(struct seq_file *s, void *data)
232 {
233 	struct ideapad_private *priv = s->private;
234 	unsigned long value;
235 
236 	if (!priv)
237 		return -EINVAL;
238 
239 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
240 		seq_printf(s, "Backlight max:\t%lu\n", value);
241 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
242 		seq_printf(s, "Backlight now:\t%lu\n", value);
243 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
244 		seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
245 	seq_printf(s, "=====================\n");
246 
247 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
248 		seq_printf(s, "Radio status:\t%s(%lu)\n",
249 			   value ? "On" : "Off", value);
250 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
251 		seq_printf(s, "Wifi status:\t%s(%lu)\n",
252 			   value ? "On" : "Off", value);
253 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
254 		seq_printf(s, "BT status:\t%s(%lu)\n",
255 			   value ? "On" : "Off", value);
256 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
257 		seq_printf(s, "3G status:\t%s(%lu)\n",
258 			   value ? "On" : "Off", value);
259 	seq_printf(s, "=====================\n");
260 
261 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
262 		seq_printf(s, "Touchpad status:%s(%lu)\n",
263 			   value ? "On" : "Off", value);
264 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
265 		seq_printf(s, "Camera status:\t%s(%lu)\n",
266 			   value ? "On" : "Off", value);
267 	seq_puts(s, "=====================\n");
268 
269 	if (!method_gbmd(priv->adev->handle, &value)) {
270 		seq_printf(s, "Conservation mode:\t%s(%lu)\n",
271 			   test_bit(BM_CONSERVATION_BIT, &value) ? "On" : "Off",
272 			   value);
273 	}
274 
275 	return 0;
276 }
277 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
278 
279 static int debugfs_cfg_show(struct seq_file *s, void *data)
280 {
281 	struct ideapad_private *priv = s->private;
282 
283 	if (!priv) {
284 		seq_printf(s, "cfg: N/A\n");
285 	} else {
286 		seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
287 			   priv->cfg);
288 		if (test_bit(CFG_BT_BIT, &priv->cfg))
289 			seq_printf(s, "Bluetooth ");
290 		if (test_bit(CFG_3G_BIT, &priv->cfg))
291 			seq_printf(s, "3G ");
292 		if (test_bit(CFG_WIFI_BIT, &priv->cfg))
293 			seq_printf(s, "Wireless ");
294 		if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
295 			seq_printf(s, "Camera ");
296 		seq_printf(s, "\nGraphic: ");
297 		switch ((priv->cfg)&0x700) {
298 		case 0x100:
299 			seq_printf(s, "Intel");
300 			break;
301 		case 0x200:
302 			seq_printf(s, "ATI");
303 			break;
304 		case 0x300:
305 			seq_printf(s, "Nvidia");
306 			break;
307 		case 0x400:
308 			seq_printf(s, "Intel and ATI");
309 			break;
310 		case 0x500:
311 			seq_printf(s, "Intel and Nvidia");
312 			break;
313 		}
314 		seq_printf(s, "\n");
315 	}
316 	return 0;
317 }
318 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
319 
320 static void ideapad_debugfs_init(struct ideapad_private *priv)
321 {
322 	struct dentry *dir;
323 
324 	dir = debugfs_create_dir("ideapad", NULL);
325 	priv->debug = dir;
326 
327 	debugfs_create_file("cfg", S_IRUGO, dir, priv, &debugfs_cfg_fops);
328 	debugfs_create_file("status", S_IRUGO, dir, priv, &debugfs_status_fops);
329 }
330 
331 static void ideapad_debugfs_exit(struct ideapad_private *priv)
332 {
333 	debugfs_remove_recursive(priv->debug);
334 	priv->debug = NULL;
335 }
336 
337 /*
338  * sysfs
339  */
340 static ssize_t show_ideapad_cam(struct device *dev,
341 				struct device_attribute *attr,
342 				char *buf)
343 {
344 	unsigned long result;
345 	struct ideapad_private *priv = dev_get_drvdata(dev);
346 
347 	if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
348 		return sprintf(buf, "-1\n");
349 	return sprintf(buf, "%lu\n", result);
350 }
351 
352 static ssize_t store_ideapad_cam(struct device *dev,
353 				 struct device_attribute *attr,
354 				 const char *buf, size_t count)
355 {
356 	int ret, state;
357 	struct ideapad_private *priv = dev_get_drvdata(dev);
358 
359 	if (!count)
360 		return 0;
361 	if (sscanf(buf, "%i", &state) != 1)
362 		return -EINVAL;
363 	ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
364 	if (ret < 0)
365 		return -EIO;
366 	return count;
367 }
368 
369 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
370 
371 static ssize_t show_ideapad_fan(struct device *dev,
372 				struct device_attribute *attr,
373 				char *buf)
374 {
375 	unsigned long result;
376 	struct ideapad_private *priv = dev_get_drvdata(dev);
377 
378 	if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
379 		return sprintf(buf, "-1\n");
380 	return sprintf(buf, "%lu\n", result);
381 }
382 
383 static ssize_t store_ideapad_fan(struct device *dev,
384 				 struct device_attribute *attr,
385 				 const char *buf, size_t count)
386 {
387 	int ret, state;
388 	struct ideapad_private *priv = dev_get_drvdata(dev);
389 
390 	if (!count)
391 		return 0;
392 	if (sscanf(buf, "%i", &state) != 1)
393 		return -EINVAL;
394 	if (state < 0 || state > 4 || state == 3)
395 		return -EINVAL;
396 	ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
397 	if (ret < 0)
398 		return -EIO;
399 	return count;
400 }
401 
402 static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
403 
404 static ssize_t touchpad_show(struct device *dev,
405 			     struct device_attribute *attr,
406 			     char *buf)
407 {
408 	struct ideapad_private *priv = dev_get_drvdata(dev);
409 	unsigned long result;
410 
411 	if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))
412 		return sprintf(buf, "-1\n");
413 	return sprintf(buf, "%lu\n", result);
414 }
415 
416 /* Switch to RO for now: It might be revisited in the future */
417 static ssize_t __maybe_unused touchpad_store(struct device *dev,
418 					     struct device_attribute *attr,
419 					     const char *buf, size_t count)
420 {
421 	struct ideapad_private *priv = dev_get_drvdata(dev);
422 	bool state;
423 	int ret;
424 
425 	ret = kstrtobool(buf, &state);
426 	if (ret)
427 		return ret;
428 
429 	ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
430 	if (ret < 0)
431 		return -EIO;
432 	return count;
433 }
434 
435 static DEVICE_ATTR_RO(touchpad);
436 
437 static ssize_t conservation_mode_show(struct device *dev,
438 				struct device_attribute *attr,
439 				char *buf)
440 {
441 	struct ideapad_private *priv = dev_get_drvdata(dev);
442 	unsigned long result;
443 
444 	if (method_gbmd(priv->adev->handle, &result))
445 		return sprintf(buf, "-1\n");
446 	return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result));
447 }
448 
449 static ssize_t conservation_mode_store(struct device *dev,
450 				 struct device_attribute *attr,
451 				 const char *buf, size_t count)
452 {
453 	struct ideapad_private *priv = dev_get_drvdata(dev);
454 	bool state;
455 	int ret;
456 
457 	ret = kstrtobool(buf, &state);
458 	if (ret)
459 		return ret;
460 
461 	ret = method_int1(priv->adev->handle, "SBMC", state ?
462 					      BMCMD_CONSERVATION_ON :
463 					      BMCMD_CONSERVATION_OFF);
464 	if (ret < 0)
465 		return -EIO;
466 	return count;
467 }
468 
469 static DEVICE_ATTR_RW(conservation_mode);
470 
471 static ssize_t fn_lock_show(struct device *dev,
472 			    struct device_attribute *attr,
473 			    char *buf)
474 {
475 	struct ideapad_private *priv = dev_get_drvdata(dev);
476 	unsigned long result;
477 	int hals;
478 	int fail = read_method_int(priv->adev->handle, "HALS", &hals);
479 
480 	if (fail)
481 		return sprintf(buf, "-1\n");
482 
483 	result = hals;
484 	return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
485 }
486 
487 static ssize_t fn_lock_store(struct device *dev,
488 			     struct device_attribute *attr,
489 			     const char *buf, size_t count)
490 {
491 	struct ideapad_private *priv = dev_get_drvdata(dev);
492 	bool state;
493 	int ret;
494 
495 	ret = kstrtobool(buf, &state);
496 	if (ret)
497 		return ret;
498 
499 	ret = method_int1(priv->adev->handle, "SALS", state ?
500 			  HACMD_FNLOCK_ON :
501 			  HACMD_FNLOCK_OFF);
502 	if (ret < 0)
503 		return -EIO;
504 	return count;
505 }
506 
507 static DEVICE_ATTR_RW(fn_lock);
508 
509 
510 static struct attribute *ideapad_attributes[] = {
511 	&dev_attr_camera_power.attr,
512 	&dev_attr_fan_mode.attr,
513 	&dev_attr_touchpad.attr,
514 	&dev_attr_conservation_mode.attr,
515 	&dev_attr_fn_lock.attr,
516 	NULL
517 };
518 
519 static umode_t ideapad_is_visible(struct kobject *kobj,
520 				 struct attribute *attr,
521 				 int idx)
522 {
523 	struct device *dev = container_of(kobj, struct device, kobj);
524 	struct ideapad_private *priv = dev_get_drvdata(dev);
525 	bool supported;
526 
527 	if (attr == &dev_attr_camera_power.attr)
528 		supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
529 	else if (attr == &dev_attr_fan_mode.attr) {
530 		unsigned long value;
531 		supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
532 					  &value);
533 	} else if (attr == &dev_attr_conservation_mode.attr) {
534 		supported = acpi_has_method(priv->adev->handle, "GBMD") &&
535 			    acpi_has_method(priv->adev->handle, "SBMC");
536 	} else if (attr == &dev_attr_fn_lock.attr) {
537 		supported = acpi_has_method(priv->adev->handle, "HALS") &&
538 			acpi_has_method(priv->adev->handle, "SALS");
539 	} else if (attr == &dev_attr_touchpad.attr)
540 		supported = priv->has_touchpad_switch;
541 	else
542 		supported = true;
543 
544 	return supported ? attr->mode : 0;
545 }
546 
547 static const struct attribute_group ideapad_attribute_group = {
548 	.is_visible = ideapad_is_visible,
549 	.attrs = ideapad_attributes
550 };
551 
552 /*
553  * Rfkill
554  */
555 struct ideapad_rfk_data {
556 	char *name;
557 	int cfgbit;
558 	int opcode;
559 	int type;
560 };
561 
562 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
563 	{ "ideapad_wlan",    CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
564 	{ "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
565 	{ "ideapad_3g",        CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
566 };
567 
568 static int ideapad_rfk_set(void *data, bool blocked)
569 {
570 	struct ideapad_rfk_priv *priv = data;
571 	int opcode = ideapad_rfk_data[priv->dev].opcode;
572 
573 	return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
574 }
575 
576 static const struct rfkill_ops ideapad_rfk_ops = {
577 	.set_block = ideapad_rfk_set,
578 };
579 
580 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
581 {
582 	unsigned long hw_blocked = 0;
583 	int i;
584 
585 	if (priv->has_hw_rfkill_switch) {
586 		if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
587 			return;
588 		hw_blocked = !hw_blocked;
589 	}
590 
591 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
592 		if (priv->rfk[i])
593 			rfkill_set_hw_state(priv->rfk[i], hw_blocked);
594 }
595 
596 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
597 {
598 	int ret;
599 	unsigned long sw_blocked;
600 
601 	if (no_bt_rfkill &&
602 	    (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
603 		/* Force to enable bluetooth when no_bt_rfkill=1 */
604 		write_ec_cmd(priv->adev->handle,
605 			     ideapad_rfk_data[dev].opcode, 1);
606 		return 0;
607 	}
608 	priv->rfk_priv[dev].dev = dev;
609 	priv->rfk_priv[dev].priv = priv;
610 
611 	priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
612 				      &priv->platform_device->dev,
613 				      ideapad_rfk_data[dev].type,
614 				      &ideapad_rfk_ops,
615 				      &priv->rfk_priv[dev]);
616 	if (!priv->rfk[dev])
617 		return -ENOMEM;
618 
619 	if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
620 			 &sw_blocked)) {
621 		rfkill_init_sw_state(priv->rfk[dev], 0);
622 	} else {
623 		sw_blocked = !sw_blocked;
624 		rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
625 	}
626 
627 	ret = rfkill_register(priv->rfk[dev]);
628 	if (ret) {
629 		rfkill_destroy(priv->rfk[dev]);
630 		return ret;
631 	}
632 	return 0;
633 }
634 
635 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
636 {
637 	if (!priv->rfk[dev])
638 		return;
639 
640 	rfkill_unregister(priv->rfk[dev]);
641 	rfkill_destroy(priv->rfk[dev]);
642 }
643 
644 /*
645  * Platform device
646  */
647 static int ideapad_sysfs_init(struct ideapad_private *priv)
648 {
649 	return sysfs_create_group(&priv->platform_device->dev.kobj,
650 				    &ideapad_attribute_group);
651 }
652 
653 static void ideapad_sysfs_exit(struct ideapad_private *priv)
654 {
655 	sysfs_remove_group(&priv->platform_device->dev.kobj,
656 			   &ideapad_attribute_group);
657 }
658 
659 /*
660  * input device
661  */
662 static const struct key_entry ideapad_keymap[] = {
663 	{ KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } },
664 	{ KE_KEY, 7,  { KEY_CAMERA } },
665 	{ KE_KEY, 8,  { KEY_MICMUTE } },
666 	{ KE_KEY, 11, { KEY_F16 } },
667 	{ KE_KEY, 13, { KEY_WLAN } },
668 	{ KE_KEY, 16, { KEY_PROG1 } },
669 	{ KE_KEY, 17, { KEY_PROG2 } },
670 	{ KE_KEY, 64, { KEY_PROG3 } },
671 	{ KE_KEY, 65, { KEY_PROG4 } },
672 	{ KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
673 	{ KE_KEY, 67, { KEY_TOUCHPAD_ON } },
674 	{ KE_KEY, 128, { KEY_ESC } },
675 
676 	{ KE_END, 0 },
677 };
678 
679 static int ideapad_input_init(struct ideapad_private *priv)
680 {
681 	struct input_dev *inputdev;
682 	int error;
683 
684 	inputdev = input_allocate_device();
685 	if (!inputdev)
686 		return -ENOMEM;
687 
688 	inputdev->name = "Ideapad extra buttons";
689 	inputdev->phys = "ideapad/input0";
690 	inputdev->id.bustype = BUS_HOST;
691 	inputdev->dev.parent = &priv->platform_device->dev;
692 
693 	error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
694 	if (error) {
695 		pr_err("Unable to setup input device keymap\n");
696 		goto err_free_dev;
697 	}
698 
699 	error = input_register_device(inputdev);
700 	if (error) {
701 		pr_err("Unable to register input device\n");
702 		goto err_free_dev;
703 	}
704 
705 	priv->inputdev = inputdev;
706 	return 0;
707 
708 err_free_dev:
709 	input_free_device(inputdev);
710 	return error;
711 }
712 
713 static void ideapad_input_exit(struct ideapad_private *priv)
714 {
715 	input_unregister_device(priv->inputdev);
716 	priv->inputdev = NULL;
717 }
718 
719 static void ideapad_input_report(struct ideapad_private *priv,
720 				 unsigned long scancode)
721 {
722 	sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
723 }
724 
725 static void ideapad_input_novokey(struct ideapad_private *priv)
726 {
727 	unsigned long long_pressed;
728 
729 	if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
730 		return;
731 	if (long_pressed)
732 		ideapad_input_report(priv, 17);
733 	else
734 		ideapad_input_report(priv, 16);
735 }
736 
737 static void ideapad_check_special_buttons(struct ideapad_private *priv)
738 {
739 	unsigned long bit, value;
740 
741 	read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
742 
743 	for (bit = 0; bit < 16; bit++) {
744 		if (test_bit(bit, &value)) {
745 			switch (bit) {
746 			case 0:	/* Z580 */
747 			case 6:	/* Z570 */
748 				/* Thermal Management button */
749 				ideapad_input_report(priv, 65);
750 				break;
751 			case 1:
752 				/* OneKey Theater button */
753 				ideapad_input_report(priv, 64);
754 				break;
755 			default:
756 				pr_info("Unknown special button: %lu\n", bit);
757 				break;
758 			}
759 		}
760 	}
761 }
762 
763 /*
764  * backlight
765  */
766 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
767 {
768 	struct ideapad_private *priv = bl_get_data(blightdev);
769 	unsigned long now;
770 
771 	if (!priv)
772 		return -EINVAL;
773 
774 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
775 		return -EIO;
776 	return now;
777 }
778 
779 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
780 {
781 	struct ideapad_private *priv = bl_get_data(blightdev);
782 
783 	if (!priv)
784 		return -EINVAL;
785 
786 	if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
787 			 blightdev->props.brightness))
788 		return -EIO;
789 	if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
790 			 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
791 		return -EIO;
792 
793 	return 0;
794 }
795 
796 static const struct backlight_ops ideapad_backlight_ops = {
797 	.get_brightness = ideapad_backlight_get_brightness,
798 	.update_status = ideapad_backlight_update_status,
799 };
800 
801 static int ideapad_backlight_init(struct ideapad_private *priv)
802 {
803 	struct backlight_device *blightdev;
804 	struct backlight_properties props;
805 	unsigned long max, now, power;
806 
807 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
808 		return -EIO;
809 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
810 		return -EIO;
811 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
812 		return -EIO;
813 
814 	memset(&props, 0, sizeof(struct backlight_properties));
815 	props.max_brightness = max;
816 	props.type = BACKLIGHT_PLATFORM;
817 	blightdev = backlight_device_register("ideapad",
818 					      &priv->platform_device->dev,
819 					      priv,
820 					      &ideapad_backlight_ops,
821 					      &props);
822 	if (IS_ERR(blightdev)) {
823 		pr_err("Could not register backlight device\n");
824 		return PTR_ERR(blightdev);
825 	}
826 
827 	priv->blightdev = blightdev;
828 	blightdev->props.brightness = now;
829 	blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
830 	backlight_update_status(blightdev);
831 
832 	return 0;
833 }
834 
835 static void ideapad_backlight_exit(struct ideapad_private *priv)
836 {
837 	backlight_device_unregister(priv->blightdev);
838 	priv->blightdev = NULL;
839 }
840 
841 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
842 {
843 	unsigned long power;
844 	struct backlight_device *blightdev = priv->blightdev;
845 
846 	if (!blightdev)
847 		return;
848 	if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
849 		return;
850 	blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
851 }
852 
853 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
854 {
855 	unsigned long now;
856 
857 	/* if we control brightness via acpi video driver */
858 	if (priv->blightdev == NULL) {
859 		read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
860 		return;
861 	}
862 
863 	backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
864 }
865 
866 /*
867  * module init/exit
868  */
869 static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
870 {
871 	unsigned long value;
872 
873 	if (!priv->has_touchpad_switch)
874 		return;
875 
876 	/* Without reading from EC touchpad LED doesn't switch state */
877 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
878 		/* Some IdeaPads don't really turn off touchpad - they only
879 		 * switch the LED state. We (de)activate KBC AUX port to turn
880 		 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
881 		 * KEY_TOUCHPAD_ON to not to get out of sync with LED */
882 		unsigned char param;
883 		i8042_command(&param, value ? I8042_CMD_AUX_ENABLE :
884 			      I8042_CMD_AUX_DISABLE);
885 		ideapad_input_report(priv, value ? 67 : 66);
886 	}
887 }
888 
889 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
890 {
891 	struct ideapad_private *priv = data;
892 	unsigned long vpc1, vpc2, vpc_bit;
893 
894 	if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
895 		return;
896 	if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
897 		return;
898 
899 	vpc1 = (vpc2 << 8) | vpc1;
900 	for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
901 		if (test_bit(vpc_bit, &vpc1)) {
902 			switch (vpc_bit) {
903 			case 9:
904 				ideapad_sync_rfk_state(priv);
905 				break;
906 			case 13:
907 			case 11:
908 			case 8:
909 			case 7:
910 			case 6:
911 				ideapad_input_report(priv, vpc_bit);
912 				break;
913 			case 5:
914 				ideapad_sync_touchpad_state(priv);
915 				break;
916 			case 4:
917 				ideapad_backlight_notify_brightness(priv);
918 				break;
919 			case 3:
920 				ideapad_input_novokey(priv);
921 				break;
922 			case 2:
923 				ideapad_backlight_notify_power(priv);
924 				break;
925 			case 0:
926 				ideapad_check_special_buttons(priv);
927 				break;
928 			case 1:
929 				/* Some IdeaPads report event 1 every ~20
930 				 * seconds while on battery power; some
931 				 * report this when changing to/from tablet
932 				 * mode. Squelch this event.
933 				 */
934 				break;
935 			default:
936 				pr_info("Unknown event: %lu\n", vpc_bit);
937 			}
938 		}
939 	}
940 }
941 
942 #if IS_ENABLED(CONFIG_ACPI_WMI)
943 static void ideapad_wmi_notify(u32 value, void *context)
944 {
945 	switch (value) {
946 	case 128:
947 		ideapad_input_report(context, value);
948 		break;
949 	default:
950 		pr_info("Unknown WMI event %u\n", value);
951 	}
952 }
953 #endif
954 
955 /*
956  * Some ideapads have a hardware rfkill switch, but most do not have one.
957  * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
958  * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
959  * There used to be a long list of DMI ids for models without a hw rfkill
960  * switch here, but that resulted in playing whack a mole.
961  * More importantly wrongly reporting the wifi radio as hw-blocked, results in
962  * non working wifi. Whereas not reporting it hw-blocked, when it actually is
963  * hw-blocked results in an empty SSID list, which is a much more benign
964  * failure mode.
965  * So the default now is the much safer option of assuming there is no
966  * hardware rfkill switch. This default also actually matches most hardware,
967  * since having a hw rfkill switch is quite rare on modern hardware, so this
968  * also leads to a much shorter list.
969  */
970 static const struct dmi_system_id hw_rfkill_list[] = {
971 	{}
972 };
973 
974 static int ideapad_acpi_add(struct platform_device *pdev)
975 {
976 	int ret, i;
977 	int cfg;
978 	struct ideapad_private *priv;
979 	struct acpi_device *adev;
980 
981 	ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
982 	if (ret)
983 		return -ENODEV;
984 
985 	if (read_method_int(adev->handle, "_CFG", &cfg))
986 		return -ENODEV;
987 
988 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
989 	if (!priv)
990 		return -ENOMEM;
991 
992 	dev_set_drvdata(&pdev->dev, priv);
993 	priv->cfg = cfg;
994 	priv->adev = adev;
995 	priv->platform_device = pdev;
996 	priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
997 
998 	/* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
999 	priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
1000 
1001 	ret = ideapad_sysfs_init(priv);
1002 	if (ret)
1003 		return ret;
1004 
1005 	ideapad_debugfs_init(priv);
1006 
1007 	ret = ideapad_input_init(priv);
1008 	if (ret)
1009 		goto input_failed;
1010 
1011 	/*
1012 	 * On some models without a hw-switch (the yoga 2 13 at least)
1013 	 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1014 	 */
1015 	if (!priv->has_hw_rfkill_switch)
1016 		write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1017 
1018 	/* The same for Touchpad */
1019 	if (!priv->has_touchpad_switch)
1020 		write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
1021 
1022 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1023 		if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
1024 			ideapad_register_rfkill(priv, i);
1025 
1026 	ideapad_sync_rfk_state(priv);
1027 	ideapad_sync_touchpad_state(priv);
1028 
1029 	if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1030 		ret = ideapad_backlight_init(priv);
1031 		if (ret && ret != -ENODEV)
1032 			goto backlight_failed;
1033 	}
1034 	ret = acpi_install_notify_handler(adev->handle,
1035 		ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
1036 	if (ret)
1037 		goto notification_failed;
1038 
1039 #if IS_ENABLED(CONFIG_ACPI_WMI)
1040 	for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1041 		ret = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1042 						 ideapad_wmi_notify, priv);
1043 		if (ret == AE_OK) {
1044 			priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1045 			break;
1046 		}
1047 	}
1048 	if (ret != AE_OK && ret != AE_NOT_EXIST)
1049 		goto notification_failed_wmi;
1050 #endif
1051 
1052 	return 0;
1053 #if IS_ENABLED(CONFIG_ACPI_WMI)
1054 notification_failed_wmi:
1055 	acpi_remove_notify_handler(priv->adev->handle,
1056 		ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1057 #endif
1058 notification_failed:
1059 	ideapad_backlight_exit(priv);
1060 backlight_failed:
1061 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1062 		ideapad_unregister_rfkill(priv, i);
1063 	ideapad_input_exit(priv);
1064 input_failed:
1065 	ideapad_debugfs_exit(priv);
1066 	ideapad_sysfs_exit(priv);
1067 	return ret;
1068 }
1069 
1070 static int ideapad_acpi_remove(struct platform_device *pdev)
1071 {
1072 	struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
1073 	int i;
1074 
1075 #if IS_ENABLED(CONFIG_ACPI_WMI)
1076 	if (priv->fnesc_guid)
1077 		wmi_remove_notify_handler(priv->fnesc_guid);
1078 #endif
1079 	acpi_remove_notify_handler(priv->adev->handle,
1080 		ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1081 	ideapad_backlight_exit(priv);
1082 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1083 		ideapad_unregister_rfkill(priv, i);
1084 	ideapad_input_exit(priv);
1085 	ideapad_debugfs_exit(priv);
1086 	ideapad_sysfs_exit(priv);
1087 	dev_set_drvdata(&pdev->dev, NULL);
1088 
1089 	return 0;
1090 }
1091 
1092 #ifdef CONFIG_PM_SLEEP
1093 static int ideapad_acpi_resume(struct device *device)
1094 {
1095 	struct ideapad_private *priv;
1096 
1097 	if (!device)
1098 		return -EINVAL;
1099 	priv = dev_get_drvdata(device);
1100 
1101 	ideapad_sync_rfk_state(priv);
1102 	ideapad_sync_touchpad_state(priv);
1103 	return 0;
1104 }
1105 #endif
1106 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1107 
1108 static const struct acpi_device_id ideapad_device_ids[] = {
1109 	{ "VPC2004", 0},
1110 	{ "", 0},
1111 };
1112 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1113 
1114 static struct platform_driver ideapad_acpi_driver = {
1115 	.probe = ideapad_acpi_add,
1116 	.remove = ideapad_acpi_remove,
1117 	.driver = {
1118 		.name   = "ideapad_acpi",
1119 		.pm     = &ideapad_pm,
1120 		.acpi_match_table = ACPI_PTR(ideapad_device_ids),
1121 	},
1122 };
1123 
1124 module_platform_driver(ideapad_acpi_driver);
1125 
1126 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1127 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
1128 MODULE_LICENSE("GPL");
1129