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