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