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