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