Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006-2012 Robert Gerlach <khnz@gmx.de>
0004  * Copyright (C) 2005-2006 Jan Rychter <jan@rychter.com>
0005  */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/bitops.h>
0013 #include <linux/io.h>
0014 #include <linux/ioport.h>
0015 #include <linux/acpi.h>
0016 #include <linux/device.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/input.h>
0019 #include <linux/delay.h>
0020 #include <linux/dmi.h>
0021 
0022 #define MODULENAME "fujitsu-tablet"
0023 
0024 #define ACPI_FUJITSU_CLASS "fujitsu"
0025 
0026 #define INVERT_TABLET_MODE_BIT      0x01
0027 #define INVERT_DOCK_STATE_BIT       0x02
0028 #define FORCE_TABLET_MODE_IF_UNDOCK 0x04
0029 
0030 #define KEYMAP_LEN 16
0031 
0032 static const struct acpi_device_id fujitsu_ids[] = {
0033     { .id = "FUJ02BD" },
0034     { .id = "FUJ02BF" },
0035     { .id = "" }
0036 };
0037 
0038 struct fujitsu_config {
0039     unsigned short keymap[KEYMAP_LEN];
0040     unsigned int quirks;
0041 };
0042 
0043 static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initdata = {
0044     KEY_RESERVED,
0045     KEY_RESERVED,
0046     KEY_RESERVED,
0047     KEY_RESERVED,
0048     KEY_SCROLLDOWN,
0049     KEY_SCROLLUP,
0050     KEY_ROTATE_DISPLAY,
0051     KEY_LEFTCTRL,
0052     KEY_BRIGHTNESSUP,
0053     KEY_BRIGHTNESSDOWN,
0054     KEY_BRIGHTNESS_ZERO,
0055     KEY_RESERVED,
0056     KEY_RESERVED,
0057     KEY_RESERVED,
0058     KEY_RESERVED,
0059     KEY_LEFTALT
0060 };
0061 
0062 static unsigned short keymap_Lifebook_T901[KEYMAP_LEN] __initdata = {
0063     KEY_RESERVED,
0064     KEY_RESERVED,
0065     KEY_RESERVED,
0066     KEY_RESERVED,
0067     KEY_SCROLLDOWN,
0068     KEY_SCROLLUP,
0069     KEY_CYCLEWINDOWS,
0070     KEY_LEFTCTRL,
0071     KEY_RESERVED,
0072     KEY_RESERVED,
0073     KEY_RESERVED,
0074     KEY_RESERVED,
0075     KEY_RESERVED,
0076     KEY_RESERVED,
0077     KEY_RESERVED,
0078     KEY_LEFTMETA
0079 };
0080 
0081 static unsigned short keymap_Lifebook_T902[KEYMAP_LEN] __initdata = {
0082     KEY_RESERVED,
0083     KEY_VOLUMEDOWN,
0084     KEY_VOLUMEUP,
0085     KEY_CYCLEWINDOWS,
0086     KEY_PROG1,
0087     KEY_PROG2,
0088     KEY_LEFTMETA,
0089     KEY_RESERVED,
0090     KEY_RESERVED,
0091     KEY_RESERVED,
0092     KEY_RESERVED,
0093     KEY_RESERVED,
0094     KEY_RESERVED,
0095     KEY_RESERVED,
0096     KEY_RESERVED,
0097     KEY_RESERVED,
0098 };
0099 
0100 static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initdata = {
0101     KEY_RESERVED,
0102     KEY_RESERVED,
0103     KEY_RESERVED,
0104     KEY_RESERVED,
0105     KEY_PROG1,
0106     KEY_PROG2,
0107     KEY_ROTATE_DISPLAY,
0108     KEY_RESERVED,
0109     KEY_RESERVED,
0110     KEY_RESERVED,
0111     KEY_UP,
0112     KEY_DOWN,
0113     KEY_RESERVED,
0114     KEY_RESERVED,
0115     KEY_LEFTCTRL,
0116     KEY_LEFTALT
0117 };
0118 
0119 static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initdata = {
0120     KEY_RESERVED,
0121     KEY_RESERVED,
0122     KEY_RESERVED,
0123     KEY_RESERVED,
0124     KEY_PRINT,
0125     KEY_BACKSPACE,
0126     KEY_SPACE,
0127     KEY_ENTER,
0128     KEY_BRIGHTNESSUP,
0129     KEY_BRIGHTNESSDOWN,
0130     KEY_DOWN,
0131     KEY_UP,
0132     KEY_SCROLLUP,
0133     KEY_SCROLLDOWN,
0134     KEY_LEFTCTRL,
0135     KEY_LEFTALT
0136 };
0137 
0138 static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initdata = {
0139     KEY_RESERVED,
0140     KEY_RESERVED,
0141     KEY_RESERVED,
0142     KEY_RESERVED,
0143     KEY_MAIL,
0144     KEY_ROTATE_DISPLAY,
0145     KEY_ESC,
0146     KEY_ENTER,
0147     KEY_BRIGHTNESSUP,
0148     KEY_BRIGHTNESSDOWN,
0149     KEY_DOWN,
0150     KEY_UP,
0151     KEY_SCROLLUP,
0152     KEY_SCROLLDOWN,
0153     KEY_LEFTCTRL,
0154     KEY_LEFTALT
0155 };
0156 
0157 static struct {
0158     struct input_dev *idev;
0159     struct fujitsu_config config;
0160     unsigned long prev_keymask;
0161 
0162     char phys[21];
0163 
0164     int irq;
0165     int io_base;
0166     int io_length;
0167 } fujitsu;
0168 
0169 static u8 fujitsu_ack(void)
0170 {
0171     return inb(fujitsu.io_base + 2);
0172 }
0173 
0174 static u8 fujitsu_status(void)
0175 {
0176     return inb(fujitsu.io_base + 6);
0177 }
0178 
0179 static u8 fujitsu_read_register(const u8 addr)
0180 {
0181     outb(addr, fujitsu.io_base);
0182     return inb(fujitsu.io_base + 4);
0183 }
0184 
0185 static void fujitsu_send_state(void)
0186 {
0187     int state;
0188     int dock, tablet_mode;
0189 
0190     state = fujitsu_read_register(0xdd);
0191 
0192     dock = state & 0x02;
0193     if (fujitsu.config.quirks & INVERT_DOCK_STATE_BIT)
0194         dock = !dock;
0195 
0196     if ((fujitsu.config.quirks & FORCE_TABLET_MODE_IF_UNDOCK) && (!dock)) {
0197         tablet_mode = 1;
0198     } else{
0199         tablet_mode = state & 0x01;
0200         if (fujitsu.config.quirks & INVERT_TABLET_MODE_BIT)
0201             tablet_mode = !tablet_mode;
0202     }
0203 
0204     input_report_switch(fujitsu.idev, SW_DOCK, dock);
0205     input_report_switch(fujitsu.idev, SW_TABLET_MODE, tablet_mode);
0206     input_sync(fujitsu.idev);
0207 }
0208 
0209 static void fujitsu_reset(void)
0210 {
0211     int timeout = 50;
0212 
0213     fujitsu_ack();
0214 
0215     while ((fujitsu_status() & 0x02) && (--timeout))
0216         msleep(20);
0217 
0218     fujitsu_send_state();
0219 }
0220 
0221 static int input_fujitsu_setup(struct device *parent, const char *name,
0222                    const char *phys)
0223 {
0224     struct input_dev *idev;
0225     int error;
0226     int i;
0227 
0228     idev = input_allocate_device();
0229     if (!idev)
0230         return -ENOMEM;
0231 
0232     idev->dev.parent = parent;
0233     idev->phys = phys;
0234     idev->name = name;
0235     idev->id.bustype = BUS_HOST;
0236     idev->id.vendor  = 0x1734;  /* Fujitsu Siemens Computer GmbH */
0237     idev->id.product = 0x0001;
0238     idev->id.version = 0x0101;
0239 
0240     idev->keycode = fujitsu.config.keymap;
0241     idev->keycodesize = sizeof(fujitsu.config.keymap[0]);
0242     idev->keycodemax = ARRAY_SIZE(fujitsu.config.keymap);
0243 
0244     __set_bit(EV_REP, idev->evbit);
0245 
0246     for (i = 0; i < ARRAY_SIZE(fujitsu.config.keymap); i++)
0247         if (fujitsu.config.keymap[i])
0248             input_set_capability(idev, EV_KEY, fujitsu.config.keymap[i]);
0249 
0250     input_set_capability(idev, EV_MSC, MSC_SCAN);
0251 
0252     input_set_capability(idev, EV_SW, SW_DOCK);
0253     input_set_capability(idev, EV_SW, SW_TABLET_MODE);
0254 
0255     error = input_register_device(idev);
0256     if (error) {
0257         input_free_device(idev);
0258         return error;
0259     }
0260 
0261     fujitsu.idev = idev;
0262     return 0;
0263 }
0264 
0265 static void input_fujitsu_remove(void)
0266 {
0267     input_unregister_device(fujitsu.idev);
0268 }
0269 
0270 static irqreturn_t fujitsu_interrupt(int irq, void *dev_id)
0271 {
0272     unsigned long keymask, changed;
0273     unsigned int keycode;
0274     int pressed;
0275     int i;
0276 
0277     if (unlikely(!(fujitsu_status() & 0x01)))
0278         return IRQ_NONE;
0279 
0280     fujitsu_send_state();
0281 
0282     keymask  = fujitsu_read_register(0xde);
0283     keymask |= fujitsu_read_register(0xdf) << 8;
0284     keymask ^= 0xffff;
0285 
0286     changed = keymask ^ fujitsu.prev_keymask;
0287     if (changed) {
0288         fujitsu.prev_keymask = keymask;
0289 
0290         for_each_set_bit(i, &changed, KEYMAP_LEN) {
0291             keycode = fujitsu.config.keymap[i];
0292             pressed = keymask & changed & BIT(i);
0293 
0294             if (pressed)
0295                 input_event(fujitsu.idev, EV_MSC, MSC_SCAN, i);
0296 
0297             input_report_key(fujitsu.idev, keycode, pressed);
0298             input_sync(fujitsu.idev);
0299         }
0300     }
0301 
0302     fujitsu_ack();
0303     return IRQ_HANDLED;
0304 }
0305 
0306 static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi)
0307 {
0308     pr_info("%s\n", dmi->ident);
0309     memcpy(fujitsu.config.keymap, dmi->driver_data,
0310             sizeof(fujitsu.config.keymap));
0311 }
0312 
0313 static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
0314 {
0315     fujitsu_dmi_common(dmi);
0316     fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
0317     return 1;
0318 }
0319 
0320 static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
0321 {
0322     fujitsu_dmi_common(dmi);
0323     fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
0324     fujitsu.config.quirks |= INVERT_DOCK_STATE_BIT;
0325     return 1;
0326 }
0327 
0328 static const struct dmi_system_id dmi_ids[] __initconst = {
0329     {
0330         .callback = fujitsu_dmi_lifebook,
0331         .ident = "Fujitsu Lifebook T901",
0332         .matches = {
0333             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0334             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook T901")
0335         },
0336         .driver_data = keymap_Lifebook_T901
0337     },
0338     {
0339         .callback = fujitsu_dmi_lifebook,
0340         .ident = "Fujitsu Lifebook T901",
0341         .matches = {
0342             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0343             DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T901")
0344         },
0345         .driver_data = keymap_Lifebook_T901
0346     },
0347     {
0348         .callback = fujitsu_dmi_lifebook,
0349         .ident = "Fujitsu Lifebook T902",
0350         .matches = {
0351             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0352             DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T902")
0353         },
0354         .driver_data = keymap_Lifebook_T902
0355     },
0356     {
0357         .callback = fujitsu_dmi_lifebook,
0358         .ident = "Fujitsu Siemens P/T Series",
0359         .matches = {
0360             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0361             DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK")
0362         },
0363         .driver_data = keymap_Lifebook_Tseries
0364     },
0365     {
0366         .callback = fujitsu_dmi_lifebook,
0367         .ident = "Fujitsu Lifebook T Series",
0368         .matches = {
0369             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0370             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook T")
0371         },
0372         .driver_data = keymap_Lifebook_Tseries
0373     },
0374     {
0375         .callback = fujitsu_dmi_stylistic,
0376         .ident = "Fujitsu Siemens Stylistic T Series",
0377         .matches = {
0378             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0379             DMI_MATCH(DMI_PRODUCT_NAME, "Stylistic T")
0380         },
0381         .driver_data = keymap_Stylistic_Tseries
0382     },
0383     {
0384         .callback = fujitsu_dmi_lifebook,
0385         .ident = "Fujitsu LifeBook U810",
0386         .matches = {
0387             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0388             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook U810")
0389         },
0390         .driver_data = keymap_Lifebook_U810
0391     },
0392     {
0393         .callback = fujitsu_dmi_stylistic,
0394         .ident = "Fujitsu Siemens Stylistic ST5xxx Series",
0395         .matches = {
0396             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0397             DMI_MATCH(DMI_PRODUCT_NAME, "STYLISTIC ST5")
0398         },
0399         .driver_data = keymap_Stylistic_ST5xxx
0400     },
0401     {
0402         .callback = fujitsu_dmi_stylistic,
0403         .ident = "Fujitsu Siemens Stylistic ST5xxx Series",
0404         .matches = {
0405             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0406             DMI_MATCH(DMI_PRODUCT_NAME, "Stylistic ST5")
0407         },
0408         .driver_data = keymap_Stylistic_ST5xxx
0409     },
0410     {
0411         .callback = fujitsu_dmi_lifebook,
0412         .ident = "Unknown (using defaults)",
0413         .matches = {
0414             DMI_MATCH(DMI_SYS_VENDOR, ""),
0415             DMI_MATCH(DMI_PRODUCT_NAME, "")
0416         },
0417         .driver_data = keymap_Lifebook_Tseries
0418     },
0419     { NULL }
0420 };
0421 
0422 static acpi_status fujitsu_walk_resources(struct acpi_resource *res, void *data)
0423 {
0424     switch (res->type) {
0425     case ACPI_RESOURCE_TYPE_IRQ:
0426         fujitsu.irq = res->data.irq.interrupts[0];
0427         return AE_OK;
0428 
0429     case ACPI_RESOURCE_TYPE_IO:
0430         fujitsu.io_base = res->data.io.minimum;
0431         fujitsu.io_length = res->data.io.address_length;
0432         return AE_OK;
0433 
0434     case ACPI_RESOURCE_TYPE_END_TAG:
0435         if (fujitsu.irq && fujitsu.io_base)
0436             return AE_OK;
0437         else
0438             return AE_NOT_FOUND;
0439 
0440     default:
0441         return AE_ERROR;
0442     }
0443 }
0444 
0445 static int acpi_fujitsu_add(struct acpi_device *adev)
0446 {
0447     acpi_status status;
0448     int error;
0449 
0450     if (!adev)
0451         return -EINVAL;
0452 
0453     status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
0454             fujitsu_walk_resources, NULL);
0455     if (ACPI_FAILURE(status) || !fujitsu.irq || !fujitsu.io_base)
0456         return -ENODEV;
0457 
0458     sprintf(acpi_device_name(adev), "Fujitsu %s", acpi_device_hid(adev));
0459     sprintf(acpi_device_class(adev), "%s", ACPI_FUJITSU_CLASS);
0460 
0461     snprintf(fujitsu.phys, sizeof(fujitsu.phys),
0462             "%s/input0", acpi_device_hid(adev));
0463 
0464     error = input_fujitsu_setup(&adev->dev,
0465         acpi_device_name(adev), fujitsu.phys);
0466     if (error)
0467         return error;
0468 
0469     if (!request_region(fujitsu.io_base, fujitsu.io_length, MODULENAME)) {
0470         input_fujitsu_remove();
0471         return -EBUSY;
0472     }
0473 
0474     fujitsu_reset();
0475 
0476     error = request_irq(fujitsu.irq, fujitsu_interrupt,
0477             IRQF_SHARED, MODULENAME, fujitsu_interrupt);
0478     if (error) {
0479         release_region(fujitsu.io_base, fujitsu.io_length);
0480         input_fujitsu_remove();
0481         return error;
0482     }
0483 
0484     return 0;
0485 }
0486 
0487 static int acpi_fujitsu_remove(struct acpi_device *adev)
0488 {
0489     free_irq(fujitsu.irq, fujitsu_interrupt);
0490     release_region(fujitsu.io_base, fujitsu.io_length);
0491     input_fujitsu_remove();
0492     return 0;
0493 }
0494 
0495 #ifdef CONFIG_PM_SLEEP
0496 static int acpi_fujitsu_resume(struct device *dev)
0497 {
0498     fujitsu_reset();
0499     return 0;
0500 }
0501 #endif
0502 
0503 static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume);
0504 
0505 static struct acpi_driver acpi_fujitsu_driver = {
0506     .name  = MODULENAME,
0507     .class = "hotkey",
0508     .ids   = fujitsu_ids,
0509     .ops   = {
0510         .add    = acpi_fujitsu_add,
0511         .remove = acpi_fujitsu_remove,
0512     },
0513     .drv.pm = &acpi_fujitsu_pm,
0514 };
0515 
0516 static int __init fujitsu_module_init(void)
0517 {
0518     int error;
0519 
0520     dmi_check_system(dmi_ids);
0521 
0522     error = acpi_bus_register_driver(&acpi_fujitsu_driver);
0523     if (error)
0524         return error;
0525 
0526     return 0;
0527 }
0528 
0529 static void __exit fujitsu_module_exit(void)
0530 {
0531     acpi_bus_unregister_driver(&acpi_fujitsu_driver);
0532 }
0533 
0534 module_init(fujitsu_module_init);
0535 module_exit(fujitsu_module_exit);
0536 
0537 MODULE_AUTHOR("Robert Gerlach <khnz@gmx.de>");
0538 MODULE_DESCRIPTION("Fujitsu tablet pc extras driver");
0539 MODULE_LICENSE("GPL");
0540 MODULE_VERSION("2.5");
0541 
0542 MODULE_DEVICE_TABLE(acpi, fujitsu_ids);