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