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