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