Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / tc / lk201.c
1 /*
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
8  * Copyright (C) 2001, 2002, 2003, 2004  Maciej W. Rozycki
9  */
10
11 #include <linux/config.h>
12
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/tty.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/kbd_ll.h>
20 #include <linux/kbd_kern.h>
21 #include <linux/vt_kern.h>
22
23 #include <asm/keyboard.h>
24 #include <asm/dec/tc.h>
25 #include <asm/dec/machtype.h>
26 #include <asm/dec/serial.h>
27
28 #include "lk201.h"
29
30 /*
31  * Only handle DECstations that have an LK201 interface.
32  * Maxine uses LK501 at the Access.Bus and various DECsystems
33  * have no keyboard interface at all.
34  */
35 #define LK_IFACE        (mips_machtype == MACH_DS23100    || \
36                          mips_machtype == MACH_DS5000_200 || \
37                          mips_machtype == MACH_DS5000_1XX || \
38                          mips_machtype == MACH_DS5000_2X0)
39 /*
40  * These use the Z8530 SCC.  Others use the DZ11.
41  */
42 #define LK_IFACE_ZS     (mips_machtype == MACH_DS5000_1XX || \
43                          mips_machtype == MACH_DS5000_2X0)
44
45 /* Simple translation table for the SysRq keys */
46
47 #ifdef CONFIG_MAGIC_SYSRQ
48 /*
49  * Actually no translation at all, at least until we figure out
50  * how to define SysRq for LK201 and friends. --macro
51  */
52 unsigned char lk201_sysrq_xlate[128];
53 unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
54
55 unsigned char kbd_sysrq_key = -1;
56 #endif
57
58 #define KEYB_LINE       3
59
60 static int __init lk201_init(void *);
61 static void __init lk201_info(void *);
62 static void lk201_rx_char(unsigned char, unsigned char);
63
64 static struct dec_serial_hook lk201_hook = {
65         .init_channel   = lk201_init,
66         .init_info      = lk201_info,
67         .rx_char        = NULL,
68         .poll_rx_char   = NULL,
69         .poll_tx_char   = NULL,
70         .cflags         = B4800 | CS8 | CSTOPB | CLOCAL,
71 };
72
73 /*
74  * This is used during keyboard initialisation
75  */
76 static unsigned char lk201_reset_string[] = {
77         LK_CMD_SET_DEFAULTS,
78         LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
79         LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
80         LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
81         LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
82         LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
83         LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
84         LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
85         LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
86         LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
87         LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
88         LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
89         LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
90         LK_CMD_MODE(LK_MODE_DOWN, 13),
91         LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
92         LK_CMD_DIS_KEYCLK,
93         LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
94 };
95
96 static void *lk201_handle;
97
98 static int lk201_send(unsigned char ch)
99 {
100         if (lk201_hook.poll_tx_char(lk201_handle, ch)) {
101                 printk(KERN_ERR "lk201: transmit timeout\n");
102                 return -EIO;
103         }
104         return 0;
105 }
106
107 static inline int lk201_get_id(void)
108 {
109         return lk201_send(LK_CMD_REQ_ID);
110 }
111
112 static int lk201_reset(void)
113 {
114         int i, r;
115
116         for (i = 0; i < sizeof(lk201_reset_string); i++) {
117                 r = lk201_send(lk201_reset_string[i]);
118                 if (r < 0)
119                         return r;
120         }
121         return 0;
122 }
123
124 static void lk201_report(unsigned char id[6])
125 {
126         char *report = "lk201: keyboard attached, ";
127
128         switch (id[2]) {
129         case LK_STAT_PWRUP_OK:
130                 printk(KERN_INFO "%sself-test OK\n", report);
131                 break;
132         case LK_STAT_PWRUP_KDOWN:
133                 /* The keyboard will resend the power-up ID
134                    after all keys are released, so we don't
135                    bother handling the error specially.  Still
136                    there may be a short-circuit inside.
137                  */
138                 printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n",
139                        report, id[3]);
140                 break;
141         case LK_STAT_PWRUP_ERROR:
142                 printk(KERN_ERR "%sself-test failure\n", report);
143                 break;
144         default:
145                 printk(KERN_ERR "%sunknown error: 0x%02x\n",
146                        report, id[2]);
147         }
148 }
149
150 static void lk201_id(unsigned char id[6])
151 {
152         /*
153          * Report whether there is an LK201 or an LK401
154          * The LK401 has ALT keys...
155          */
156         switch (id[4]) {
157         case 1:
158                 printk(KERN_INFO "lk201: LK201 detected\n");
159                 break;
160         case 2:
161                 printk(KERN_INFO "lk201: LK401 detected\n");
162                 break;
163         case 3:
164                 printk(KERN_INFO "lk201: LK443 detected\n");
165                 break;
166         case 4:
167                 printk(KERN_INFO "lk201: LK421 detected\n");
168                 break;
169         default:
170                 printk(KERN_WARNING
171                        "lk201: unknown keyboard detected, ID %d\n", id[4]);
172                 printk(KERN_WARNING "lk201: ... please report to "
173                        "<linux-mips@linux-mips.org>\n");
174         }
175 }
176
177 #define DEFAULT_KEYB_REP_DELAY  (250/5) /* [5ms] */
178 #define DEFAULT_KEYB_REP_RATE   30      /* [cps] */
179
180 static struct kbd_repeat kbdrate = {
181         DEFAULT_KEYB_REP_DELAY,
182         DEFAULT_KEYB_REP_RATE
183 };
184
185 static void parse_kbd_rate(struct kbd_repeat *r)
186 {
187         if (r->delay <= 0)
188                 r->delay = kbdrate.delay;
189         if (r->rate <= 0)
190                 r->rate = kbdrate.rate;
191
192         if (r->delay < 5)
193                 r->delay = 5;
194         if (r->delay > 630)
195                 r->delay = 630;
196         if (r->rate < 12)
197                 r->rate = 12;
198         if (r->rate > 127)
199                 r->rate = 127;
200         if (r->rate == 125)
201                 r->rate = 124;
202 }
203
204 static int write_kbd_rate(struct kbd_repeat *rep)
205 {
206         int delay, rate;
207         int i;
208
209         delay = rep->delay / 5;
210         rate = rep->rate;
211         for (i = 0; i < 4; i++) {
212                 if (lk201_hook.poll_tx_char(lk201_handle,
213                                             LK_CMD_RPT_RATE(i)))
214                         return 1;
215                 if (lk201_hook.poll_tx_char(lk201_handle,
216                                             LK_PARAM_DELAY(delay)))
217                         return 1;
218                 if (lk201_hook.poll_tx_char(lk201_handle,
219                                             LK_PARAM_RATE(rate)))
220                         return 1;
221         }
222         return 0;
223 }
224
225 static int lk201_kbd_rate(struct kbd_repeat *rep)
226 {
227         if (rep == NULL)
228                 return -EINVAL;
229
230         parse_kbd_rate(rep);
231
232         if (write_kbd_rate(rep)) {
233                 memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
234                 return -EIO;
235         }
236
237         memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
238
239         return 0;
240 }
241
242 static void lk201_kd_mksound(unsigned int hz, unsigned int ticks)
243 {
244         if (!ticks)
245                 return;
246
247         /*
248          * Can't set frequency and we "approximate"
249          * duration by volume. ;-)
250          */
251         ticks /= HZ / 32;
252         if (ticks > 7)
253                 ticks = 7;
254         ticks = 7 - ticks;
255
256         if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_ENB_BELL))
257                 return;
258         if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_VOLUME(ticks)))
259                 return;
260         if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_BELL))
261                 return;
262 }
263
264 void kbd_leds(unsigned char leds)
265 {
266         unsigned char l = 0;
267
268         if (!lk201_handle)              /* FIXME */
269                 return;
270
271         /* FIXME -- Only Hold and Lock LEDs for now. --macro */
272         if (leds & LED_SCR)
273                 l |= LK_LED_HOLD;
274         if (leds & LED_CAP)
275                 l |= LK_LED_LOCK;
276
277         if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_ON))
278                 return;
279         if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(l)))
280                 return;
281         if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_OFF))
282                 return;
283         if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(~l)))
284                 return;
285 }
286
287 int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
288 {
289         return -EINVAL;
290 }
291
292 int kbd_getkeycode(unsigned int scancode)
293 {
294         return -EINVAL;
295 }
296
297 int kbd_translate(unsigned char scancode, unsigned char *keycode,
298                   char raw_mode)
299 {
300         *keycode = scancode;
301         return 1;
302 }
303
304 char kbd_unexpected_up(unsigned char keycode)
305 {
306         return 0x80;
307 }
308
309 static void lk201_rx_char(unsigned char ch, unsigned char fl)
310 {
311         static unsigned char id[6];
312         static int id_i;
313
314         static int shift_state = 0;
315         static int prev_scancode;
316         unsigned char c = scancodeRemap[ch];
317
318         if (fl != TTY_NORMAL && fl != TTY_OVERRUN) {
319                 printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", fl);
320                 return;
321         }
322
323         /* Assume this is a power-up ID. */
324         if (ch == LK_STAT_PWRUP_ID && !id_i) {
325                 id[id_i++] = ch;
326                 return;
327         }
328
329         /* Handle the power-up sequence. */
330         if (id_i) {
331                 id[id_i++] = ch;
332                 if (id_i == 4) {
333                         /* OK, the power-up concluded. */
334                         lk201_report(id);
335                         if (id[2] == LK_STAT_PWRUP_OK)
336                                 lk201_get_id();
337                         else {
338                                 id_i = 0;
339                                 printk(KERN_ERR "lk201: keyboard power-up "
340                                        "error, skipping initialization\n");
341                         }
342                 } else if (id_i == 6) {
343                         /* We got the ID; report it and start operation. */
344                         id_i = 0;
345                         lk201_id(id);
346                         lk201_reset();
347                 }
348                 return;
349         }
350
351         /* Everything else is a scancode/status response. */
352         id_i = 0;
353         switch (ch) {
354         case LK_STAT_RESUME_ERR:
355         case LK_STAT_ERROR:
356         case LK_STAT_INHIBIT_ACK:
357         case LK_STAT_TEST_ACK:
358         case LK_STAT_MODE_KEYDOWN:
359         case LK_STAT_MODE_ACK:
360                 break;
361         case LK_KEY_LOCK:
362                 shift_state ^= LK_LOCK;
363                 handle_scancode(c, (shift_state & LK_LOCK) ? 1 : 0);
364                 break;
365         case LK_KEY_SHIFT:
366                 shift_state ^= LK_SHIFT;
367                 handle_scancode(c, (shift_state & LK_SHIFT) ? 1 : 0);
368                 break;
369         case LK_KEY_CTRL:
370                 shift_state ^= LK_CTRL;
371                 handle_scancode(c, (shift_state & LK_CTRL) ? 1 : 0);
372                 break;
373         case LK_KEY_COMP:
374                 shift_state ^= LK_COMP;
375                 handle_scancode(c, (shift_state & LK_COMP) ? 1 : 0);
376                 break;
377         case LK_KEY_RELEASE:
378                 if (shift_state & LK_SHIFT)
379                         handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
380                 if (shift_state & LK_CTRL)
381                         handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
382                 if (shift_state & LK_COMP)
383                         handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
384                 if (shift_state & LK_LOCK)
385                         handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
386                 shift_state = 0;
387                 break;
388         case LK_KEY_REPEAT:
389                 handle_scancode(prev_scancode, 1);
390                 break;
391         default:
392                 prev_scancode = c;
393                 handle_scancode(c, 1);
394                 break;
395         }
396         tasklet_schedule(&keyboard_tasklet);
397 }
398
399 static void __init lk201_info(void *handle)
400 {
401 }
402
403 static int __init lk201_init(void *handle)
404 {
405         /* First install handlers. */
406         lk201_handle = handle;
407         kbd_rate = lk201_kbd_rate;
408         kd_mksound = lk201_kd_mksound;
409
410         lk201_hook.rx_char = lk201_rx_char;
411
412         /* Then just issue a reset -- the handlers will do the rest. */
413         lk201_send(LK_CMD_POWER_UP);
414
415         return 0;
416 }
417
418 void __init kbd_init_hw(void)
419 {
420         /* Maxine uses LK501 at the Access.Bus. */
421         if (!LK_IFACE)
422                 return;
423
424         printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n");
425
426         if (LK_IFACE_ZS) {
427                 /*
428                  * kbd_init_hw() is being called before
429                  * rs_init() so just register the kbd hook
430                  * and let zs_init do the rest :-)
431                  */
432                 if (!register_dec_serial_hook(KEYB_LINE, &lk201_hook))
433                         unregister_dec_serial_hook(KEYB_LINE);
434         } else {
435                 /*
436                  * TODO: modify dz.c to allow similar hooks
437                  * for LK201 handling on DS2100, DS3100, and DS5000/200
438                  */
439                 printk(KERN_ERR "lk201: support for DZ11 not yet ready.\n");
440         }
441 }