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/acpi.h> 12 #include <linux/backlight.h> 13 #include <linux/bitops.h> 14 #include <linux/bug.h> 15 #include <linux/debugfs.h> 16 #include <linux/device.h> 17 #include <linux/dmi.h> 18 #include <linux/fb.h> 19 #include <linux/i8042.h> 20 #include <linux/init.h> 21 #include <linux/input.h> 22 #include <linux/input/sparse-keymap.h> 23 #include <linux/jiffies.h> 24 #include <linux/kernel.h> 25 #include <linux/leds.h> 26 #include <linux/module.h> 27 #include <linux/platform_device.h> 28 #include <linux/platform_profile.h> 29 #include <linux/rfkill.h> 30 #include <linux/seq_file.h> 31 #include <linux/sysfs.h> 32 #include <linux/types.h> 33 34 #include <acpi/video.h> 35 36 #include <dt-bindings/leds/common.h> 37 38 #define IDEAPAD_RFKILL_DEV_NUM 3 39 40 #if IS_ENABLED(CONFIG_ACPI_WMI) 41 static const char *const ideapad_wmi_fnesc_events[] = { 42 "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */ 43 "56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */ 44 "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", /* Legion 5 */ 45 }; 46 #endif 47 48 enum { 49 CFG_CAP_BT_BIT = 16, 50 CFG_CAP_3G_BIT = 17, 51 CFG_CAP_WIFI_BIT = 18, 52 CFG_CAP_CAM_BIT = 19, 53 CFG_CAP_TOUCHPAD_BIT = 30, 54 }; 55 56 enum { 57 GBMD_CONSERVATION_STATE_BIT = 5, 58 }; 59 60 enum { 61 SBMC_CONSERVATION_ON = 3, 62 SBMC_CONSERVATION_OFF = 5, 63 }; 64 65 enum { 66 HALS_KBD_BL_SUPPORT_BIT = 4, 67 HALS_KBD_BL_STATE_BIT = 5, 68 HALS_USB_CHARGING_SUPPORT_BIT = 6, 69 HALS_USB_CHARGING_STATE_BIT = 7, 70 HALS_FNLOCK_SUPPORT_BIT = 9, 71 HALS_FNLOCK_STATE_BIT = 10, 72 HALS_HOTKEYS_PRIMARY_BIT = 11, 73 }; 74 75 enum { 76 SALS_KBD_BL_ON = 0x8, 77 SALS_KBD_BL_OFF = 0x9, 78 SALS_USB_CHARGING_ON = 0xa, 79 SALS_USB_CHARGING_OFF = 0xb, 80 SALS_FNLOCK_ON = 0xe, 81 SALS_FNLOCK_OFF = 0xf, 82 }; 83 84 enum { 85 VPCCMD_R_VPC1 = 0x10, 86 VPCCMD_R_BL_MAX, 87 VPCCMD_R_BL, 88 VPCCMD_W_BL, 89 VPCCMD_R_WIFI, 90 VPCCMD_W_WIFI, 91 VPCCMD_R_BT, 92 VPCCMD_W_BT, 93 VPCCMD_R_BL_POWER, 94 VPCCMD_R_NOVO, 95 VPCCMD_R_VPC2, 96 VPCCMD_R_TOUCHPAD, 97 VPCCMD_W_TOUCHPAD, 98 VPCCMD_R_CAMERA, 99 VPCCMD_W_CAMERA, 100 VPCCMD_R_3G, 101 VPCCMD_W_3G, 102 VPCCMD_R_ODD, /* 0x21 */ 103 VPCCMD_W_FAN, 104 VPCCMD_R_RF, 105 VPCCMD_W_RF, 106 VPCCMD_R_FAN = 0x2B, 107 VPCCMD_R_SPECIAL_BUTTONS = 0x31, 108 VPCCMD_W_BL_POWER = 0x33, 109 }; 110 111 struct ideapad_dytc_priv { 112 enum platform_profile_option current_profile; 113 struct platform_profile_handler pprof; 114 struct mutex mutex; /* protects the DYTC interface */ 115 struct ideapad_private *priv; 116 }; 117 118 struct ideapad_rfk_priv { 119 int dev; 120 struct ideapad_private *priv; 121 }; 122 123 struct ideapad_private { 124 struct acpi_device *adev; 125 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; 126 struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM]; 127 struct platform_device *platform_device; 128 struct input_dev *inputdev; 129 struct backlight_device *blightdev; 130 struct ideapad_dytc_priv *dytc; 131 struct dentry *debug; 132 unsigned long cfg; 133 const char *fnesc_guid; 134 struct { 135 bool conservation_mode : 1; 136 bool dytc : 1; 137 bool fan_mode : 1; 138 bool fn_lock : 1; 139 bool set_fn_lock_led : 1; 140 bool hw_rfkill_switch : 1; 141 bool kbd_bl : 1; 142 bool touchpad_ctrl_via_ec : 1; 143 bool usb_charging : 1; 144 } features; 145 struct { 146 bool initialized; 147 struct led_classdev led; 148 unsigned int last_brightness; 149 } kbd_bl; 150 }; 151 152 static bool no_bt_rfkill; 153 module_param(no_bt_rfkill, bool, 0444); 154 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); 155 156 static bool allow_v4_dytc; 157 module_param(allow_v4_dytc, bool, 0444); 158 MODULE_PARM_DESC(allow_v4_dytc, 159 "Enable DYTC version 4 platform-profile support. " 160 "If you need this please report this to: platform-driver-x86@vger.kernel.org"); 161 162 static bool hw_rfkill_switch; 163 module_param(hw_rfkill_switch, bool, 0444); 164 MODULE_PARM_DESC(hw_rfkill_switch, 165 "Enable rfkill support for laptops with a hw on/off wifi switch/slider. " 166 "If you need this please report this to: platform-driver-x86@vger.kernel.org"); 167 168 static bool set_fn_lock_led; 169 module_param(set_fn_lock_led, bool, 0444); 170 MODULE_PARM_DESC(set_fn_lock_led, 171 "Enable driver based updates of the fn-lock LED on fn-lock changes. " 172 "If you need this please report this to: platform-driver-x86@vger.kernel.org"); 173 174 /* 175 * ACPI Helpers 176 */ 177 #define IDEAPAD_EC_TIMEOUT 200 /* in ms */ 178 179 static int eval_int(acpi_handle handle, const char *name, unsigned long *res) 180 { 181 unsigned long long result; 182 acpi_status status; 183 184 status = acpi_evaluate_integer(handle, (char *)name, NULL, &result); 185 if (ACPI_FAILURE(status)) 186 return -EIO; 187 188 *res = result; 189 190 return 0; 191 } 192 193 static int exec_simple_method(acpi_handle handle, const char *name, unsigned long arg) 194 { 195 acpi_status status = acpi_execute_simple_method(handle, (char *)name, arg); 196 197 return ACPI_FAILURE(status) ? -EIO : 0; 198 } 199 200 static int eval_gbmd(acpi_handle handle, unsigned long *res) 201 { 202 return eval_int(handle, "GBMD", res); 203 } 204 205 static int exec_sbmc(acpi_handle handle, unsigned long arg) 206 { 207 return exec_simple_method(handle, "SBMC", arg); 208 } 209 210 static int eval_hals(acpi_handle handle, unsigned long *res) 211 { 212 return eval_int(handle, "HALS", res); 213 } 214 215 static int exec_sals(acpi_handle handle, unsigned long arg) 216 { 217 return exec_simple_method(handle, "SALS", arg); 218 } 219 220 static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, unsigned long *res) 221 { 222 struct acpi_object_list params; 223 unsigned long long result; 224 union acpi_object in_obj; 225 acpi_status status; 226 227 params.count = 1; 228 params.pointer = &in_obj; 229 in_obj.type = ACPI_TYPE_INTEGER; 230 in_obj.integer.value = arg; 231 232 status = acpi_evaluate_integer(handle, (char *)name, ¶ms, &result); 233 if (ACPI_FAILURE(status)) 234 return -EIO; 235 236 if (res) 237 *res = result; 238 239 return 0; 240 } 241 242 static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res) 243 { 244 return eval_int_with_arg(handle, "DYTC", cmd, res); 245 } 246 247 static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res) 248 { 249 return eval_int_with_arg(handle, "VPCR", cmd, res); 250 } 251 252 static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data) 253 { 254 struct acpi_object_list params; 255 union acpi_object in_obj[2]; 256 acpi_status status; 257 258 params.count = 2; 259 params.pointer = in_obj; 260 in_obj[0].type = ACPI_TYPE_INTEGER; 261 in_obj[0].integer.value = cmd; 262 in_obj[1].type = ACPI_TYPE_INTEGER; 263 in_obj[1].integer.value = data; 264 265 status = acpi_evaluate_object(handle, "VPCW", ¶ms, NULL); 266 if (ACPI_FAILURE(status)) 267 return -EIO; 268 269 return 0; 270 } 271 272 static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data) 273 { 274 unsigned long end_jiffies, val; 275 int err; 276 277 err = eval_vpcw(handle, 1, cmd); 278 if (err) 279 return err; 280 281 end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 282 283 while (time_before(jiffies, end_jiffies)) { 284 schedule(); 285 286 err = eval_vpcr(handle, 1, &val); 287 if (err) 288 return err; 289 290 if (val == 0) 291 return eval_vpcr(handle, 0, data); 292 } 293 294 acpi_handle_err(handle, "timeout in %s\n", __func__); 295 296 return -ETIMEDOUT; 297 } 298 299 static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data) 300 { 301 unsigned long end_jiffies, val; 302 int err; 303 304 err = eval_vpcw(handle, 0, data); 305 if (err) 306 return err; 307 308 err = eval_vpcw(handle, 1, cmd); 309 if (err) 310 return err; 311 312 end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 313 314 while (time_before(jiffies, end_jiffies)) { 315 schedule(); 316 317 err = eval_vpcr(handle, 1, &val); 318 if (err) 319 return err; 320 321 if (val == 0) 322 return 0; 323 } 324 325 acpi_handle_err(handle, "timeout in %s\n", __func__); 326 327 return -ETIMEDOUT; 328 } 329 330 /* 331 * debugfs 332 */ 333 static int debugfs_status_show(struct seq_file *s, void *data) 334 { 335 struct ideapad_private *priv = s->private; 336 unsigned long value; 337 338 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value)) 339 seq_printf(s, "Backlight max: %lu\n", value); 340 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value)) 341 seq_printf(s, "Backlight now: %lu\n", value); 342 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value)) 343 seq_printf(s, "BL power value: %s (%lu)\n", value ? "on" : "off", value); 344 345 seq_puts(s, "=====================\n"); 346 347 if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value)) 348 seq_printf(s, "Radio status: %s (%lu)\n", value ? "on" : "off", value); 349 if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value)) 350 seq_printf(s, "Wifi status: %s (%lu)\n", value ? "on" : "off", value); 351 if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value)) 352 seq_printf(s, "BT status: %s (%lu)\n", value ? "on" : "off", value); 353 if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value)) 354 seq_printf(s, "3G status: %s (%lu)\n", value ? "on" : "off", value); 355 356 seq_puts(s, "=====================\n"); 357 358 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) 359 seq_printf(s, "Touchpad status: %s (%lu)\n", value ? "on" : "off", value); 360 if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value)) 361 seq_printf(s, "Camera status: %s (%lu)\n", value ? "on" : "off", value); 362 363 seq_puts(s, "=====================\n"); 364 365 if (!eval_gbmd(priv->adev->handle, &value)) 366 seq_printf(s, "GBMD: %#010lx\n", value); 367 if (!eval_hals(priv->adev->handle, &value)) 368 seq_printf(s, "HALS: %#010lx\n", value); 369 370 return 0; 371 } 372 DEFINE_SHOW_ATTRIBUTE(debugfs_status); 373 374 static int debugfs_cfg_show(struct seq_file *s, void *data) 375 { 376 struct ideapad_private *priv = s->private; 377 378 seq_printf(s, "_CFG: %#010lx\n\n", priv->cfg); 379 380 seq_puts(s, "Capabilities:"); 381 if (test_bit(CFG_CAP_BT_BIT, &priv->cfg)) 382 seq_puts(s, " bluetooth"); 383 if (test_bit(CFG_CAP_3G_BIT, &priv->cfg)) 384 seq_puts(s, " 3G"); 385 if (test_bit(CFG_CAP_WIFI_BIT, &priv->cfg)) 386 seq_puts(s, " wifi"); 387 if (test_bit(CFG_CAP_CAM_BIT, &priv->cfg)) 388 seq_puts(s, " camera"); 389 if (test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg)) 390 seq_puts(s, " touchpad"); 391 seq_puts(s, "\n"); 392 393 seq_puts(s, "Graphics: "); 394 switch (priv->cfg & 0x700) { 395 case 0x100: 396 seq_puts(s, "Intel"); 397 break; 398 case 0x200: 399 seq_puts(s, "ATI"); 400 break; 401 case 0x300: 402 seq_puts(s, "Nvidia"); 403 break; 404 case 0x400: 405 seq_puts(s, "Intel and ATI"); 406 break; 407 case 0x500: 408 seq_puts(s, "Intel and Nvidia"); 409 break; 410 } 411 seq_puts(s, "\n"); 412 413 return 0; 414 } 415 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg); 416 417 static void ideapad_debugfs_init(struct ideapad_private *priv) 418 { 419 struct dentry *dir; 420 421 dir = debugfs_create_dir("ideapad", NULL); 422 priv->debug = dir; 423 424 debugfs_create_file("cfg", 0444, dir, priv, &debugfs_cfg_fops); 425 debugfs_create_file("status", 0444, dir, priv, &debugfs_status_fops); 426 } 427 428 static void ideapad_debugfs_exit(struct ideapad_private *priv) 429 { 430 debugfs_remove_recursive(priv->debug); 431 priv->debug = NULL; 432 } 433 434 /* 435 * sysfs 436 */ 437 static ssize_t camera_power_show(struct device *dev, 438 struct device_attribute *attr, 439 char *buf) 440 { 441 struct ideapad_private *priv = dev_get_drvdata(dev); 442 unsigned long result; 443 int err; 444 445 err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); 446 if (err) 447 return err; 448 449 return sysfs_emit(buf, "%d\n", !!result); 450 } 451 452 static ssize_t camera_power_store(struct device *dev, 453 struct device_attribute *attr, 454 const char *buf, size_t count) 455 { 456 struct ideapad_private *priv = dev_get_drvdata(dev); 457 bool state; 458 int err; 459 460 err = kstrtobool(buf, &state); 461 if (err) 462 return err; 463 464 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); 465 if (err) 466 return err; 467 468 return count; 469 } 470 471 static DEVICE_ATTR_RW(camera_power); 472 473 static ssize_t conservation_mode_show(struct device *dev, 474 struct device_attribute *attr, 475 char *buf) 476 { 477 struct ideapad_private *priv = dev_get_drvdata(dev); 478 unsigned long result; 479 int err; 480 481 err = eval_gbmd(priv->adev->handle, &result); 482 if (err) 483 return err; 484 485 return sysfs_emit(buf, "%d\n", !!test_bit(GBMD_CONSERVATION_STATE_BIT, &result)); 486 } 487 488 static ssize_t conservation_mode_store(struct device *dev, 489 struct device_attribute *attr, 490 const char *buf, size_t count) 491 { 492 struct ideapad_private *priv = dev_get_drvdata(dev); 493 bool state; 494 int err; 495 496 err = kstrtobool(buf, &state); 497 if (err) 498 return err; 499 500 err = exec_sbmc(priv->adev->handle, state ? SBMC_CONSERVATION_ON : SBMC_CONSERVATION_OFF); 501 if (err) 502 return err; 503 504 return count; 505 } 506 507 static DEVICE_ATTR_RW(conservation_mode); 508 509 static ssize_t fan_mode_show(struct device *dev, 510 struct device_attribute *attr, 511 char *buf) 512 { 513 struct ideapad_private *priv = dev_get_drvdata(dev); 514 unsigned long result; 515 int err; 516 517 err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); 518 if (err) 519 return err; 520 521 return sysfs_emit(buf, "%lu\n", result); 522 } 523 524 static ssize_t fan_mode_store(struct device *dev, 525 struct device_attribute *attr, 526 const char *buf, size_t count) 527 { 528 struct ideapad_private *priv = dev_get_drvdata(dev); 529 unsigned int state; 530 int err; 531 532 err = kstrtouint(buf, 0, &state); 533 if (err) 534 return err; 535 536 if (state > 4 || state == 3) 537 return -EINVAL; 538 539 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); 540 if (err) 541 return err; 542 543 return count; 544 } 545 546 static DEVICE_ATTR_RW(fan_mode); 547 548 static ssize_t fn_lock_show(struct device *dev, 549 struct device_attribute *attr, 550 char *buf) 551 { 552 struct ideapad_private *priv = dev_get_drvdata(dev); 553 unsigned long hals; 554 int err; 555 556 err = eval_hals(priv->adev->handle, &hals); 557 if (err) 558 return err; 559 560 return sysfs_emit(buf, "%d\n", !!test_bit(HALS_FNLOCK_STATE_BIT, &hals)); 561 } 562 563 static ssize_t fn_lock_store(struct device *dev, 564 struct device_attribute *attr, 565 const char *buf, size_t count) 566 { 567 struct ideapad_private *priv = dev_get_drvdata(dev); 568 bool state; 569 int err; 570 571 err = kstrtobool(buf, &state); 572 if (err) 573 return err; 574 575 err = exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF); 576 if (err) 577 return err; 578 579 return count; 580 } 581 582 static DEVICE_ATTR_RW(fn_lock); 583 584 static ssize_t touchpad_show(struct device *dev, 585 struct device_attribute *attr, 586 char *buf) 587 { 588 struct ideapad_private *priv = dev_get_drvdata(dev); 589 unsigned long result; 590 int err; 591 592 err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); 593 if (err) 594 return err; 595 596 return sysfs_emit(buf, "%d\n", !!result); 597 } 598 599 static ssize_t touchpad_store(struct device *dev, 600 struct device_attribute *attr, 601 const char *buf, size_t count) 602 { 603 struct ideapad_private *priv = dev_get_drvdata(dev); 604 bool state; 605 int err; 606 607 err = kstrtobool(buf, &state); 608 if (err) 609 return err; 610 611 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); 612 if (err) 613 return err; 614 615 return count; 616 } 617 618 static DEVICE_ATTR_RW(touchpad); 619 620 static ssize_t usb_charging_show(struct device *dev, 621 struct device_attribute *attr, 622 char *buf) 623 { 624 struct ideapad_private *priv = dev_get_drvdata(dev); 625 unsigned long hals; 626 int err; 627 628 err = eval_hals(priv->adev->handle, &hals); 629 if (err) 630 return err; 631 632 return sysfs_emit(buf, "%d\n", !!test_bit(HALS_USB_CHARGING_STATE_BIT, &hals)); 633 } 634 635 static ssize_t usb_charging_store(struct device *dev, 636 struct device_attribute *attr, 637 const char *buf, size_t count) 638 { 639 struct ideapad_private *priv = dev_get_drvdata(dev); 640 bool state; 641 int err; 642 643 err = kstrtobool(buf, &state); 644 if (err) 645 return err; 646 647 err = exec_sals(priv->adev->handle, state ? SALS_USB_CHARGING_ON : SALS_USB_CHARGING_OFF); 648 if (err) 649 return err; 650 651 return count; 652 } 653 654 static DEVICE_ATTR_RW(usb_charging); 655 656 static struct attribute *ideapad_attributes[] = { 657 &dev_attr_camera_power.attr, 658 &dev_attr_conservation_mode.attr, 659 &dev_attr_fan_mode.attr, 660 &dev_attr_fn_lock.attr, 661 &dev_attr_touchpad.attr, 662 &dev_attr_usb_charging.attr, 663 NULL 664 }; 665 666 static umode_t ideapad_is_visible(struct kobject *kobj, 667 struct attribute *attr, 668 int idx) 669 { 670 struct device *dev = kobj_to_dev(kobj); 671 struct ideapad_private *priv = dev_get_drvdata(dev); 672 bool supported = true; 673 674 if (attr == &dev_attr_camera_power.attr) 675 supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg); 676 else if (attr == &dev_attr_conservation_mode.attr) 677 supported = priv->features.conservation_mode; 678 else if (attr == &dev_attr_fan_mode.attr) 679 supported = priv->features.fan_mode; 680 else if (attr == &dev_attr_fn_lock.attr) 681 supported = priv->features.fn_lock; 682 else if (attr == &dev_attr_touchpad.attr) 683 supported = priv->features.touchpad_ctrl_via_ec && 684 test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg); 685 else if (attr == &dev_attr_usb_charging.attr) 686 supported = priv->features.usb_charging; 687 688 return supported ? attr->mode : 0; 689 } 690 691 static const struct attribute_group ideapad_attribute_group = { 692 .is_visible = ideapad_is_visible, 693 .attrs = ideapad_attributes 694 }; 695 696 /* 697 * DYTC Platform profile 698 */ 699 #define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */ 700 #define DYTC_CMD_SET 1 /* To enable/disable IC function mode */ 701 #define DYTC_CMD_GET 2 /* To get current IC function and mode */ 702 #define DYTC_CMD_RESET 0x1ff /* To reset back to default */ 703 704 #define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */ 705 #define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */ 706 #define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */ 707 708 #define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */ 709 #define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */ 710 711 #define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - function setting */ 712 #define DYTC_SET_MODE_BIT 16 /* Bits 16-19 - mode setting */ 713 #define DYTC_SET_VALID_BIT 20 /* Bit 20 - 1 = on, 0 = off */ 714 715 #define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */ 716 #define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */ 717 #define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */ 718 719 #define DYTC_MODE_PERFORM 2 /* High power mode aka performance */ 720 #define DYTC_MODE_LOW_POWER 3 /* Low power mode aka quiet */ 721 #define DYTC_MODE_BALANCE 0xF /* Default mode aka balanced */ 722 723 #define DYTC_SET_COMMAND(function, mode, on) \ 724 (DYTC_CMD_SET | (function) << DYTC_SET_FUNCTION_BIT | \ 725 (mode) << DYTC_SET_MODE_BIT | \ 726 (on) << DYTC_SET_VALID_BIT) 727 728 #define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0) 729 730 #define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1) 731 732 static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile) 733 { 734 switch (dytcmode) { 735 case DYTC_MODE_LOW_POWER: 736 *profile = PLATFORM_PROFILE_LOW_POWER; 737 break; 738 case DYTC_MODE_BALANCE: 739 *profile = PLATFORM_PROFILE_BALANCED; 740 break; 741 case DYTC_MODE_PERFORM: 742 *profile = PLATFORM_PROFILE_PERFORMANCE; 743 break; 744 default: /* Unknown mode */ 745 return -EINVAL; 746 } 747 748 return 0; 749 } 750 751 static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode) 752 { 753 switch (profile) { 754 case PLATFORM_PROFILE_LOW_POWER: 755 *perfmode = DYTC_MODE_LOW_POWER; 756 break; 757 case PLATFORM_PROFILE_BALANCED: 758 *perfmode = DYTC_MODE_BALANCE; 759 break; 760 case PLATFORM_PROFILE_PERFORMANCE: 761 *perfmode = DYTC_MODE_PERFORM; 762 break; 763 default: /* Unknown profile */ 764 return -EOPNOTSUPP; 765 } 766 767 return 0; 768 } 769 770 /* 771 * dytc_profile_get: Function to register with platform_profile 772 * handler. Returns current platform profile. 773 */ 774 static int dytc_profile_get(struct platform_profile_handler *pprof, 775 enum platform_profile_option *profile) 776 { 777 struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof); 778 779 *profile = dytc->current_profile; 780 return 0; 781 } 782 783 /* 784 * Helper function - check if we are in CQL mode and if we are 785 * - disable CQL, 786 * - run the command 787 * - enable CQL 788 * If not in CQL mode, just run the command 789 */ 790 static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd, 791 unsigned long *output) 792 { 793 int err, cmd_err, cur_funcmode; 794 795 /* Determine if we are in CQL mode. This alters the commands we do */ 796 err = eval_dytc(priv->adev->handle, DYTC_CMD_GET, output); 797 if (err) 798 return err; 799 800 cur_funcmode = (*output >> DYTC_GET_FUNCTION_BIT) & 0xF; 801 /* Check if we're OK to return immediately */ 802 if (cmd == DYTC_CMD_GET && cur_funcmode != DYTC_FUNCTION_CQL) 803 return 0; 804 805 if (cur_funcmode == DYTC_FUNCTION_CQL) { 806 err = eval_dytc(priv->adev->handle, DYTC_DISABLE_CQL, NULL); 807 if (err) 808 return err; 809 } 810 811 cmd_err = eval_dytc(priv->adev->handle, cmd, output); 812 /* Check return condition after we've restored CQL state */ 813 814 if (cur_funcmode == DYTC_FUNCTION_CQL) { 815 err = eval_dytc(priv->adev->handle, DYTC_ENABLE_CQL, NULL); 816 if (err) 817 return err; 818 } 819 820 return cmd_err; 821 } 822 823 /* 824 * dytc_profile_set: Function to register with platform_profile 825 * handler. Sets current platform profile. 826 */ 827 static int dytc_profile_set(struct platform_profile_handler *pprof, 828 enum platform_profile_option profile) 829 { 830 struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof); 831 struct ideapad_private *priv = dytc->priv; 832 unsigned long output; 833 int err; 834 835 err = mutex_lock_interruptible(&dytc->mutex); 836 if (err) 837 return err; 838 839 if (profile == PLATFORM_PROFILE_BALANCED) { 840 /* To get back to balanced mode we just issue a reset command */ 841 err = eval_dytc(priv->adev->handle, DYTC_CMD_RESET, NULL); 842 if (err) 843 goto unlock; 844 } else { 845 int perfmode; 846 847 err = convert_profile_to_dytc(profile, &perfmode); 848 if (err) 849 goto unlock; 850 851 /* Determine if we are in CQL mode. This alters the commands we do */ 852 err = dytc_cql_command(priv, DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), 853 &output); 854 if (err) 855 goto unlock; 856 } 857 858 /* Success - update current profile */ 859 dytc->current_profile = profile; 860 861 unlock: 862 mutex_unlock(&dytc->mutex); 863 864 return err; 865 } 866 867 static void dytc_profile_refresh(struct ideapad_private *priv) 868 { 869 enum platform_profile_option profile; 870 unsigned long output; 871 int err, perfmode; 872 873 mutex_lock(&priv->dytc->mutex); 874 err = dytc_cql_command(priv, DYTC_CMD_GET, &output); 875 mutex_unlock(&priv->dytc->mutex); 876 if (err) 877 return; 878 879 perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; 880 881 if (convert_dytc_to_profile(perfmode, &profile)) 882 return; 883 884 if (profile != priv->dytc->current_profile) { 885 priv->dytc->current_profile = profile; 886 platform_profile_notify(); 887 } 888 } 889 890 static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = { 891 { 892 /* Ideapad 5 Pro 16ACH6 */ 893 .matches = { 894 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 895 DMI_MATCH(DMI_PRODUCT_NAME, "82L5") 896 } 897 }, 898 { 899 /* Ideapad 5 15ITL05 */ 900 .matches = { 901 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 902 DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05") 903 } 904 }, 905 {} 906 }; 907 908 static int ideapad_dytc_profile_init(struct ideapad_private *priv) 909 { 910 int err, dytc_version; 911 unsigned long output; 912 913 if (!priv->features.dytc) 914 return -ENODEV; 915 916 err = eval_dytc(priv->adev->handle, DYTC_CMD_QUERY, &output); 917 /* For all other errors we can flag the failure */ 918 if (err) 919 return err; 920 921 /* Check DYTC is enabled and supports mode setting */ 922 if (!test_bit(DYTC_QUERY_ENABLE_BIT, &output)) { 923 dev_info(&priv->platform_device->dev, "DYTC_QUERY_ENABLE_BIT returned false\n"); 924 return -ENODEV; 925 } 926 927 dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; 928 929 if (dytc_version < 4) { 930 dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n"); 931 return -ENODEV; 932 } 933 934 if (dytc_version < 5 && 935 !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) { 936 dev_info(&priv->platform_device->dev, 937 "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n"); 938 return -ENODEV; 939 } 940 941 priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL); 942 if (!priv->dytc) 943 return -ENOMEM; 944 945 mutex_init(&priv->dytc->mutex); 946 947 priv->dytc->priv = priv; 948 priv->dytc->pprof.profile_get = dytc_profile_get; 949 priv->dytc->pprof.profile_set = dytc_profile_set; 950 951 /* Setup supported modes */ 952 set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices); 953 set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices); 954 set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices); 955 956 /* Create platform_profile structure and register */ 957 err = platform_profile_register(&priv->dytc->pprof); 958 if (err) 959 goto pp_reg_failed; 960 961 /* Ensure initial values are correct */ 962 dytc_profile_refresh(priv); 963 964 return 0; 965 966 pp_reg_failed: 967 mutex_destroy(&priv->dytc->mutex); 968 kfree(priv->dytc); 969 priv->dytc = NULL; 970 971 return err; 972 } 973 974 static void ideapad_dytc_profile_exit(struct ideapad_private *priv) 975 { 976 if (!priv->dytc) 977 return; 978 979 platform_profile_remove(); 980 mutex_destroy(&priv->dytc->mutex); 981 kfree(priv->dytc); 982 983 priv->dytc = NULL; 984 } 985 986 /* 987 * Rfkill 988 */ 989 struct ideapad_rfk_data { 990 char *name; 991 int cfgbit; 992 int opcode; 993 int type; 994 }; 995 996 static const struct ideapad_rfk_data ideapad_rfk_data[] = { 997 { "ideapad_wlan", CFG_CAP_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, 998 { "ideapad_bluetooth", CFG_CAP_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, 999 { "ideapad_3g", CFG_CAP_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, 1000 }; 1001 1002 static int ideapad_rfk_set(void *data, bool blocked) 1003 { 1004 struct ideapad_rfk_priv *priv = data; 1005 int opcode = ideapad_rfk_data[priv->dev].opcode; 1006 1007 return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); 1008 } 1009 1010 static const struct rfkill_ops ideapad_rfk_ops = { 1011 .set_block = ideapad_rfk_set, 1012 }; 1013 1014 static void ideapad_sync_rfk_state(struct ideapad_private *priv) 1015 { 1016 unsigned long hw_blocked = 0; 1017 int i; 1018 1019 if (priv->features.hw_rfkill_switch) { 1020 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 1021 return; 1022 hw_blocked = !hw_blocked; 1023 } 1024 1025 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1026 if (priv->rfk[i]) 1027 rfkill_set_hw_state(priv->rfk[i], hw_blocked); 1028 } 1029 1030 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) 1031 { 1032 unsigned long rf_enabled; 1033 int err; 1034 1035 if (no_bt_rfkill && ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH) { 1036 /* Force to enable bluetooth when no_bt_rfkill=1 */ 1037 write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1); 1038 return 0; 1039 } 1040 1041 priv->rfk_priv[dev].dev = dev; 1042 priv->rfk_priv[dev].priv = priv; 1043 1044 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, 1045 &priv->platform_device->dev, 1046 ideapad_rfk_data[dev].type, 1047 &ideapad_rfk_ops, 1048 &priv->rfk_priv[dev]); 1049 if (!priv->rfk[dev]) 1050 return -ENOMEM; 1051 1052 err = read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode - 1, &rf_enabled); 1053 if (err) 1054 rf_enabled = 1; 1055 1056 rfkill_init_sw_state(priv->rfk[dev], !rf_enabled); 1057 1058 err = rfkill_register(priv->rfk[dev]); 1059 if (err) 1060 rfkill_destroy(priv->rfk[dev]); 1061 1062 return err; 1063 } 1064 1065 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) 1066 { 1067 if (!priv->rfk[dev]) 1068 return; 1069 1070 rfkill_unregister(priv->rfk[dev]); 1071 rfkill_destroy(priv->rfk[dev]); 1072 } 1073 1074 /* 1075 * Platform device 1076 */ 1077 static int ideapad_sysfs_init(struct ideapad_private *priv) 1078 { 1079 return device_add_group(&priv->platform_device->dev, 1080 &ideapad_attribute_group); 1081 } 1082 1083 static void ideapad_sysfs_exit(struct ideapad_private *priv) 1084 { 1085 device_remove_group(&priv->platform_device->dev, 1086 &ideapad_attribute_group); 1087 } 1088 1089 /* 1090 * input device 1091 */ 1092 static const struct key_entry ideapad_keymap[] = { 1093 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, 1094 { KE_KEY, 7, { KEY_CAMERA } }, 1095 { KE_KEY, 8, { KEY_MICMUTE } }, 1096 { KE_KEY, 11, { KEY_F16 } }, 1097 { KE_KEY, 13, { KEY_WLAN } }, 1098 { KE_KEY, 16, { KEY_PROG1 } }, 1099 { KE_KEY, 17, { KEY_PROG2 } }, 1100 { KE_KEY, 64, { KEY_PROG3 } }, 1101 { KE_KEY, 65, { KEY_PROG4 } }, 1102 { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, 1103 { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, 1104 { KE_KEY, 128, { KEY_ESC } }, 1105 { KE_END }, 1106 }; 1107 1108 static int ideapad_input_init(struct ideapad_private *priv) 1109 { 1110 struct input_dev *inputdev; 1111 int err; 1112 1113 inputdev = input_allocate_device(); 1114 if (!inputdev) 1115 return -ENOMEM; 1116 1117 inputdev->name = "Ideapad extra buttons"; 1118 inputdev->phys = "ideapad/input0"; 1119 inputdev->id.bustype = BUS_HOST; 1120 inputdev->dev.parent = &priv->platform_device->dev; 1121 1122 err = sparse_keymap_setup(inputdev, ideapad_keymap, NULL); 1123 if (err) { 1124 dev_err(&priv->platform_device->dev, 1125 "Could not set up input device keymap: %d\n", err); 1126 goto err_free_dev; 1127 } 1128 1129 err = input_register_device(inputdev); 1130 if (err) { 1131 dev_err(&priv->platform_device->dev, 1132 "Could not register input device: %d\n", err); 1133 goto err_free_dev; 1134 } 1135 1136 priv->inputdev = inputdev; 1137 1138 return 0; 1139 1140 err_free_dev: 1141 input_free_device(inputdev); 1142 1143 return err; 1144 } 1145 1146 static void ideapad_input_exit(struct ideapad_private *priv) 1147 { 1148 input_unregister_device(priv->inputdev); 1149 priv->inputdev = NULL; 1150 } 1151 1152 static void ideapad_input_report(struct ideapad_private *priv, 1153 unsigned long scancode) 1154 { 1155 sparse_keymap_report_event(priv->inputdev, scancode, 1, true); 1156 } 1157 1158 static void ideapad_input_novokey(struct ideapad_private *priv) 1159 { 1160 unsigned long long_pressed; 1161 1162 if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) 1163 return; 1164 1165 if (long_pressed) 1166 ideapad_input_report(priv, 17); 1167 else 1168 ideapad_input_report(priv, 16); 1169 } 1170 1171 static void ideapad_check_special_buttons(struct ideapad_private *priv) 1172 { 1173 unsigned long bit, value; 1174 1175 if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) 1176 return; 1177 1178 for_each_set_bit (bit, &value, 16) { 1179 switch (bit) { 1180 case 6: /* Z570 */ 1181 case 0: /* Z580 */ 1182 /* Thermal Management button */ 1183 ideapad_input_report(priv, 65); 1184 break; 1185 case 1: 1186 /* OneKey Theater button */ 1187 ideapad_input_report(priv, 64); 1188 break; 1189 default: 1190 dev_info(&priv->platform_device->dev, 1191 "Unknown special button: %lu\n", bit); 1192 break; 1193 } 1194 } 1195 } 1196 1197 /* 1198 * backlight 1199 */ 1200 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) 1201 { 1202 struct ideapad_private *priv = bl_get_data(blightdev); 1203 unsigned long now; 1204 int err; 1205 1206 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1207 if (err) 1208 return err; 1209 1210 return now; 1211 } 1212 1213 static int ideapad_backlight_update_status(struct backlight_device *blightdev) 1214 { 1215 struct ideapad_private *priv = bl_get_data(blightdev); 1216 int err; 1217 1218 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL, 1219 blightdev->props.brightness); 1220 if (err) 1221 return err; 1222 1223 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER, 1224 blightdev->props.power != FB_BLANK_POWERDOWN); 1225 if (err) 1226 return err; 1227 1228 return 0; 1229 } 1230 1231 static const struct backlight_ops ideapad_backlight_ops = { 1232 .get_brightness = ideapad_backlight_get_brightness, 1233 .update_status = ideapad_backlight_update_status, 1234 }; 1235 1236 static int ideapad_backlight_init(struct ideapad_private *priv) 1237 { 1238 struct backlight_device *blightdev; 1239 struct backlight_properties props; 1240 unsigned long max, now, power; 1241 int err; 1242 1243 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max); 1244 if (err) 1245 return err; 1246 1247 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1248 if (err) 1249 return err; 1250 1251 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power); 1252 if (err) 1253 return err; 1254 1255 memset(&props, 0, sizeof(props)); 1256 1257 props.max_brightness = max; 1258 props.type = BACKLIGHT_PLATFORM; 1259 1260 blightdev = backlight_device_register("ideapad", 1261 &priv->platform_device->dev, 1262 priv, 1263 &ideapad_backlight_ops, 1264 &props); 1265 if (IS_ERR(blightdev)) { 1266 err = PTR_ERR(blightdev); 1267 dev_err(&priv->platform_device->dev, 1268 "Could not register backlight device: %d\n", err); 1269 return err; 1270 } 1271 1272 priv->blightdev = blightdev; 1273 blightdev->props.brightness = now; 1274 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1275 1276 backlight_update_status(blightdev); 1277 1278 return 0; 1279 } 1280 1281 static void ideapad_backlight_exit(struct ideapad_private *priv) 1282 { 1283 backlight_device_unregister(priv->blightdev); 1284 priv->blightdev = NULL; 1285 } 1286 1287 static void ideapad_backlight_notify_power(struct ideapad_private *priv) 1288 { 1289 struct backlight_device *blightdev = priv->blightdev; 1290 unsigned long power; 1291 1292 if (!blightdev) 1293 return; 1294 1295 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) 1296 return; 1297 1298 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1299 } 1300 1301 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) 1302 { 1303 unsigned long now; 1304 1305 /* if we control brightness via acpi video driver */ 1306 if (!priv->blightdev) 1307 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1308 else 1309 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY); 1310 } 1311 1312 /* 1313 * keyboard backlight 1314 */ 1315 static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv) 1316 { 1317 unsigned long hals; 1318 int err; 1319 1320 err = eval_hals(priv->adev->handle, &hals); 1321 if (err) 1322 return err; 1323 1324 return !!test_bit(HALS_KBD_BL_STATE_BIT, &hals); 1325 } 1326 1327 static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev) 1328 { 1329 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led); 1330 1331 return ideapad_kbd_bl_brightness_get(priv); 1332 } 1333 1334 static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness) 1335 { 1336 int err = exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF); 1337 1338 if (err) 1339 return err; 1340 1341 priv->kbd_bl.last_brightness = brightness; 1342 1343 return 0; 1344 } 1345 1346 static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev, 1347 enum led_brightness brightness) 1348 { 1349 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led); 1350 1351 return ideapad_kbd_bl_brightness_set(priv, brightness); 1352 } 1353 1354 static void ideapad_kbd_bl_notify(struct ideapad_private *priv) 1355 { 1356 int brightness; 1357 1358 if (!priv->kbd_bl.initialized) 1359 return; 1360 1361 brightness = ideapad_kbd_bl_brightness_get(priv); 1362 if (brightness < 0) 1363 return; 1364 1365 if (brightness == priv->kbd_bl.last_brightness) 1366 return; 1367 1368 priv->kbd_bl.last_brightness = brightness; 1369 1370 led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness); 1371 } 1372 1373 static int ideapad_kbd_bl_init(struct ideapad_private *priv) 1374 { 1375 int brightness, err; 1376 1377 if (!priv->features.kbd_bl) 1378 return -ENODEV; 1379 1380 if (WARN_ON(priv->kbd_bl.initialized)) 1381 return -EEXIST; 1382 1383 brightness = ideapad_kbd_bl_brightness_get(priv); 1384 if (brightness < 0) 1385 return brightness; 1386 1387 priv->kbd_bl.last_brightness = brightness; 1388 1389 priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT; 1390 priv->kbd_bl.led.max_brightness = 1; 1391 priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get; 1392 priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set; 1393 priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED; 1394 1395 err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led); 1396 if (err) 1397 return err; 1398 1399 priv->kbd_bl.initialized = true; 1400 1401 return 0; 1402 } 1403 1404 static void ideapad_kbd_bl_exit(struct ideapad_private *priv) 1405 { 1406 if (!priv->kbd_bl.initialized) 1407 return; 1408 1409 priv->kbd_bl.initialized = false; 1410 1411 led_classdev_unregister(&priv->kbd_bl.led); 1412 } 1413 1414 /* 1415 * module init/exit 1416 */ 1417 static void ideapad_sync_touchpad_state(struct ideapad_private *priv) 1418 { 1419 unsigned long value; 1420 1421 if (!priv->features.touchpad_ctrl_via_ec) 1422 return; 1423 1424 /* Without reading from EC touchpad LED doesn't switch state */ 1425 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { 1426 unsigned char param; 1427 /* 1428 * Some IdeaPads don't really turn off touchpad - they only 1429 * switch the LED state. We (de)activate KBC AUX port to turn 1430 * touchpad off and on. We send KEY_TOUCHPAD_OFF and 1431 * KEY_TOUCHPAD_ON to not to get out of sync with LED 1432 */ 1433 i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE); 1434 ideapad_input_report(priv, value ? 67 : 66); 1435 sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad"); 1436 } 1437 } 1438 1439 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) 1440 { 1441 struct ideapad_private *priv = data; 1442 unsigned long vpc1, vpc2, bit; 1443 1444 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) 1445 return; 1446 1447 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) 1448 return; 1449 1450 vpc1 = (vpc2 << 8) | vpc1; 1451 1452 for_each_set_bit (bit, &vpc1, 16) { 1453 switch (bit) { 1454 case 13: 1455 case 11: 1456 case 8: 1457 case 7: 1458 case 6: 1459 ideapad_input_report(priv, bit); 1460 break; 1461 case 10: 1462 /* 1463 * This event gets send on a Yoga 300-11IBR when the EC 1464 * believes that the device has changed between laptop/ 1465 * tent/stand/tablet mode. The EC relies on getting 1466 * angle info from 2 accelerometers through a special 1467 * windows service calling a DSM on the DUAL250E ACPI- 1468 * device. Linux does not do this, making the laptop/ 1469 * tent/stand/tablet mode info unreliable, so we simply 1470 * ignore these events. 1471 */ 1472 break; 1473 case 9: 1474 ideapad_sync_rfk_state(priv); 1475 break; 1476 case 5: 1477 ideapad_sync_touchpad_state(priv); 1478 break; 1479 case 4: 1480 ideapad_backlight_notify_brightness(priv); 1481 break; 1482 case 3: 1483 ideapad_input_novokey(priv); 1484 break; 1485 case 2: 1486 ideapad_backlight_notify_power(priv); 1487 break; 1488 case 1: 1489 /* 1490 * Some IdeaPads report event 1 every ~20 1491 * seconds while on battery power; some 1492 * report this when changing to/from tablet 1493 * mode; some report this when the keyboard 1494 * backlight has changed. 1495 */ 1496 ideapad_kbd_bl_notify(priv); 1497 break; 1498 case 0: 1499 ideapad_check_special_buttons(priv); 1500 break; 1501 default: 1502 dev_info(&priv->platform_device->dev, 1503 "Unknown event: %lu\n", bit); 1504 } 1505 } 1506 } 1507 1508 #if IS_ENABLED(CONFIG_ACPI_WMI) 1509 static void ideapad_wmi_notify(u32 value, void *context) 1510 { 1511 struct ideapad_private *priv = context; 1512 unsigned long result; 1513 1514 switch (value) { 1515 case 128: 1516 ideapad_input_report(priv, value); 1517 break; 1518 case 208: 1519 if (!priv->features.set_fn_lock_led) 1520 break; 1521 1522 if (!eval_hals(priv->adev->handle, &result)) { 1523 bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result); 1524 1525 exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF); 1526 } 1527 break; 1528 default: 1529 dev_info(&priv->platform_device->dev, 1530 "Unknown WMI event: %u\n", value); 1531 } 1532 } 1533 #endif 1534 1535 /* On some models we need to call exec_sals(SALS_FNLOCK_ON/OFF) to set the LED */ 1536 static const struct dmi_system_id set_fn_lock_led_list[] = { 1537 { 1538 /* https://bugzilla.kernel.org/show_bug.cgi?id=212671 */ 1539 .matches = { 1540 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1541 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion R7000P2020H"), 1542 } 1543 }, 1544 {} 1545 }; 1546 1547 /* 1548 * Some ideapads have a hardware rfkill switch, but most do not have one. 1549 * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill, 1550 * switch causing ideapad_laptop to wrongly report all radios as hw-blocked. 1551 * There used to be a long list of DMI ids for models without a hw rfkill 1552 * switch here, but that resulted in playing whack a mole. 1553 * More importantly wrongly reporting the wifi radio as hw-blocked, results in 1554 * non working wifi. Whereas not reporting it hw-blocked, when it actually is 1555 * hw-blocked results in an empty SSID list, which is a much more benign 1556 * failure mode. 1557 * So the default now is the much safer option of assuming there is no 1558 * hardware rfkill switch. This default also actually matches most hardware, 1559 * since having a hw rfkill switch is quite rare on modern hardware, so this 1560 * also leads to a much shorter list. 1561 */ 1562 static const struct dmi_system_id hw_rfkill_list[] = { 1563 {} 1564 }; 1565 1566 static const struct dmi_system_id no_touchpad_switch_list[] = { 1567 { 1568 .ident = "Lenovo Yoga 3 Pro 1370", 1569 .matches = { 1570 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1571 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"), 1572 }, 1573 }, 1574 { 1575 .ident = "ZhaoYang K4e-IML", 1576 .matches = { 1577 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1578 DMI_MATCH(DMI_PRODUCT_VERSION, "ZhaoYang K4e-IML"), 1579 }, 1580 }, 1581 {} 1582 }; 1583 1584 static void ideapad_check_features(struct ideapad_private *priv) 1585 { 1586 acpi_handle handle = priv->adev->handle; 1587 unsigned long val; 1588 1589 priv->features.set_fn_lock_led = 1590 set_fn_lock_led || dmi_check_system(set_fn_lock_led_list); 1591 priv->features.hw_rfkill_switch = 1592 hw_rfkill_switch || dmi_check_system(hw_rfkill_list); 1593 1594 /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */ 1595 if (acpi_dev_present("ELAN0634", NULL, -1)) 1596 priv->features.touchpad_ctrl_via_ec = 0; 1597 else if (dmi_check_system(no_touchpad_switch_list)) 1598 priv->features.touchpad_ctrl_via_ec = 0; 1599 else 1600 priv->features.touchpad_ctrl_via_ec = 1; 1601 1602 if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) 1603 priv->features.fan_mode = true; 1604 1605 if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC")) 1606 priv->features.conservation_mode = true; 1607 1608 if (acpi_has_method(handle, "DYTC")) 1609 priv->features.dytc = true; 1610 1611 if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) { 1612 if (!eval_hals(handle, &val)) { 1613 if (test_bit(HALS_FNLOCK_SUPPORT_BIT, &val)) 1614 priv->features.fn_lock = true; 1615 1616 if (test_bit(HALS_KBD_BL_SUPPORT_BIT, &val)) 1617 priv->features.kbd_bl = true; 1618 1619 if (test_bit(HALS_USB_CHARGING_SUPPORT_BIT, &val)) 1620 priv->features.usb_charging = true; 1621 } 1622 } 1623 } 1624 1625 static int ideapad_acpi_add(struct platform_device *pdev) 1626 { 1627 struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); 1628 struct ideapad_private *priv; 1629 acpi_status status; 1630 unsigned long cfg; 1631 int err, i; 1632 1633 if (!adev || eval_int(adev->handle, "_CFG", &cfg)) 1634 return -ENODEV; 1635 1636 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1637 if (!priv) 1638 return -ENOMEM; 1639 1640 dev_set_drvdata(&pdev->dev, priv); 1641 1642 priv->cfg = cfg; 1643 priv->adev = adev; 1644 priv->platform_device = pdev; 1645 1646 ideapad_check_features(priv); 1647 1648 err = ideapad_sysfs_init(priv); 1649 if (err) 1650 return err; 1651 1652 ideapad_debugfs_init(priv); 1653 1654 err = ideapad_input_init(priv); 1655 if (err) 1656 goto input_failed; 1657 1658 err = ideapad_kbd_bl_init(priv); 1659 if (err) { 1660 if (err != -ENODEV) 1661 dev_warn(&pdev->dev, "Could not set up keyboard backlight LED: %d\n", err); 1662 else 1663 dev_info(&pdev->dev, "Keyboard backlight control not available\n"); 1664 } 1665 1666 /* 1667 * On some models without a hw-switch (the yoga 2 13 at least) 1668 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. 1669 */ 1670 if (!priv->features.hw_rfkill_switch) 1671 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); 1672 1673 /* The same for Touchpad */ 1674 if (!priv->features.touchpad_ctrl_via_ec) 1675 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1); 1676 1677 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1678 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 1679 ideapad_register_rfkill(priv, i); 1680 1681 ideapad_sync_rfk_state(priv); 1682 ideapad_sync_touchpad_state(priv); 1683 1684 err = ideapad_dytc_profile_init(priv); 1685 if (err) { 1686 if (err != -ENODEV) 1687 dev_warn(&pdev->dev, "Could not set up DYTC interface: %d\n", err); 1688 else 1689 dev_info(&pdev->dev, "DYTC interface is not available\n"); 1690 } 1691 1692 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { 1693 err = ideapad_backlight_init(priv); 1694 if (err && err != -ENODEV) 1695 goto backlight_failed; 1696 } 1697 1698 status = acpi_install_notify_handler(adev->handle, 1699 ACPI_DEVICE_NOTIFY, 1700 ideapad_acpi_notify, priv); 1701 if (ACPI_FAILURE(status)) { 1702 err = -EIO; 1703 goto notification_failed; 1704 } 1705 1706 #if IS_ENABLED(CONFIG_ACPI_WMI) 1707 for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) { 1708 status = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i], 1709 ideapad_wmi_notify, priv); 1710 if (ACPI_SUCCESS(status)) { 1711 priv->fnesc_guid = ideapad_wmi_fnesc_events[i]; 1712 break; 1713 } 1714 } 1715 1716 if (ACPI_FAILURE(status) && status != AE_NOT_EXIST) { 1717 err = -EIO; 1718 goto notification_failed_wmi; 1719 } 1720 #endif 1721 1722 return 0; 1723 1724 #if IS_ENABLED(CONFIG_ACPI_WMI) 1725 notification_failed_wmi: 1726 acpi_remove_notify_handler(priv->adev->handle, 1727 ACPI_DEVICE_NOTIFY, 1728 ideapad_acpi_notify); 1729 #endif 1730 1731 notification_failed: 1732 ideapad_backlight_exit(priv); 1733 1734 backlight_failed: 1735 ideapad_dytc_profile_exit(priv); 1736 1737 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1738 ideapad_unregister_rfkill(priv, i); 1739 1740 ideapad_kbd_bl_exit(priv); 1741 ideapad_input_exit(priv); 1742 1743 input_failed: 1744 ideapad_debugfs_exit(priv); 1745 ideapad_sysfs_exit(priv); 1746 1747 return err; 1748 } 1749 1750 static int ideapad_acpi_remove(struct platform_device *pdev) 1751 { 1752 struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); 1753 int i; 1754 1755 #if IS_ENABLED(CONFIG_ACPI_WMI) 1756 if (priv->fnesc_guid) 1757 wmi_remove_notify_handler(priv->fnesc_guid); 1758 #endif 1759 1760 acpi_remove_notify_handler(priv->adev->handle, 1761 ACPI_DEVICE_NOTIFY, 1762 ideapad_acpi_notify); 1763 1764 ideapad_backlight_exit(priv); 1765 ideapad_dytc_profile_exit(priv); 1766 1767 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1768 ideapad_unregister_rfkill(priv, i); 1769 1770 ideapad_kbd_bl_exit(priv); 1771 ideapad_input_exit(priv); 1772 ideapad_debugfs_exit(priv); 1773 ideapad_sysfs_exit(priv); 1774 1775 return 0; 1776 } 1777 1778 #ifdef CONFIG_PM_SLEEP 1779 static int ideapad_acpi_resume(struct device *dev) 1780 { 1781 struct ideapad_private *priv = dev_get_drvdata(dev); 1782 1783 ideapad_sync_rfk_state(priv); 1784 ideapad_sync_touchpad_state(priv); 1785 1786 if (priv->dytc) 1787 dytc_profile_refresh(priv); 1788 1789 return 0; 1790 } 1791 #endif 1792 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); 1793 1794 static const struct acpi_device_id ideapad_device_ids[] = { 1795 {"VPC2004", 0}, 1796 {"", 0}, 1797 }; 1798 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); 1799 1800 static struct platform_driver ideapad_acpi_driver = { 1801 .probe = ideapad_acpi_add, 1802 .remove = ideapad_acpi_remove, 1803 .driver = { 1804 .name = "ideapad_acpi", 1805 .pm = &ideapad_pm, 1806 .acpi_match_table = ACPI_PTR(ideapad_device_ids), 1807 }, 1808 }; 1809 1810 module_platform_driver(ideapad_acpi_driver); 1811 1812 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 1813 MODULE_DESCRIPTION("IdeaPad ACPI Extras"); 1814 MODULE_LICENSE("GPL"); 1815