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