1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2006-2012 Robert Gerlach <khnz@gmx.de> 4 * Copyright (C) 2005-2006 Jan Rychter <jan@rychter.com> 5 */ 6 7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/bitops.h> 13 #include <linux/io.h> 14 #include <linux/ioport.h> 15 #include <linux/acpi.h> 16 #include <linux/device.h> 17 #include <linux/interrupt.h> 18 #include <linux/input.h> 19 #include <linux/delay.h> 20 #include <linux/dmi.h> 21 #include <linux/platform_device.h> 22 23 #define MODULENAME "fujitsu-tablet" 24 25 #define ACPI_FUJITSU_CLASS "fujitsu" 26 27 #define INVERT_TABLET_MODE_BIT 0x01 28 #define INVERT_DOCK_STATE_BIT 0x02 29 #define FORCE_TABLET_MODE_IF_UNDOCK 0x04 30 31 #define KEYMAP_LEN 16 32 33 static const struct acpi_device_id fujitsu_ids[] = { 34 { .id = "FUJ02BD" }, 35 { .id = "FUJ02BF" }, 36 { .id = "" } 37 }; 38 39 struct fujitsu_config { 40 unsigned short keymap[KEYMAP_LEN]; 41 unsigned int quirks; 42 }; 43 44 static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initdata = { 45 KEY_RESERVED, 46 KEY_RESERVED, 47 KEY_RESERVED, 48 KEY_RESERVED, 49 KEY_SCROLLDOWN, 50 KEY_SCROLLUP, 51 KEY_ROTATE_DISPLAY, 52 KEY_LEFTCTRL, 53 KEY_BRIGHTNESSUP, 54 KEY_BRIGHTNESSDOWN, 55 KEY_BRIGHTNESS_ZERO, 56 KEY_RESERVED, 57 KEY_RESERVED, 58 KEY_RESERVED, 59 KEY_RESERVED, 60 KEY_LEFTALT 61 }; 62 63 static unsigned short keymap_Lifebook_T901[KEYMAP_LEN] __initdata = { 64 KEY_RESERVED, 65 KEY_RESERVED, 66 KEY_RESERVED, 67 KEY_RESERVED, 68 KEY_SCROLLDOWN, 69 KEY_SCROLLUP, 70 KEY_CYCLEWINDOWS, 71 KEY_LEFTCTRL, 72 KEY_RESERVED, 73 KEY_RESERVED, 74 KEY_RESERVED, 75 KEY_RESERVED, 76 KEY_RESERVED, 77 KEY_RESERVED, 78 KEY_RESERVED, 79 KEY_LEFTMETA 80 }; 81 82 static unsigned short keymap_Lifebook_T902[KEYMAP_LEN] __initdata = { 83 KEY_RESERVED, 84 KEY_VOLUMEDOWN, 85 KEY_VOLUMEUP, 86 KEY_CYCLEWINDOWS, 87 KEY_PROG1, 88 KEY_PROG2, 89 KEY_LEFTMETA, 90 KEY_RESERVED, 91 KEY_RESERVED, 92 KEY_RESERVED, 93 KEY_RESERVED, 94 KEY_RESERVED, 95 KEY_RESERVED, 96 KEY_RESERVED, 97 KEY_RESERVED, 98 KEY_RESERVED, 99 }; 100 101 static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initdata = { 102 KEY_RESERVED, 103 KEY_RESERVED, 104 KEY_RESERVED, 105 KEY_RESERVED, 106 KEY_PROG1, 107 KEY_PROG2, 108 KEY_ROTATE_DISPLAY, 109 KEY_RESERVED, 110 KEY_RESERVED, 111 KEY_RESERVED, 112 KEY_UP, 113 KEY_DOWN, 114 KEY_RESERVED, 115 KEY_RESERVED, 116 KEY_LEFTCTRL, 117 KEY_LEFTALT 118 }; 119 120 static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initdata = { 121 KEY_RESERVED, 122 KEY_RESERVED, 123 KEY_RESERVED, 124 KEY_RESERVED, 125 KEY_PRINT, 126 KEY_BACKSPACE, 127 KEY_SPACE, 128 KEY_ENTER, 129 KEY_BRIGHTNESSUP, 130 KEY_BRIGHTNESSDOWN, 131 KEY_DOWN, 132 KEY_UP, 133 KEY_SCROLLUP, 134 KEY_SCROLLDOWN, 135 KEY_LEFTCTRL, 136 KEY_LEFTALT 137 }; 138 139 static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initdata = { 140 KEY_RESERVED, 141 KEY_RESERVED, 142 KEY_RESERVED, 143 KEY_RESERVED, 144 KEY_MAIL, 145 KEY_ROTATE_DISPLAY, 146 KEY_ESC, 147 KEY_ENTER, 148 KEY_BRIGHTNESSUP, 149 KEY_BRIGHTNESSDOWN, 150 KEY_DOWN, 151 KEY_UP, 152 KEY_SCROLLUP, 153 KEY_SCROLLDOWN, 154 KEY_LEFTCTRL, 155 KEY_LEFTALT 156 }; 157 158 static struct { 159 struct input_dev *idev; 160 struct fujitsu_config config; 161 unsigned long prev_keymask; 162 163 char phys[21]; 164 165 int irq; 166 int io_base; 167 int io_length; 168 } fujitsu; 169 170 static u8 fujitsu_ack(void) 171 { 172 return inb(fujitsu.io_base + 2); 173 } 174 175 static u8 fujitsu_status(void) 176 { 177 return inb(fujitsu.io_base + 6); 178 } 179 180 static u8 fujitsu_read_register(const u8 addr) 181 { 182 outb(addr, fujitsu.io_base); 183 return inb(fujitsu.io_base + 4); 184 } 185 186 static void fujitsu_send_state(void) 187 { 188 int state; 189 int dock, tablet_mode; 190 191 state = fujitsu_read_register(0xdd); 192 193 dock = state & 0x02; 194 if (fujitsu.config.quirks & INVERT_DOCK_STATE_BIT) 195 dock = !dock; 196 197 if ((fujitsu.config.quirks & FORCE_TABLET_MODE_IF_UNDOCK) && (!dock)) { 198 tablet_mode = 1; 199 } else{ 200 tablet_mode = state & 0x01; 201 if (fujitsu.config.quirks & INVERT_TABLET_MODE_BIT) 202 tablet_mode = !tablet_mode; 203 } 204 205 input_report_switch(fujitsu.idev, SW_DOCK, dock); 206 input_report_switch(fujitsu.idev, SW_TABLET_MODE, tablet_mode); 207 input_sync(fujitsu.idev); 208 } 209 210 static void fujitsu_reset(void) 211 { 212 int timeout = 50; 213 214 fujitsu_ack(); 215 216 while ((fujitsu_status() & 0x02) && (--timeout)) 217 msleep(20); 218 219 fujitsu_send_state(); 220 } 221 222 static int input_fujitsu_setup(struct device *parent, const char *name, 223 const char *phys) 224 { 225 struct input_dev *idev; 226 int error; 227 int i; 228 229 idev = input_allocate_device(); 230 if (!idev) 231 return -ENOMEM; 232 233 idev->dev.parent = parent; 234 idev->phys = phys; 235 idev->name = name; 236 idev->id.bustype = BUS_HOST; 237 idev->id.vendor = 0x1734; /* Fujitsu Siemens Computer GmbH */ 238 idev->id.product = 0x0001; 239 idev->id.version = 0x0101; 240 241 idev->keycode = fujitsu.config.keymap; 242 idev->keycodesize = sizeof(fujitsu.config.keymap[0]); 243 idev->keycodemax = ARRAY_SIZE(fujitsu.config.keymap); 244 245 __set_bit(EV_REP, idev->evbit); 246 247 for (i = 0; i < ARRAY_SIZE(fujitsu.config.keymap); i++) 248 if (fujitsu.config.keymap[i]) 249 input_set_capability(idev, EV_KEY, fujitsu.config.keymap[i]); 250 251 input_set_capability(idev, EV_MSC, MSC_SCAN); 252 253 input_set_capability(idev, EV_SW, SW_DOCK); 254 input_set_capability(idev, EV_SW, SW_TABLET_MODE); 255 256 error = input_register_device(idev); 257 if (error) { 258 input_free_device(idev); 259 return error; 260 } 261 262 fujitsu.idev = idev; 263 return 0; 264 } 265 266 static void input_fujitsu_remove(void) 267 { 268 input_unregister_device(fujitsu.idev); 269 } 270 271 static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) 272 { 273 unsigned long keymask, changed; 274 unsigned int keycode; 275 int pressed; 276 int i; 277 278 if (unlikely(!(fujitsu_status() & 0x01))) 279 return IRQ_NONE; 280 281 fujitsu_send_state(); 282 283 keymask = fujitsu_read_register(0xde); 284 keymask |= fujitsu_read_register(0xdf) << 8; 285 keymask ^= 0xffff; 286 287 changed = keymask ^ fujitsu.prev_keymask; 288 if (changed) { 289 fujitsu.prev_keymask = keymask; 290 291 for_each_set_bit(i, &changed, KEYMAP_LEN) { 292 keycode = fujitsu.config.keymap[i]; 293 pressed = keymask & changed & BIT(i); 294 295 if (pressed) 296 input_event(fujitsu.idev, EV_MSC, MSC_SCAN, i); 297 298 input_report_key(fujitsu.idev, keycode, pressed); 299 input_sync(fujitsu.idev); 300 } 301 } 302 303 fujitsu_ack(); 304 return IRQ_HANDLED; 305 } 306 307 static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) 308 { 309 pr_info("%s\n", dmi->ident); 310 memcpy(fujitsu.config.keymap, dmi->driver_data, 311 sizeof(fujitsu.config.keymap)); 312 } 313 314 static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) 315 { 316 fujitsu_dmi_common(dmi); 317 fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; 318 return 1; 319 } 320 321 static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) 322 { 323 fujitsu_dmi_common(dmi); 324 fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; 325 fujitsu.config.quirks |= INVERT_DOCK_STATE_BIT; 326 return 1; 327 } 328 329 static const struct dmi_system_id dmi_ids[] __initconst = { 330 { 331 .callback = fujitsu_dmi_lifebook, 332 .ident = "Fujitsu Lifebook T901", 333 .matches = { 334 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 335 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook T901") 336 }, 337 .driver_data = keymap_Lifebook_T901 338 }, 339 { 340 .callback = fujitsu_dmi_lifebook, 341 .ident = "Fujitsu Lifebook T901", 342 .matches = { 343 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 344 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T901") 345 }, 346 .driver_data = keymap_Lifebook_T901 347 }, 348 { 349 .callback = fujitsu_dmi_lifebook, 350 .ident = "Fujitsu Lifebook T902", 351 .matches = { 352 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 353 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T902") 354 }, 355 .driver_data = keymap_Lifebook_T902 356 }, 357 { 358 .callback = fujitsu_dmi_lifebook, 359 .ident = "Fujitsu Siemens P/T Series", 360 .matches = { 361 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 362 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK") 363 }, 364 .driver_data = keymap_Lifebook_Tseries 365 }, 366 { 367 .callback = fujitsu_dmi_lifebook, 368 .ident = "Fujitsu Lifebook T Series", 369 .matches = { 370 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 371 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook T") 372 }, 373 .driver_data = keymap_Lifebook_Tseries 374 }, 375 { 376 .callback = fujitsu_dmi_stylistic, 377 .ident = "Fujitsu Siemens Stylistic T Series", 378 .matches = { 379 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 380 DMI_MATCH(DMI_PRODUCT_NAME, "Stylistic T") 381 }, 382 .driver_data = keymap_Stylistic_Tseries 383 }, 384 { 385 .callback = fujitsu_dmi_lifebook, 386 .ident = "Fujitsu LifeBook U810", 387 .matches = { 388 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 389 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook U810") 390 }, 391 .driver_data = keymap_Lifebook_U810 392 }, 393 { 394 .callback = fujitsu_dmi_stylistic, 395 .ident = "Fujitsu Siemens Stylistic ST5xxx Series", 396 .matches = { 397 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 398 DMI_MATCH(DMI_PRODUCT_NAME, "STYLISTIC ST5") 399 }, 400 .driver_data = keymap_Stylistic_ST5xxx 401 }, 402 { 403 .callback = fujitsu_dmi_stylistic, 404 .ident = "Fujitsu Siemens Stylistic ST5xxx Series", 405 .matches = { 406 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 407 DMI_MATCH(DMI_PRODUCT_NAME, "Stylistic ST5") 408 }, 409 .driver_data = keymap_Stylistic_ST5xxx 410 }, 411 { 412 .callback = fujitsu_dmi_lifebook, 413 .ident = "Unknown (using defaults)", 414 .matches = { 415 DMI_MATCH(DMI_SYS_VENDOR, ""), 416 DMI_MATCH(DMI_PRODUCT_NAME, "") 417 }, 418 .driver_data = keymap_Lifebook_Tseries 419 }, 420 { NULL } 421 }; 422 423 static acpi_status fujitsu_walk_resources(struct acpi_resource *res, void *data) 424 { 425 switch (res->type) { 426 case ACPI_RESOURCE_TYPE_IRQ: 427 fujitsu.irq = res->data.irq.interrupts[0]; 428 return AE_OK; 429 430 case ACPI_RESOURCE_TYPE_IO: 431 fujitsu.io_base = res->data.io.minimum; 432 fujitsu.io_length = res->data.io.address_length; 433 return AE_OK; 434 435 case ACPI_RESOURCE_TYPE_END_TAG: 436 if (fujitsu.irq && fujitsu.io_base) 437 return AE_OK; 438 else 439 return AE_NOT_FOUND; 440 441 default: 442 return AE_ERROR; 443 } 444 } 445 446 static int acpi_fujitsu_probe(struct platform_device *pdev) 447 { 448 struct acpi_device *adev; 449 acpi_status status; 450 int error; 451 452 adev = ACPI_COMPANION(&pdev->dev); 453 if (!adev) 454 return -ENODEV; 455 456 status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS, 457 fujitsu_walk_resources, NULL); 458 if (ACPI_FAILURE(status) || !fujitsu.irq || !fujitsu.io_base) 459 return -ENODEV; 460 461 sprintf(acpi_device_name(adev), "Fujitsu %s", acpi_device_hid(adev)); 462 sprintf(acpi_device_class(adev), "%s", ACPI_FUJITSU_CLASS); 463 464 snprintf(fujitsu.phys, sizeof(fujitsu.phys), 465 "%s/input0", acpi_device_hid(adev)); 466 467 error = input_fujitsu_setup(&pdev->dev, 468 acpi_device_name(adev), fujitsu.phys); 469 if (error) 470 return error; 471 472 if (!request_region(fujitsu.io_base, fujitsu.io_length, MODULENAME)) { 473 input_fujitsu_remove(); 474 return -EBUSY; 475 } 476 477 fujitsu_reset(); 478 479 error = request_irq(fujitsu.irq, fujitsu_interrupt, 480 IRQF_SHARED, MODULENAME, fujitsu_interrupt); 481 if (error) { 482 release_region(fujitsu.io_base, fujitsu.io_length); 483 input_fujitsu_remove(); 484 return error; 485 } 486 487 return 0; 488 } 489 490 static void acpi_fujitsu_remove(struct platform_device *pdev) 491 { 492 free_irq(fujitsu.irq, fujitsu_interrupt); 493 release_region(fujitsu.io_base, fujitsu.io_length); 494 input_fujitsu_remove(); 495 } 496 497 #ifdef CONFIG_PM_SLEEP 498 static int acpi_fujitsu_resume(struct device *dev) 499 { 500 fujitsu_reset(); 501 return 0; 502 } 503 #endif 504 505 static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume); 506 507 static struct platform_driver acpi_fujitsu_driver = { 508 .probe = acpi_fujitsu_probe, 509 .remove = acpi_fujitsu_remove, 510 .driver = { 511 .name = MODULENAME, 512 .acpi_match_table = fujitsu_ids, 513 .pm = &acpi_fujitsu_pm, 514 }, 515 }; 516 517 static int __init fujitsu_module_init(void) 518 { 519 int error; 520 521 dmi_check_system(dmi_ids); 522 523 error = platform_driver_register(&acpi_fujitsu_driver); 524 if (error) 525 return error; 526 527 return 0; 528 } 529 530 static void __exit fujitsu_module_exit(void) 531 { 532 platform_driver_unregister(&acpi_fujitsu_driver); 533 } 534 535 module_init(fujitsu_module_init); 536 module_exit(fujitsu_module_exit); 537 538 MODULE_AUTHOR("Robert Gerlach <khnz@gmx.de>"); 539 MODULE_DESCRIPTION("Fujitsu tablet pc extras driver"); 540 MODULE_LICENSE("GPL"); 541 MODULE_VERSION("2.5"); 542 543 MODULE_DEVICE_TABLE(acpi, fujitsu_ids); 544