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 int ideapad_dytc_profile_init(struct ideapad_private *priv) 872 { 873 int err, dytc_version; 874 unsigned long output; 875 876 if (!priv->features.dytc) 877 return -ENODEV; 878 879 err = eval_dytc(priv->adev->handle, DYTC_CMD_QUERY, &output); 880 /* For all other errors we can flag the failure */ 881 if (err) 882 return err; 883 884 /* Check DYTC is enabled and supports mode setting */ 885 if (!test_bit(DYTC_QUERY_ENABLE_BIT, &output)) 886 return -ENODEV; 887 888 dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; 889 if (dytc_version < 5) 890 return -ENODEV; 891 892 priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL); 893 if (!priv->dytc) 894 return -ENOMEM; 895 896 mutex_init(&priv->dytc->mutex); 897 898 priv->dytc->priv = priv; 899 priv->dytc->pprof.profile_get = dytc_profile_get; 900 priv->dytc->pprof.profile_set = dytc_profile_set; 901 902 /* Setup supported modes */ 903 set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices); 904 set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices); 905 set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices); 906 907 /* Create platform_profile structure and register */ 908 err = platform_profile_register(&priv->dytc->pprof); 909 if (err) 910 goto pp_reg_failed; 911 912 /* Ensure initial values are correct */ 913 dytc_profile_refresh(priv); 914 915 return 0; 916 917 pp_reg_failed: 918 mutex_destroy(&priv->dytc->mutex); 919 kfree(priv->dytc); 920 priv->dytc = NULL; 921 922 return err; 923 } 924 925 static void ideapad_dytc_profile_exit(struct ideapad_private *priv) 926 { 927 if (!priv->dytc) 928 return; 929 930 platform_profile_remove(); 931 mutex_destroy(&priv->dytc->mutex); 932 kfree(priv->dytc); 933 934 priv->dytc = NULL; 935 } 936 937 /* 938 * Rfkill 939 */ 940 struct ideapad_rfk_data { 941 char *name; 942 int cfgbit; 943 int opcode; 944 int type; 945 }; 946 947 static const struct ideapad_rfk_data ideapad_rfk_data[] = { 948 { "ideapad_wlan", CFG_CAP_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, 949 { "ideapad_bluetooth", CFG_CAP_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, 950 { "ideapad_3g", CFG_CAP_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, 951 }; 952 953 static int ideapad_rfk_set(void *data, bool blocked) 954 { 955 struct ideapad_rfk_priv *priv = data; 956 int opcode = ideapad_rfk_data[priv->dev].opcode; 957 958 return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); 959 } 960 961 static const struct rfkill_ops ideapad_rfk_ops = { 962 .set_block = ideapad_rfk_set, 963 }; 964 965 static void ideapad_sync_rfk_state(struct ideapad_private *priv) 966 { 967 unsigned long hw_blocked = 0; 968 int i; 969 970 if (priv->features.hw_rfkill_switch) { 971 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 972 return; 973 hw_blocked = !hw_blocked; 974 } 975 976 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 977 if (priv->rfk[i]) 978 rfkill_set_hw_state(priv->rfk[i], hw_blocked); 979 } 980 981 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) 982 { 983 unsigned long rf_enabled; 984 int err; 985 986 if (no_bt_rfkill && ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH) { 987 /* Force to enable bluetooth when no_bt_rfkill=1 */ 988 write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1); 989 return 0; 990 } 991 992 priv->rfk_priv[dev].dev = dev; 993 priv->rfk_priv[dev].priv = priv; 994 995 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, 996 &priv->platform_device->dev, 997 ideapad_rfk_data[dev].type, 998 &ideapad_rfk_ops, 999 &priv->rfk_priv[dev]); 1000 if (!priv->rfk[dev]) 1001 return -ENOMEM; 1002 1003 err = read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode - 1, &rf_enabled); 1004 if (err) 1005 rf_enabled = 1; 1006 1007 rfkill_init_sw_state(priv->rfk[dev], !rf_enabled); 1008 1009 err = rfkill_register(priv->rfk[dev]); 1010 if (err) 1011 rfkill_destroy(priv->rfk[dev]); 1012 1013 return err; 1014 } 1015 1016 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) 1017 { 1018 if (!priv->rfk[dev]) 1019 return; 1020 1021 rfkill_unregister(priv->rfk[dev]); 1022 rfkill_destroy(priv->rfk[dev]); 1023 } 1024 1025 /* 1026 * Platform device 1027 */ 1028 static int ideapad_sysfs_init(struct ideapad_private *priv) 1029 { 1030 return device_add_group(&priv->platform_device->dev, 1031 &ideapad_attribute_group); 1032 } 1033 1034 static void ideapad_sysfs_exit(struct ideapad_private *priv) 1035 { 1036 device_remove_group(&priv->platform_device->dev, 1037 &ideapad_attribute_group); 1038 } 1039 1040 /* 1041 * input device 1042 */ 1043 static const struct key_entry ideapad_keymap[] = { 1044 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, 1045 { KE_KEY, 7, { KEY_CAMERA } }, 1046 { KE_KEY, 8, { KEY_MICMUTE } }, 1047 { KE_KEY, 11, { KEY_F16 } }, 1048 { KE_KEY, 13, { KEY_WLAN } }, 1049 { KE_KEY, 16, { KEY_PROG1 } }, 1050 { KE_KEY, 17, { KEY_PROG2 } }, 1051 { KE_KEY, 64, { KEY_PROG3 } }, 1052 { KE_KEY, 65, { KEY_PROG4 } }, 1053 { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, 1054 { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, 1055 { KE_KEY, 128, { KEY_ESC } }, 1056 { KE_END }, 1057 }; 1058 1059 static int ideapad_input_init(struct ideapad_private *priv) 1060 { 1061 struct input_dev *inputdev; 1062 int err; 1063 1064 inputdev = input_allocate_device(); 1065 if (!inputdev) 1066 return -ENOMEM; 1067 1068 inputdev->name = "Ideapad extra buttons"; 1069 inputdev->phys = "ideapad/input0"; 1070 inputdev->id.bustype = BUS_HOST; 1071 inputdev->dev.parent = &priv->platform_device->dev; 1072 1073 err = sparse_keymap_setup(inputdev, ideapad_keymap, NULL); 1074 if (err) { 1075 dev_err(&priv->platform_device->dev, 1076 "Could not set up input device keymap: %d\n", err); 1077 goto err_free_dev; 1078 } 1079 1080 err = input_register_device(inputdev); 1081 if (err) { 1082 dev_err(&priv->platform_device->dev, 1083 "Could not register input device: %d\n", err); 1084 goto err_free_dev; 1085 } 1086 1087 priv->inputdev = inputdev; 1088 1089 return 0; 1090 1091 err_free_dev: 1092 input_free_device(inputdev); 1093 1094 return err; 1095 } 1096 1097 static void ideapad_input_exit(struct ideapad_private *priv) 1098 { 1099 input_unregister_device(priv->inputdev); 1100 priv->inputdev = NULL; 1101 } 1102 1103 static void ideapad_input_report(struct ideapad_private *priv, 1104 unsigned long scancode) 1105 { 1106 sparse_keymap_report_event(priv->inputdev, scancode, 1, true); 1107 } 1108 1109 static void ideapad_input_novokey(struct ideapad_private *priv) 1110 { 1111 unsigned long long_pressed; 1112 1113 if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) 1114 return; 1115 1116 if (long_pressed) 1117 ideapad_input_report(priv, 17); 1118 else 1119 ideapad_input_report(priv, 16); 1120 } 1121 1122 static void ideapad_check_special_buttons(struct ideapad_private *priv) 1123 { 1124 unsigned long bit, value; 1125 1126 if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) 1127 return; 1128 1129 for_each_set_bit (bit, &value, 16) { 1130 switch (bit) { 1131 case 6: /* Z570 */ 1132 case 0: /* Z580 */ 1133 /* Thermal Management button */ 1134 ideapad_input_report(priv, 65); 1135 break; 1136 case 1: 1137 /* OneKey Theater button */ 1138 ideapad_input_report(priv, 64); 1139 break; 1140 default: 1141 dev_info(&priv->platform_device->dev, 1142 "Unknown special button: %lu\n", bit); 1143 break; 1144 } 1145 } 1146 } 1147 1148 /* 1149 * backlight 1150 */ 1151 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) 1152 { 1153 struct ideapad_private *priv = bl_get_data(blightdev); 1154 unsigned long now; 1155 int err; 1156 1157 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1158 if (err) 1159 return err; 1160 1161 return now; 1162 } 1163 1164 static int ideapad_backlight_update_status(struct backlight_device *blightdev) 1165 { 1166 struct ideapad_private *priv = bl_get_data(blightdev); 1167 int err; 1168 1169 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL, 1170 blightdev->props.brightness); 1171 if (err) 1172 return err; 1173 1174 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER, 1175 blightdev->props.power != FB_BLANK_POWERDOWN); 1176 if (err) 1177 return err; 1178 1179 return 0; 1180 } 1181 1182 static const struct backlight_ops ideapad_backlight_ops = { 1183 .get_brightness = ideapad_backlight_get_brightness, 1184 .update_status = ideapad_backlight_update_status, 1185 }; 1186 1187 static int ideapad_backlight_init(struct ideapad_private *priv) 1188 { 1189 struct backlight_device *blightdev; 1190 struct backlight_properties props; 1191 unsigned long max, now, power; 1192 int err; 1193 1194 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max); 1195 if (err) 1196 return err; 1197 1198 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1199 if (err) 1200 return err; 1201 1202 err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power); 1203 if (err) 1204 return err; 1205 1206 memset(&props, 0, sizeof(props)); 1207 1208 props.max_brightness = max; 1209 props.type = BACKLIGHT_PLATFORM; 1210 1211 blightdev = backlight_device_register("ideapad", 1212 &priv->platform_device->dev, 1213 priv, 1214 &ideapad_backlight_ops, 1215 &props); 1216 if (IS_ERR(blightdev)) { 1217 err = PTR_ERR(blightdev); 1218 dev_err(&priv->platform_device->dev, 1219 "Could not register backlight device: %d\n", err); 1220 return err; 1221 } 1222 1223 priv->blightdev = blightdev; 1224 blightdev->props.brightness = now; 1225 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1226 1227 backlight_update_status(blightdev); 1228 1229 return 0; 1230 } 1231 1232 static void ideapad_backlight_exit(struct ideapad_private *priv) 1233 { 1234 backlight_device_unregister(priv->blightdev); 1235 priv->blightdev = NULL; 1236 } 1237 1238 static void ideapad_backlight_notify_power(struct ideapad_private *priv) 1239 { 1240 struct backlight_device *blightdev = priv->blightdev; 1241 unsigned long power; 1242 1243 if (!blightdev) 1244 return; 1245 1246 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) 1247 return; 1248 1249 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1250 } 1251 1252 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) 1253 { 1254 unsigned long now; 1255 1256 /* if we control brightness via acpi video driver */ 1257 if (!priv->blightdev) 1258 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); 1259 else 1260 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY); 1261 } 1262 1263 /* 1264 * keyboard backlight 1265 */ 1266 static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv) 1267 { 1268 unsigned long hals; 1269 int err; 1270 1271 err = eval_hals(priv->adev->handle, &hals); 1272 if (err) 1273 return err; 1274 1275 return !!test_bit(HALS_KBD_BL_STATE_BIT, &hals); 1276 } 1277 1278 static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev) 1279 { 1280 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led); 1281 1282 return ideapad_kbd_bl_brightness_get(priv); 1283 } 1284 1285 static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness) 1286 { 1287 int err = exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF); 1288 1289 if (err) 1290 return err; 1291 1292 priv->kbd_bl.last_brightness = brightness; 1293 1294 return 0; 1295 } 1296 1297 static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev, 1298 enum led_brightness brightness) 1299 { 1300 struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led); 1301 1302 return ideapad_kbd_bl_brightness_set(priv, brightness); 1303 } 1304 1305 static void ideapad_kbd_bl_notify(struct ideapad_private *priv) 1306 { 1307 int brightness; 1308 1309 if (!priv->kbd_bl.initialized) 1310 return; 1311 1312 brightness = ideapad_kbd_bl_brightness_get(priv); 1313 if (brightness < 0) 1314 return; 1315 1316 if (brightness == priv->kbd_bl.last_brightness) 1317 return; 1318 1319 priv->kbd_bl.last_brightness = brightness; 1320 1321 led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness); 1322 } 1323 1324 static int ideapad_kbd_bl_init(struct ideapad_private *priv) 1325 { 1326 int brightness, err; 1327 1328 if (!priv->features.kbd_bl) 1329 return -ENODEV; 1330 1331 if (WARN_ON(priv->kbd_bl.initialized)) 1332 return -EEXIST; 1333 1334 brightness = ideapad_kbd_bl_brightness_get(priv); 1335 if (brightness < 0) 1336 return brightness; 1337 1338 priv->kbd_bl.last_brightness = brightness; 1339 1340 priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT; 1341 priv->kbd_bl.led.max_brightness = 1; 1342 priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get; 1343 priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set; 1344 priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED; 1345 1346 err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led); 1347 if (err) 1348 return err; 1349 1350 priv->kbd_bl.initialized = true; 1351 1352 return 0; 1353 } 1354 1355 static void ideapad_kbd_bl_exit(struct ideapad_private *priv) 1356 { 1357 if (!priv->kbd_bl.initialized) 1358 return; 1359 1360 priv->kbd_bl.initialized = false; 1361 1362 led_classdev_unregister(&priv->kbd_bl.led); 1363 } 1364 1365 /* 1366 * module init/exit 1367 */ 1368 static void ideapad_sync_touchpad_state(struct ideapad_private *priv) 1369 { 1370 unsigned long value; 1371 1372 if (!priv->features.touchpad_ctrl_via_ec) 1373 return; 1374 1375 /* Without reading from EC touchpad LED doesn't switch state */ 1376 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { 1377 unsigned char param; 1378 /* 1379 * Some IdeaPads don't really turn off touchpad - they only 1380 * switch the LED state. We (de)activate KBC AUX port to turn 1381 * touchpad off and on. We send KEY_TOUCHPAD_OFF and 1382 * KEY_TOUCHPAD_ON to not to get out of sync with LED 1383 */ 1384 i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE); 1385 ideapad_input_report(priv, value ? 67 : 66); 1386 sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad"); 1387 } 1388 } 1389 1390 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) 1391 { 1392 struct ideapad_private *priv = data; 1393 unsigned long vpc1, vpc2, bit; 1394 1395 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) 1396 return; 1397 1398 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) 1399 return; 1400 1401 vpc1 = (vpc2 << 8) | vpc1; 1402 1403 for_each_set_bit (bit, &vpc1, 16) { 1404 switch (bit) { 1405 case 13: 1406 case 11: 1407 case 8: 1408 case 7: 1409 case 6: 1410 ideapad_input_report(priv, bit); 1411 break; 1412 case 10: 1413 /* 1414 * This event gets send on a Yoga 300-11IBR when the EC 1415 * believes that the device has changed between laptop/ 1416 * tent/stand/tablet mode. The EC relies on getting 1417 * angle info from 2 accelerometers through a special 1418 * windows service calling a DSM on the DUAL250E ACPI- 1419 * device. Linux does not do this, making the laptop/ 1420 * tent/stand/tablet mode info unreliable, so we simply 1421 * ignore these events. 1422 */ 1423 break; 1424 case 9: 1425 ideapad_sync_rfk_state(priv); 1426 break; 1427 case 5: 1428 ideapad_sync_touchpad_state(priv); 1429 break; 1430 case 4: 1431 ideapad_backlight_notify_brightness(priv); 1432 break; 1433 case 3: 1434 ideapad_input_novokey(priv); 1435 break; 1436 case 2: 1437 ideapad_backlight_notify_power(priv); 1438 break; 1439 case 1: 1440 /* 1441 * Some IdeaPads report event 1 every ~20 1442 * seconds while on battery power; some 1443 * report this when changing to/from tablet 1444 * mode; some report this when the keyboard 1445 * backlight has changed. 1446 */ 1447 ideapad_kbd_bl_notify(priv); 1448 break; 1449 case 0: 1450 ideapad_check_special_buttons(priv); 1451 break; 1452 default: 1453 dev_info(&priv->platform_device->dev, 1454 "Unknown event: %lu\n", bit); 1455 } 1456 } 1457 } 1458 1459 #if IS_ENABLED(CONFIG_ACPI_WMI) 1460 static void ideapad_wmi_notify(u32 value, void *context) 1461 { 1462 struct ideapad_private *priv = context; 1463 unsigned long result; 1464 1465 switch (value) { 1466 case 128: 1467 ideapad_input_report(priv, value); 1468 break; 1469 case 208: 1470 if (!eval_hals(priv->adev->handle, &result)) { 1471 bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result); 1472 1473 exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF); 1474 } 1475 break; 1476 default: 1477 dev_info(&priv->platform_device->dev, 1478 "Unknown WMI event: %u\n", value); 1479 } 1480 } 1481 #endif 1482 1483 /* 1484 * Some ideapads have a hardware rfkill switch, but most do not have one. 1485 * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill, 1486 * switch causing ideapad_laptop to wrongly report all radios as hw-blocked. 1487 * There used to be a long list of DMI ids for models without a hw rfkill 1488 * switch here, but that resulted in playing whack a mole. 1489 * More importantly wrongly reporting the wifi radio as hw-blocked, results in 1490 * non working wifi. Whereas not reporting it hw-blocked, when it actually is 1491 * hw-blocked results in an empty SSID list, which is a much more benign 1492 * failure mode. 1493 * So the default now is the much safer option of assuming there is no 1494 * hardware rfkill switch. This default also actually matches most hardware, 1495 * since having a hw rfkill switch is quite rare on modern hardware, so this 1496 * also leads to a much shorter list. 1497 */ 1498 static const struct dmi_system_id hw_rfkill_list[] = { 1499 {} 1500 }; 1501 1502 static void ideapad_check_features(struct ideapad_private *priv) 1503 { 1504 acpi_handle handle = priv->adev->handle; 1505 unsigned long val; 1506 1507 priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list); 1508 1509 /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */ 1510 priv->features.touchpad_ctrl_via_ec = !acpi_dev_present("ELAN0634", NULL, -1); 1511 1512 if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) 1513 priv->features.fan_mode = true; 1514 1515 if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC")) 1516 priv->features.conservation_mode = true; 1517 1518 if (acpi_has_method(handle, "DYTC")) 1519 priv->features.dytc = true; 1520 1521 if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) { 1522 if (!eval_hals(handle, &val)) { 1523 if (test_bit(HALS_FNLOCK_SUPPORT_BIT, &val)) 1524 priv->features.fn_lock = true; 1525 1526 if (test_bit(HALS_KBD_BL_SUPPORT_BIT, &val)) 1527 priv->features.kbd_bl = true; 1528 1529 if (test_bit(HALS_USB_CHARGING_SUPPORT_BIT, &val)) 1530 priv->features.usb_charging = true; 1531 } 1532 } 1533 } 1534 1535 static int ideapad_acpi_add(struct platform_device *pdev) 1536 { 1537 struct ideapad_private *priv; 1538 struct acpi_device *adev; 1539 acpi_status status; 1540 unsigned long cfg; 1541 int err, i; 1542 1543 err = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); 1544 if (err) 1545 return -ENODEV; 1546 1547 if (eval_int(adev->handle, "_CFG", &cfg)) 1548 return -ENODEV; 1549 1550 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1551 if (!priv) 1552 return -ENOMEM; 1553 1554 dev_set_drvdata(&pdev->dev, priv); 1555 1556 priv->cfg = cfg; 1557 priv->adev = adev; 1558 priv->platform_device = pdev; 1559 1560 ideapad_check_features(priv); 1561 1562 err = ideapad_sysfs_init(priv); 1563 if (err) 1564 return err; 1565 1566 ideapad_debugfs_init(priv); 1567 1568 err = ideapad_input_init(priv); 1569 if (err) 1570 goto input_failed; 1571 1572 err = ideapad_kbd_bl_init(priv); 1573 if (err) { 1574 if (err != -ENODEV) 1575 dev_warn(&pdev->dev, "Could not set up keyboard backlight LED: %d\n", err); 1576 else 1577 dev_info(&pdev->dev, "Keyboard backlight control not available\n"); 1578 } 1579 1580 /* 1581 * On some models without a hw-switch (the yoga 2 13 at least) 1582 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. 1583 */ 1584 if (!priv->features.hw_rfkill_switch) 1585 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); 1586 1587 /* The same for Touchpad */ 1588 if (!priv->features.touchpad_ctrl_via_ec) 1589 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1); 1590 1591 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1592 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 1593 ideapad_register_rfkill(priv, i); 1594 1595 ideapad_sync_rfk_state(priv); 1596 ideapad_sync_touchpad_state(priv); 1597 1598 err = ideapad_dytc_profile_init(priv); 1599 if (err) { 1600 if (err != -ENODEV) 1601 dev_warn(&pdev->dev, "Could not set up DYTC interface: %d\n", err); 1602 else 1603 dev_info(&pdev->dev, "DYTC interface is not available\n"); 1604 } 1605 1606 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { 1607 err = ideapad_backlight_init(priv); 1608 if (err && err != -ENODEV) 1609 goto backlight_failed; 1610 } 1611 1612 status = acpi_install_notify_handler(adev->handle, 1613 ACPI_DEVICE_NOTIFY, 1614 ideapad_acpi_notify, priv); 1615 if (ACPI_FAILURE(status)) { 1616 err = -EIO; 1617 goto notification_failed; 1618 } 1619 1620 #if IS_ENABLED(CONFIG_ACPI_WMI) 1621 for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) { 1622 status = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i], 1623 ideapad_wmi_notify, priv); 1624 if (ACPI_SUCCESS(status)) { 1625 priv->fnesc_guid = ideapad_wmi_fnesc_events[i]; 1626 break; 1627 } 1628 } 1629 1630 if (ACPI_FAILURE(status) && status != AE_NOT_EXIST) { 1631 err = -EIO; 1632 goto notification_failed_wmi; 1633 } 1634 #endif 1635 1636 return 0; 1637 1638 #if IS_ENABLED(CONFIG_ACPI_WMI) 1639 notification_failed_wmi: 1640 acpi_remove_notify_handler(priv->adev->handle, 1641 ACPI_DEVICE_NOTIFY, 1642 ideapad_acpi_notify); 1643 #endif 1644 1645 notification_failed: 1646 ideapad_backlight_exit(priv); 1647 1648 backlight_failed: 1649 ideapad_dytc_profile_exit(priv); 1650 1651 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1652 ideapad_unregister_rfkill(priv, i); 1653 1654 ideapad_kbd_bl_exit(priv); 1655 ideapad_input_exit(priv); 1656 1657 input_failed: 1658 ideapad_debugfs_exit(priv); 1659 ideapad_sysfs_exit(priv); 1660 1661 return err; 1662 } 1663 1664 static int ideapad_acpi_remove(struct platform_device *pdev) 1665 { 1666 struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); 1667 int i; 1668 1669 #if IS_ENABLED(CONFIG_ACPI_WMI) 1670 if (priv->fnesc_guid) 1671 wmi_remove_notify_handler(priv->fnesc_guid); 1672 #endif 1673 1674 acpi_remove_notify_handler(priv->adev->handle, 1675 ACPI_DEVICE_NOTIFY, 1676 ideapad_acpi_notify); 1677 1678 ideapad_backlight_exit(priv); 1679 ideapad_dytc_profile_exit(priv); 1680 1681 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 1682 ideapad_unregister_rfkill(priv, i); 1683 1684 ideapad_kbd_bl_exit(priv); 1685 ideapad_input_exit(priv); 1686 ideapad_debugfs_exit(priv); 1687 ideapad_sysfs_exit(priv); 1688 1689 return 0; 1690 } 1691 1692 #ifdef CONFIG_PM_SLEEP 1693 static int ideapad_acpi_resume(struct device *dev) 1694 { 1695 struct ideapad_private *priv = dev_get_drvdata(dev); 1696 1697 ideapad_sync_rfk_state(priv); 1698 ideapad_sync_touchpad_state(priv); 1699 1700 if (priv->dytc) 1701 dytc_profile_refresh(priv); 1702 1703 return 0; 1704 } 1705 #endif 1706 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); 1707 1708 static const struct acpi_device_id ideapad_device_ids[] = { 1709 {"VPC2004", 0}, 1710 {"", 0}, 1711 }; 1712 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); 1713 1714 static struct platform_driver ideapad_acpi_driver = { 1715 .probe = ideapad_acpi_add, 1716 .remove = ideapad_acpi_remove, 1717 .driver = { 1718 .name = "ideapad_acpi", 1719 .pm = &ideapad_pm, 1720 .acpi_match_table = ACPI_PTR(ideapad_device_ids), 1721 }, 1722 }; 1723 1724 module_platform_driver(ideapad_acpi_driver); 1725 1726 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 1727 MODULE_DESCRIPTION("IdeaPad ACPI Extras"); 1728 MODULE_LICENSE("GPL"); 1729