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