1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /*-*-linux-c-*-*/ 3 4 /* 5 Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@just42.net> 6 Copyright (C) 2008 Peter Gruber <nokos@gmx.net> 7 Copyright (C) 2008 Tony Vroon <tony@linx.net> 8 Based on earlier work: 9 Copyright (C) 2003 Shane Spencer <shane@bogomip.com> 10 Adrian Yee <brewt-fujitsu@brewt.org> 11 12 Templated from msi-laptop.c and thinkpad_acpi.c which is copyright 13 by its respective authors. 14 15 */ 16 17 /* 18 * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional 19 * features made available on a range of Fujitsu laptops including the 20 * P2xxx/P5xxx/S6xxx/S7xxx series. 21 * 22 * This driver implements a vendor-specific backlight control interface for 23 * Fujitsu laptops and provides support for hotkeys present on certain Fujitsu 24 * laptops. 25 * 26 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and 27 * P8010. It should work on most P-series and S-series Lifebooks, but 28 * YMMV. 29 * 30 * The module parameter use_alt_lcd_levels switches between different ACPI 31 * brightness controls which are used by different Fujitsu laptops. In most 32 * cases the correct method is automatically detected. "use_alt_lcd_levels=1" 33 * is applicable for a Fujitsu Lifebook S6410 if autodetection fails. 34 * 35 */ 36 37 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38 39 #include <linux/module.h> 40 #include <linux/kernel.h> 41 #include <linux/init.h> 42 #include <linux/acpi.h> 43 #include <linux/bitops.h> 44 #include <linux/dmi.h> 45 #include <linux/backlight.h> 46 #include <linux/input.h> 47 #include <linux/input/sparse-keymap.h> 48 #include <linux/kfifo.h> 49 #include <linux/leds.h> 50 #include <linux/platform_device.h> 51 #include <linux/power_supply.h> 52 #include <acpi/battery.h> 53 #include <acpi/video.h> 54 55 #define FUJITSU_DRIVER_VERSION "0.6.0" 56 57 #define FUJITSU_LCD_N_LEVELS 8 58 59 #define ACPI_FUJITSU_CLASS "fujitsu" 60 #define ACPI_FUJITSU_BL_HID "FUJ02B1" 61 #define ACPI_FUJITSU_BL_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI brightness driver" 62 #define ACPI_FUJITSU_BL_DEVICE_NAME "Fujitsu FUJ02B1" 63 #define ACPI_FUJITSU_LAPTOP_HID "FUJ02E3" 64 #define ACPI_FUJITSU_LAPTOP_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver" 65 #define ACPI_FUJITSU_LAPTOP_DEVICE_NAME "Fujitsu FUJ02E3" 66 67 #define ACPI_FUJITSU_NOTIFY_CODE 0x80 68 69 /* FUNC interface - command values */ 70 #define FUNC_FLAGS BIT(12) 71 #define FUNC_LEDS (BIT(12) | BIT(0)) 72 #define FUNC_BUTTONS (BIT(12) | BIT(1)) 73 #define FUNC_BACKLIGHT (BIT(12) | BIT(2)) 74 75 /* FUNC interface - responses */ 76 #define UNSUPPORTED_CMD 0x80000000 77 78 /* FUNC interface - status flags */ 79 #define FLAG_RFKILL BIT(5) 80 #define FLAG_LID BIT(8) 81 #define FLAG_DOCK BIT(9) 82 #define FLAG_TOUCHPAD_TOGGLE BIT(26) 83 #define FLAG_MICMUTE BIT(29) 84 #define FLAG_SOFTKEYS (FLAG_RFKILL | FLAG_TOUCHPAD_TOGGLE | FLAG_MICMUTE) 85 86 /* FUNC interface - LED control */ 87 #define FUNC_LED_OFF BIT(0) 88 #define FUNC_LED_ON (BIT(0) | BIT(16) | BIT(17)) 89 #define LOGOLAMP_POWERON BIT(13) 90 #define LOGOLAMP_ALWAYS BIT(14) 91 #define KEYBOARD_LAMPS BIT(8) 92 #define RADIO_LED_ON BIT(5) 93 #define ECO_LED BIT(16) 94 #define ECO_LED_ON BIT(19) 95 96 /* FUNC interface - backlight power control */ 97 #define BACKLIGHT_PARAM_POWER BIT(2) 98 #define BACKLIGHT_OFF (BIT(0) | BIT(1)) 99 #define BACKLIGHT_ON 0 100 101 /* FUNC interface - battery control interface */ 102 #define FUNC_S006_METHOD 0x1006 103 #define CHARGE_CONTROL_RW 0x21 104 105 /* Scancodes read from the GIRB register */ 106 #define KEY1_CODE 0x410 107 #define KEY2_CODE 0x411 108 #define KEY3_CODE 0x412 109 #define KEY4_CODE 0x413 110 #define KEY5_CODE 0x420 111 112 /* Hotkey ringbuffer limits */ 113 #define MAX_HOTKEY_RINGBUFFER_SIZE 100 114 #define RINGBUFFERSIZE 40 115 116 /* Module parameters */ 117 static int use_alt_lcd_levels = -1; 118 static bool disable_brightness_adjust; 119 120 /* Device controlling the backlight and associated keys */ 121 struct fujitsu_bl { 122 struct input_dev *input; 123 char phys[32]; 124 struct backlight_device *bl_device; 125 unsigned int max_brightness; 126 unsigned int brightness_level; 127 }; 128 129 static struct fujitsu_bl *fujitsu_bl; 130 131 /* Device used to access hotkeys and other features on the laptop */ 132 struct fujitsu_laptop { 133 struct input_dev *input; 134 char phys[32]; 135 struct platform_device *pf_device; 136 struct kfifo fifo; 137 spinlock_t fifo_lock; 138 int flags_supported; 139 int flags_state; 140 bool charge_control_supported; 141 }; 142 143 static struct acpi_device *fext; 144 145 /* Fujitsu ACPI interface function */ 146 147 static int call_fext_func(struct acpi_device *device, 148 int func, int op, int feature, int state) 149 { 150 union acpi_object params[4] = { 151 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = func }, 152 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = op }, 153 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = feature }, 154 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = state } 155 }; 156 struct acpi_object_list arg_list = { 4, params }; 157 unsigned long long value; 158 acpi_status status; 159 160 status = acpi_evaluate_integer(device->handle, "FUNC", &arg_list, 161 &value); 162 if (ACPI_FAILURE(status)) { 163 acpi_handle_err(device->handle, "Failed to evaluate FUNC\n"); 164 return -ENODEV; 165 } 166 167 acpi_handle_debug(device->handle, 168 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", 169 func, op, feature, state, (int)value); 170 return value; 171 } 172 173 /* Battery charge control code */ 174 static ssize_t charge_control_end_threshold_store(struct device *dev, 175 struct device_attribute *attr, 176 const char *buf, size_t count) 177 { 178 int cc_end_value, s006_cc_return; 179 int value, ret; 180 181 ret = kstrtouint(buf, 10, &value); 182 if (ret) 183 return ret; 184 185 if (value < 50 || value > 100) 186 return -EINVAL; 187 188 cc_end_value = value * 0x100 + 0x20; 189 s006_cc_return = call_fext_func(fext, FUNC_S006_METHOD, 190 CHARGE_CONTROL_RW, cc_end_value, 0x0); 191 if (s006_cc_return < 0) 192 return s006_cc_return; 193 /* 194 * The S006 0x21 method returns 0x00 in case the provided value 195 * is invalid. 196 */ 197 if (s006_cc_return == 0x00) 198 return -EINVAL; 199 200 return count; 201 } 202 203 static ssize_t charge_control_end_threshold_show(struct device *dev, 204 struct device_attribute *attr, 205 char *buf) 206 { 207 int status; 208 209 status = call_fext_func(fext, FUNC_S006_METHOD, 210 CHARGE_CONTROL_RW, 0x21, 0x0); 211 if (status < 0) 212 return status; 213 214 return sysfs_emit(buf, "%d\n", status); 215 } 216 217 static DEVICE_ATTR_RW(charge_control_end_threshold); 218 219 /* ACPI battery hook */ 220 static int fujitsu_battery_add_hook(struct power_supply *battery, 221 struct acpi_battery_hook *hook) 222 { 223 return device_create_file(&battery->dev, 224 &dev_attr_charge_control_end_threshold); 225 } 226 227 static int fujitsu_battery_remove_hook(struct power_supply *battery, 228 struct acpi_battery_hook *hook) 229 { 230 device_remove_file(&battery->dev, 231 &dev_attr_charge_control_end_threshold); 232 233 return 0; 234 } 235 236 static struct acpi_battery_hook battery_hook = { 237 .add_battery = fujitsu_battery_add_hook, 238 .remove_battery = fujitsu_battery_remove_hook, 239 .name = "Fujitsu Battery Extension", 240 }; 241 242 /* 243 * These functions are intended to be called from acpi_fujitsu_laptop_add and 244 * acpi_fujitsu_laptop_remove. 245 */ 246 static int fujitsu_battery_charge_control_add(struct acpi_device *device) 247 { 248 struct fujitsu_laptop *priv = acpi_driver_data(device); 249 int s006_cc_return; 250 251 priv->charge_control_supported = false; 252 /* 253 * Check if the S006 0x21 method exists by trying to get the current 254 * battery charge limit. 255 */ 256 s006_cc_return = call_fext_func(fext, FUNC_S006_METHOD, 257 CHARGE_CONTROL_RW, 0x21, 0x0); 258 if (s006_cc_return < 0) 259 return s006_cc_return; 260 if (s006_cc_return == UNSUPPORTED_CMD) 261 return -ENODEV; 262 263 priv->charge_control_supported = true; 264 battery_hook_register(&battery_hook); 265 266 return 0; 267 } 268 269 static void fujitsu_battery_charge_control_remove(struct acpi_device *device) 270 { 271 struct fujitsu_laptop *priv = acpi_driver_data(device); 272 273 if (priv->charge_control_supported) 274 battery_hook_unregister(&battery_hook); 275 } 276 277 /* Hardware access for LCD brightness control */ 278 279 static int set_lcd_level(struct acpi_device *device, int level) 280 { 281 struct fujitsu_bl *priv = acpi_driver_data(device); 282 acpi_status status; 283 char *method; 284 285 switch (use_alt_lcd_levels) { 286 case -1: 287 if (acpi_has_method(device->handle, "SBL2")) 288 method = "SBL2"; 289 else 290 method = "SBLL"; 291 break; 292 case 1: 293 method = "SBL2"; 294 break; 295 default: 296 method = "SBLL"; 297 break; 298 } 299 300 acpi_handle_debug(device->handle, "set lcd level via %s [%d]\n", method, 301 level); 302 303 if (level < 0 || level >= priv->max_brightness) 304 return -EINVAL; 305 306 status = acpi_execute_simple_method(device->handle, method, level); 307 if (ACPI_FAILURE(status)) { 308 acpi_handle_err(device->handle, "Failed to evaluate %s\n", 309 method); 310 return -ENODEV; 311 } 312 313 priv->brightness_level = level; 314 315 return 0; 316 } 317 318 static int get_lcd_level(struct acpi_device *device) 319 { 320 struct fujitsu_bl *priv = acpi_driver_data(device); 321 unsigned long long state = 0; 322 acpi_status status = AE_OK; 323 324 acpi_handle_debug(device->handle, "get lcd level via GBLL\n"); 325 326 status = acpi_evaluate_integer(device->handle, "GBLL", NULL, &state); 327 if (ACPI_FAILURE(status)) 328 return 0; 329 330 priv->brightness_level = state & 0x0fffffff; 331 332 return priv->brightness_level; 333 } 334 335 static int get_max_brightness(struct acpi_device *device) 336 { 337 struct fujitsu_bl *priv = acpi_driver_data(device); 338 unsigned long long state = 0; 339 acpi_status status = AE_OK; 340 341 acpi_handle_debug(device->handle, "get max lcd level via RBLL\n"); 342 343 status = acpi_evaluate_integer(device->handle, "RBLL", NULL, &state); 344 if (ACPI_FAILURE(status)) 345 return -1; 346 347 priv->max_brightness = state; 348 349 return priv->max_brightness; 350 } 351 352 /* Backlight device stuff */ 353 354 static int bl_get_brightness(struct backlight_device *b) 355 { 356 struct acpi_device *device = bl_get_data(b); 357 358 return b->props.power == BACKLIGHT_POWER_OFF ? 0 : get_lcd_level(device); 359 } 360 361 static int bl_update_status(struct backlight_device *b) 362 { 363 struct acpi_device *device = bl_get_data(b); 364 365 if (fext) { 366 if (b->props.power == BACKLIGHT_POWER_OFF) 367 call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 368 BACKLIGHT_PARAM_POWER, BACKLIGHT_OFF); 369 else 370 call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 371 BACKLIGHT_PARAM_POWER, BACKLIGHT_ON); 372 } 373 374 return set_lcd_level(device, b->props.brightness); 375 } 376 377 static const struct backlight_ops fujitsu_bl_ops = { 378 .get_brightness = bl_get_brightness, 379 .update_status = bl_update_status, 380 }; 381 382 static ssize_t lid_show(struct device *dev, struct device_attribute *attr, 383 char *buf) 384 { 385 struct fujitsu_laptop *priv = dev_get_drvdata(dev); 386 387 if (!(priv->flags_supported & FLAG_LID)) 388 return sysfs_emit(buf, "unknown\n"); 389 if (priv->flags_state & FLAG_LID) 390 return sysfs_emit(buf, "open\n"); 391 else 392 return sysfs_emit(buf, "closed\n"); 393 } 394 395 static ssize_t dock_show(struct device *dev, struct device_attribute *attr, 396 char *buf) 397 { 398 struct fujitsu_laptop *priv = dev_get_drvdata(dev); 399 400 if (!(priv->flags_supported & FLAG_DOCK)) 401 return sysfs_emit(buf, "unknown\n"); 402 if (priv->flags_state & FLAG_DOCK) 403 return sysfs_emit(buf, "docked\n"); 404 else 405 return sysfs_emit(buf, "undocked\n"); 406 } 407 408 static ssize_t radios_show(struct device *dev, struct device_attribute *attr, 409 char *buf) 410 { 411 struct fujitsu_laptop *priv = dev_get_drvdata(dev); 412 413 if (!(priv->flags_supported & FLAG_RFKILL)) 414 return sysfs_emit(buf, "unknown\n"); 415 if (priv->flags_state & FLAG_RFKILL) 416 return sysfs_emit(buf, "on\n"); 417 else 418 return sysfs_emit(buf, "killed\n"); 419 } 420 421 static DEVICE_ATTR_RO(lid); 422 static DEVICE_ATTR_RO(dock); 423 static DEVICE_ATTR_RO(radios); 424 425 static struct attribute *fujitsu_pf_attributes[] = { 426 &dev_attr_lid.attr, 427 &dev_attr_dock.attr, 428 &dev_attr_radios.attr, 429 NULL 430 }; 431 432 static const struct attribute_group fujitsu_pf_attribute_group = { 433 .attrs = fujitsu_pf_attributes 434 }; 435 436 static struct platform_driver fujitsu_pf_driver = { 437 .driver = { 438 .name = "fujitsu-laptop", 439 } 440 }; 441 442 /* ACPI device for LCD brightness control */ 443 444 static const struct key_entry keymap_backlight[] = { 445 { KE_KEY, true, { KEY_BRIGHTNESSUP } }, 446 { KE_KEY, false, { KEY_BRIGHTNESSDOWN } }, 447 { KE_END, 0 } 448 }; 449 450 static int acpi_fujitsu_bl_input_setup(struct acpi_device *device) 451 { 452 struct fujitsu_bl *priv = acpi_driver_data(device); 453 int ret; 454 455 priv->input = devm_input_allocate_device(&device->dev); 456 if (!priv->input) 457 return -ENOMEM; 458 459 snprintf(priv->phys, sizeof(priv->phys), "%s/video/input0", 460 acpi_device_hid(device)); 461 462 priv->input->name = acpi_device_name(device); 463 priv->input->phys = priv->phys; 464 priv->input->id.bustype = BUS_HOST; 465 priv->input->id.product = 0x06; 466 467 ret = sparse_keymap_setup(priv->input, keymap_backlight, NULL); 468 if (ret) 469 return ret; 470 471 return input_register_device(priv->input); 472 } 473 474 static int fujitsu_backlight_register(struct acpi_device *device) 475 { 476 struct fujitsu_bl *priv = acpi_driver_data(device); 477 const struct backlight_properties props = { 478 .brightness = priv->brightness_level, 479 .max_brightness = priv->max_brightness - 1, 480 .type = BACKLIGHT_PLATFORM 481 }; 482 struct backlight_device *bd; 483 484 bd = devm_backlight_device_register(&device->dev, "fujitsu-laptop", 485 &device->dev, device, 486 &fujitsu_bl_ops, &props); 487 if (IS_ERR(bd)) 488 return PTR_ERR(bd); 489 490 priv->bl_device = bd; 491 492 return 0; 493 } 494 495 static int acpi_fujitsu_bl_add(struct acpi_device *device) 496 { 497 struct fujitsu_bl *priv; 498 int ret; 499 500 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 501 return -ENODEV; 502 503 priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); 504 if (!priv) 505 return -ENOMEM; 506 507 fujitsu_bl = priv; 508 strcpy(acpi_device_name(device), ACPI_FUJITSU_BL_DEVICE_NAME); 509 strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 510 device->driver_data = priv; 511 512 pr_info("ACPI: %s [%s]\n", 513 acpi_device_name(device), acpi_device_bid(device)); 514 515 if (get_max_brightness(device) <= 0) 516 priv->max_brightness = FUJITSU_LCD_N_LEVELS; 517 get_lcd_level(device); 518 519 ret = acpi_fujitsu_bl_input_setup(device); 520 if (ret) 521 return ret; 522 523 return fujitsu_backlight_register(device); 524 } 525 526 /* Brightness notify */ 527 528 static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event) 529 { 530 struct fujitsu_bl *priv = acpi_driver_data(device); 531 int oldb, newb; 532 533 if (event != ACPI_FUJITSU_NOTIFY_CODE) { 534 acpi_handle_info(device->handle, "unsupported event [0x%x]\n", 535 event); 536 sparse_keymap_report_event(priv->input, -1, 1, true); 537 return; 538 } 539 540 oldb = priv->brightness_level; 541 get_lcd_level(device); 542 newb = priv->brightness_level; 543 544 acpi_handle_debug(device->handle, 545 "brightness button event [%i -> %i]\n", oldb, newb); 546 547 if (oldb == newb) 548 return; 549 550 if (!disable_brightness_adjust) 551 set_lcd_level(device, newb); 552 553 sparse_keymap_report_event(priv->input, oldb < newb, 1, true); 554 } 555 556 /* ACPI device for hotkey handling */ 557 558 static const struct key_entry keymap_default[] = { 559 { KE_KEY, KEY1_CODE, { KEY_PROG1 } }, 560 { KE_KEY, KEY2_CODE, { KEY_PROG2 } }, 561 { KE_KEY, KEY3_CODE, { KEY_PROG3 } }, 562 { KE_KEY, KEY4_CODE, { KEY_PROG4 } }, 563 { KE_KEY, KEY5_CODE, { KEY_RFKILL } }, 564 /* Soft keys read from status flags */ 565 { KE_KEY, FLAG_RFKILL, { KEY_RFKILL } }, 566 { KE_KEY, FLAG_TOUCHPAD_TOGGLE, { KEY_TOUCHPAD_TOGGLE } }, 567 { KE_KEY, FLAG_MICMUTE, { KEY_MICMUTE } }, 568 { KE_END, 0 } 569 }; 570 571 static const struct key_entry keymap_s64x0[] = { 572 { KE_KEY, KEY1_CODE, { KEY_SCREENLOCK } }, /* "Lock" */ 573 { KE_KEY, KEY2_CODE, { KEY_HELP } }, /* "Mobility Center */ 574 { KE_KEY, KEY3_CODE, { KEY_PROG3 } }, 575 { KE_KEY, KEY4_CODE, { KEY_PROG4 } }, 576 { KE_END, 0 } 577 }; 578 579 static const struct key_entry keymap_p8010[] = { 580 { KE_KEY, KEY1_CODE, { KEY_HELP } }, /* "Support" */ 581 { KE_KEY, KEY2_CODE, { KEY_PROG2 } }, 582 { KE_KEY, KEY3_CODE, { KEY_SWITCHVIDEOMODE } }, /* "Presentation" */ 583 { KE_KEY, KEY4_CODE, { KEY_WWW } }, /* "WWW" */ 584 { KE_END, 0 } 585 }; 586 587 static const struct key_entry *keymap = keymap_default; 588 589 static int fujitsu_laptop_dmi_keymap_override(const struct dmi_system_id *id) 590 { 591 pr_info("Identified laptop model '%s'\n", id->ident); 592 keymap = id->driver_data; 593 return 1; 594 } 595 596 static const struct dmi_system_id fujitsu_laptop_dmi_table[] = { 597 { 598 .callback = fujitsu_laptop_dmi_keymap_override, 599 .ident = "Fujitsu Siemens S6410", 600 .matches = { 601 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 602 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), 603 }, 604 .driver_data = (void *)keymap_s64x0 605 }, 606 { 607 .callback = fujitsu_laptop_dmi_keymap_override, 608 .ident = "Fujitsu Siemens S6420", 609 .matches = { 610 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 611 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), 612 }, 613 .driver_data = (void *)keymap_s64x0 614 }, 615 { 616 .callback = fujitsu_laptop_dmi_keymap_override, 617 .ident = "Fujitsu LifeBook P8010", 618 .matches = { 619 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 620 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), 621 }, 622 .driver_data = (void *)keymap_p8010 623 }, 624 {} 625 }; 626 627 static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device) 628 { 629 struct fujitsu_laptop *priv = acpi_driver_data(device); 630 int ret; 631 632 priv->input = devm_input_allocate_device(&device->dev); 633 if (!priv->input) 634 return -ENOMEM; 635 636 snprintf(priv->phys, sizeof(priv->phys), "%s/input0", 637 acpi_device_hid(device)); 638 639 priv->input->name = acpi_device_name(device); 640 priv->input->phys = priv->phys; 641 priv->input->id.bustype = BUS_HOST; 642 643 dmi_check_system(fujitsu_laptop_dmi_table); 644 ret = sparse_keymap_setup(priv->input, keymap, NULL); 645 if (ret) 646 return ret; 647 648 return input_register_device(priv->input); 649 } 650 651 static int fujitsu_laptop_platform_add(struct acpi_device *device) 652 { 653 struct fujitsu_laptop *priv = acpi_driver_data(device); 654 int ret; 655 656 priv->pf_device = platform_device_alloc("fujitsu-laptop", PLATFORM_DEVID_NONE); 657 if (!priv->pf_device) 658 return -ENOMEM; 659 660 platform_set_drvdata(priv->pf_device, priv); 661 662 ret = platform_device_add(priv->pf_device); 663 if (ret) 664 goto err_put_platform_device; 665 666 ret = sysfs_create_group(&priv->pf_device->dev.kobj, 667 &fujitsu_pf_attribute_group); 668 if (ret) 669 goto err_del_platform_device; 670 671 return 0; 672 673 err_del_platform_device: 674 platform_device_del(priv->pf_device); 675 err_put_platform_device: 676 platform_device_put(priv->pf_device); 677 678 return ret; 679 } 680 681 static void fujitsu_laptop_platform_remove(struct acpi_device *device) 682 { 683 struct fujitsu_laptop *priv = acpi_driver_data(device); 684 685 sysfs_remove_group(&priv->pf_device->dev.kobj, 686 &fujitsu_pf_attribute_group); 687 platform_device_unregister(priv->pf_device); 688 } 689 690 static int logolamp_set(struct led_classdev *cdev, 691 enum led_brightness brightness) 692 { 693 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 694 int poweron = FUNC_LED_ON, always = FUNC_LED_ON; 695 int ret; 696 697 if (brightness < LED_HALF) 698 poweron = FUNC_LED_OFF; 699 700 if (brightness < LED_FULL) 701 always = FUNC_LED_OFF; 702 703 ret = call_fext_func(device, FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron); 704 if (ret < 0) 705 return ret; 706 707 return call_fext_func(device, FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always); 708 } 709 710 static enum led_brightness logolamp_get(struct led_classdev *cdev) 711 { 712 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 713 int ret; 714 715 ret = call_fext_func(device, FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); 716 if (ret == FUNC_LED_ON) 717 return LED_FULL; 718 719 ret = call_fext_func(device, FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); 720 if (ret == FUNC_LED_ON) 721 return LED_HALF; 722 723 return LED_OFF; 724 } 725 726 static int kblamps_set(struct led_classdev *cdev, 727 enum led_brightness brightness) 728 { 729 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 730 731 if (brightness >= LED_FULL) 732 return call_fext_func(device, FUNC_LEDS, 0x1, KEYBOARD_LAMPS, 733 FUNC_LED_ON); 734 else 735 return call_fext_func(device, FUNC_LEDS, 0x1, KEYBOARD_LAMPS, 736 FUNC_LED_OFF); 737 } 738 739 static enum led_brightness kblamps_get(struct led_classdev *cdev) 740 { 741 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 742 enum led_brightness brightness = LED_OFF; 743 744 if (call_fext_func(device, 745 FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON) 746 brightness = LED_FULL; 747 748 return brightness; 749 } 750 751 static int radio_led_set(struct led_classdev *cdev, 752 enum led_brightness brightness) 753 { 754 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 755 756 if (brightness >= LED_FULL) 757 return call_fext_func(device, FUNC_FLAGS, 0x5, RADIO_LED_ON, 758 RADIO_LED_ON); 759 else 760 return call_fext_func(device, FUNC_FLAGS, 0x5, RADIO_LED_ON, 761 0x0); 762 } 763 764 static enum led_brightness radio_led_get(struct led_classdev *cdev) 765 { 766 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 767 enum led_brightness brightness = LED_OFF; 768 769 if (call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON) 770 brightness = LED_FULL; 771 772 return brightness; 773 } 774 775 static int eco_led_set(struct led_classdev *cdev, 776 enum led_brightness brightness) 777 { 778 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 779 int curr; 780 781 curr = call_fext_func(device, FUNC_LEDS, 0x2, ECO_LED, 0x0); 782 if (brightness >= LED_FULL) 783 return call_fext_func(device, FUNC_LEDS, 0x1, ECO_LED, 784 curr | ECO_LED_ON); 785 else 786 return call_fext_func(device, FUNC_LEDS, 0x1, ECO_LED, 787 curr & ~ECO_LED_ON); 788 } 789 790 static enum led_brightness eco_led_get(struct led_classdev *cdev) 791 { 792 struct acpi_device *device = to_acpi_device(cdev->dev->parent); 793 enum led_brightness brightness = LED_OFF; 794 795 if (call_fext_func(device, FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON) 796 brightness = LED_FULL; 797 798 return brightness; 799 } 800 801 static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) 802 { 803 struct fujitsu_laptop *priv = acpi_driver_data(device); 804 struct led_classdev *led; 805 int ret; 806 807 if (call_fext_func(device, 808 FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 809 led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL); 810 if (!led) 811 return -ENOMEM; 812 813 led->name = "fujitsu::logolamp"; 814 led->brightness_set_blocking = logolamp_set; 815 led->brightness_get = logolamp_get; 816 ret = devm_led_classdev_register(&device->dev, led); 817 if (ret) 818 return ret; 819 } 820 821 if ((call_fext_func(device, 822 FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) && 823 (call_fext_func(device, FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) { 824 led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL); 825 if (!led) 826 return -ENOMEM; 827 828 led->name = "fujitsu::kblamps"; 829 led->brightness_set_blocking = kblamps_set; 830 led->brightness_get = kblamps_get; 831 ret = devm_led_classdev_register(&device->dev, led); 832 if (ret) 833 return ret; 834 } 835 836 /* 837 * Some Fujitsu laptops have a radio toggle button in place of a slide 838 * switch and all such machines appear to also have an RF LED. Based on 839 * comparing DSDT tables of four Fujitsu Lifebook models (E744, E751, 840 * S7110, S8420; the first one has a radio toggle button, the other 841 * three have slide switches), bit 17 of flags_supported (the value 842 * returned by method S000 of ACPI device FUJ02E3) seems to indicate 843 * whether given model has a radio toggle button. 844 */ 845 if (priv->flags_supported & BIT(17)) { 846 led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL); 847 if (!led) 848 return -ENOMEM; 849 850 led->name = "fujitsu::radio_led"; 851 led->brightness_set_blocking = radio_led_set; 852 led->brightness_get = radio_led_get; 853 led->default_trigger = "rfkill-any"; 854 ret = devm_led_classdev_register(&device->dev, led); 855 if (ret) 856 return ret; 857 } 858 859 /* Support for eco led is not always signaled in bit corresponding 860 * to the bit used to control the led. According to the DSDT table, 861 * bit 14 seems to indicate presence of said led as well. 862 * Confirm by testing the status. 863 */ 864 if ((call_fext_func(device, FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) && 865 (call_fext_func(device, 866 FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) { 867 led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL); 868 if (!led) 869 return -ENOMEM; 870 871 led->name = "fujitsu::eco_led"; 872 led->brightness_set_blocking = eco_led_set; 873 led->brightness_get = eco_led_get; 874 ret = devm_led_classdev_register(&device->dev, led); 875 if (ret) 876 return ret; 877 } 878 879 return 0; 880 } 881 882 static int acpi_fujitsu_laptop_add(struct acpi_device *device) 883 { 884 struct fujitsu_laptop *priv; 885 int ret, i = 0; 886 887 priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); 888 if (!priv) 889 return -ENOMEM; 890 891 WARN_ONCE(fext, "More than one FUJ02E3 ACPI device was found. Driver may not work as intended."); 892 fext = device; 893 894 strcpy(acpi_device_name(device), ACPI_FUJITSU_LAPTOP_DEVICE_NAME); 895 strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 896 device->driver_data = priv; 897 898 /* kfifo */ 899 spin_lock_init(&priv->fifo_lock); 900 ret = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int), 901 GFP_KERNEL); 902 if (ret) 903 return ret; 904 905 pr_info("ACPI: %s [%s]\n", 906 acpi_device_name(device), acpi_device_bid(device)); 907 908 while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 && 909 i++ < MAX_HOTKEY_RINGBUFFER_SIZE) 910 ; /* No action, result is discarded */ 911 acpi_handle_debug(device->handle, "Discarded %i ringbuffer entries\n", 912 i); 913 914 priv->flags_supported = call_fext_func(device, FUNC_FLAGS, 0x0, 0x0, 915 0x0); 916 917 /* Make sure our bitmask of supported functions is cleared if the 918 RFKILL function block is not implemented, like on the S7020. */ 919 if (priv->flags_supported == UNSUPPORTED_CMD) 920 priv->flags_supported = 0; 921 922 if (priv->flags_supported) 923 priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, 924 0x0); 925 926 /* Suspect this is a keymap of the application panel, print it */ 927 acpi_handle_info(device->handle, "BTNI: [0x%x]\n", 928 call_fext_func(device, FUNC_BUTTONS, 0x0, 0x0, 0x0)); 929 930 /* Sync backlight power status */ 931 if (fujitsu_bl && fujitsu_bl->bl_device && 932 acpi_video_get_backlight_type() == acpi_backlight_vendor) { 933 if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, 934 BACKLIGHT_PARAM_POWER, 0x0) == BACKLIGHT_OFF) 935 fujitsu_bl->bl_device->props.power = BACKLIGHT_POWER_OFF; 936 else 937 fujitsu_bl->bl_device->props.power = BACKLIGHT_POWER_ON; 938 } 939 940 ret = acpi_fujitsu_laptop_input_setup(device); 941 if (ret) 942 goto err_free_fifo; 943 944 ret = acpi_fujitsu_laptop_leds_register(device); 945 if (ret) 946 goto err_free_fifo; 947 948 ret = fujitsu_laptop_platform_add(device); 949 if (ret) 950 goto err_free_fifo; 951 952 ret = fujitsu_battery_charge_control_add(device); 953 if (ret < 0) 954 pr_warn("Unable to register battery charge control: %d\n", ret); 955 956 return 0; 957 958 err_free_fifo: 959 kfifo_free(&priv->fifo); 960 961 return ret; 962 } 963 964 static void acpi_fujitsu_laptop_remove(struct acpi_device *device) 965 { 966 struct fujitsu_laptop *priv = acpi_driver_data(device); 967 968 fujitsu_battery_charge_control_remove(device); 969 970 fujitsu_laptop_platform_remove(device); 971 972 kfifo_free(&priv->fifo); 973 } 974 975 static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode) 976 { 977 struct fujitsu_laptop *priv = acpi_driver_data(device); 978 int ret; 979 980 ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode, 981 sizeof(scancode), &priv->fifo_lock); 982 if (ret != sizeof(scancode)) { 983 dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n", 984 scancode); 985 return; 986 } 987 sparse_keymap_report_event(priv->input, scancode, 1, false); 988 dev_dbg(&priv->input->dev, "Push scancode into ringbuffer [0x%x]\n", 989 scancode); 990 } 991 992 static void acpi_fujitsu_laptop_release(struct acpi_device *device) 993 { 994 struct fujitsu_laptop *priv = acpi_driver_data(device); 995 int scancode, ret; 996 997 while (true) { 998 ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode, 999 sizeof(scancode), &priv->fifo_lock); 1000 if (ret != sizeof(scancode)) 1001 return; 1002 sparse_keymap_report_event(priv->input, scancode, 0, false); 1003 dev_dbg(&priv->input->dev, 1004 "Pop scancode from ringbuffer [0x%x]\n", scancode); 1005 } 1006 } 1007 1008 static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) 1009 { 1010 struct fujitsu_laptop *priv = acpi_driver_data(device); 1011 unsigned long flags; 1012 int scancode, i = 0; 1013 unsigned int irb; 1014 1015 if (event != ACPI_FUJITSU_NOTIFY_CODE) { 1016 acpi_handle_info(device->handle, "Unsupported event [0x%x]\n", 1017 event); 1018 sparse_keymap_report_event(priv->input, -1, 1, true); 1019 return; 1020 } 1021 1022 if (priv->flags_supported) 1023 priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, 1024 0x0); 1025 1026 while ((irb = call_fext_func(device, 1027 FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 && 1028 i++ < MAX_HOTKEY_RINGBUFFER_SIZE) { 1029 scancode = irb & 0x4ff; 1030 if (sparse_keymap_entry_from_scancode(priv->input, scancode)) 1031 acpi_fujitsu_laptop_press(device, scancode); 1032 else if (scancode == 0) 1033 acpi_fujitsu_laptop_release(device); 1034 else 1035 acpi_handle_info(device->handle, 1036 "Unknown GIRB result [%x]\n", irb); 1037 } 1038 1039 /* 1040 * First seen on the Skylake-based Lifebook E736/E746/E756), the 1041 * touchpad toggle hotkey (Fn+F4) is handled in software. Other models 1042 * have since added additional "soft keys". These are reported in the 1043 * status flags queried using FUNC_FLAGS. 1044 */ 1045 if (priv->flags_supported & (FLAG_SOFTKEYS)) { 1046 flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0); 1047 flags &= (FLAG_SOFTKEYS); 1048 for_each_set_bit(i, &flags, BITS_PER_LONG) 1049 sparse_keymap_report_event(priv->input, BIT(i), 1, true); 1050 } 1051 } 1052 1053 /* Initialization */ 1054 1055 static const struct acpi_device_id fujitsu_bl_device_ids[] = { 1056 {ACPI_FUJITSU_BL_HID, 0}, 1057 {"", 0}, 1058 }; 1059 1060 static struct acpi_driver acpi_fujitsu_bl_driver = { 1061 .name = ACPI_FUJITSU_BL_DRIVER_NAME, 1062 .class = ACPI_FUJITSU_CLASS, 1063 .ids = fujitsu_bl_device_ids, 1064 .ops = { 1065 .add = acpi_fujitsu_bl_add, 1066 .notify = acpi_fujitsu_bl_notify, 1067 }, 1068 }; 1069 1070 static const struct acpi_device_id fujitsu_laptop_device_ids[] = { 1071 {ACPI_FUJITSU_LAPTOP_HID, 0}, 1072 {"", 0}, 1073 }; 1074 1075 static struct acpi_driver acpi_fujitsu_laptop_driver = { 1076 .name = ACPI_FUJITSU_LAPTOP_DRIVER_NAME, 1077 .class = ACPI_FUJITSU_CLASS, 1078 .ids = fujitsu_laptop_device_ids, 1079 .ops = { 1080 .add = acpi_fujitsu_laptop_add, 1081 .remove = acpi_fujitsu_laptop_remove, 1082 .notify = acpi_fujitsu_laptop_notify, 1083 }, 1084 }; 1085 1086 static const struct acpi_device_id fujitsu_ids[] __used = { 1087 {ACPI_FUJITSU_BL_HID, 0}, 1088 {ACPI_FUJITSU_LAPTOP_HID, 0}, 1089 {"", 0} 1090 }; 1091 MODULE_DEVICE_TABLE(acpi, fujitsu_ids); 1092 1093 static int __init fujitsu_init(void) 1094 { 1095 int ret; 1096 1097 ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver); 1098 if (ret) 1099 return ret; 1100 1101 /* Register platform stuff */ 1102 1103 ret = platform_driver_register(&fujitsu_pf_driver); 1104 if (ret) 1105 goto err_unregister_acpi; 1106 1107 /* Register laptop driver */ 1108 1109 ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver); 1110 if (ret) 1111 goto err_unregister_platform_driver; 1112 1113 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n"); 1114 1115 return 0; 1116 1117 err_unregister_platform_driver: 1118 platform_driver_unregister(&fujitsu_pf_driver); 1119 err_unregister_acpi: 1120 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1121 1122 return ret; 1123 } 1124 1125 static void __exit fujitsu_cleanup(void) 1126 { 1127 acpi_bus_unregister_driver(&acpi_fujitsu_laptop_driver); 1128 1129 platform_driver_unregister(&fujitsu_pf_driver); 1130 1131 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1132 1133 pr_info("driver unloaded\n"); 1134 } 1135 1136 module_init(fujitsu_init); 1137 module_exit(fujitsu_cleanup); 1138 1139 module_param(use_alt_lcd_levels, int, 0644); 1140 MODULE_PARM_DESC(use_alt_lcd_levels, "Interface used for setting LCD brightness level (-1 = auto, 0 = force SBLL, 1 = force SBL2)"); 1141 module_param(disable_brightness_adjust, bool, 0644); 1142 MODULE_PARM_DESC(disable_brightness_adjust, "Disable LCD brightness adjustment"); 1143 1144 MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon"); 1145 MODULE_DESCRIPTION("Fujitsu laptop extras support"); 1146 MODULE_VERSION(FUJITSU_DRIVER_VERSION); 1147 MODULE_LICENSE("GPL"); 1148