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