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