1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
39#include <linux/module.h>
40
41#include <linux/types.h>
42#include <linux/errno.h>
43#include <linux/signal.h>
44#include <linux/sched.h>
45#include <linux/spinlock.h>
46#include <linux/interrupt.h>
47#include <linux/miscdevice.h>
48#include <linux/slab.h>
49#include <linux/ioport.h>
50#include <linux/fcntl.h>
51#include <linux/init.h>
52#include <linux/delay.h>
53#include <linux/kernel.h>
54#include <linux/ctype.h>
55#include <linux/parport.h>
56#include <linux/list.h>
57#include <linux/notifier.h>
58#include <linux/reboot.h>
59#include <generated/utsrelease.h>
60
61#include <linux/io.h>
62#include <linux/uaccess.h>
63
64#define LCD_MINOR 156
65#define KEYPAD_MINOR 185
66
67#define PANEL_VERSION "0.9.5"
68
69#define LCD_MAXBYTES 256
70
71#define KEYPAD_BUFFER 64
72
73
74#define INPUT_POLL_TIME (HZ/50)
75
76#define KEYPAD_REP_START (10)
77
78#define KEYPAD_REP_DELAY (2)
79
80
81#define FLASH_LIGHT_TEMPO (200)
82
83
84#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3)
85
86#define PNL_PBUSY 0x80
87#define PNL_PACK 0x40
88#define PNL_POUTPA 0x20
89#define PNL_PSELECD 0x10
90#define PNL_PERRORP 0x08
91
92#define PNL_PBIDIR 0x20
93
94#define PNL_PINTEN 0x10
95#define PNL_PSELECP 0x08
96#define PNL_PINITP 0x04
97#define PNL_PAUTOLF 0x02
98#define PNL_PSTROBE 0x01
99
100#define PNL_PD0 0x01
101#define PNL_PD1 0x02
102#define PNL_PD2 0x04
103#define PNL_PD3 0x08
104#define PNL_PD4 0x10
105#define PNL_PD5 0x20
106#define PNL_PD6 0x40
107#define PNL_PD7 0x80
108
109#define PIN_NONE 0
110#define PIN_STROBE 1
111#define PIN_D0 2
112#define PIN_D1 3
113#define PIN_D2 4
114#define PIN_D3 5
115#define PIN_D4 6
116#define PIN_D5 7
117#define PIN_D6 8
118#define PIN_D7 9
119#define PIN_AUTOLF 14
120#define PIN_INITP 16
121#define PIN_SELECP 17
122#define PIN_NOT_SET 127
123
124#define LCD_FLAG_S 0x0001
125#define LCD_FLAG_ID 0x0002
126#define LCD_FLAG_B 0x0004
127#define LCD_FLAG_C 0x0008
128#define LCD_FLAG_D 0x0010
129#define LCD_FLAG_F 0x0020
130#define LCD_FLAG_N 0x0040
131#define LCD_FLAG_L 0x0080
132
133
134#define LCD_CMD_DISPLAY_CLEAR 0x01
135
136#define LCD_CMD_ENTRY_MODE 0x04
137#define LCD_CMD_CURSOR_INC 0x02
138
139#define LCD_CMD_DISPLAY_CTRL 0x08
140#define LCD_CMD_DISPLAY_ON 0x04
141#define LCD_CMD_CURSOR_ON 0x02
142#define LCD_CMD_BLINK_ON 0x01
143
144#define LCD_CMD_SHIFT 0x10
145#define LCD_CMD_DISPLAY_SHIFT 0x08
146#define LCD_CMD_SHIFT_RIGHT 0x04
147
148#define LCD_CMD_FUNCTION_SET 0x20
149#define LCD_CMD_DATA_LEN_8BITS 0x10
150#define LCD_CMD_TWO_LINES 0x08
151#define LCD_CMD_FONT_5X10_DOTS 0x04
152
153#define LCD_CMD_SET_CGRAM_ADDR 0x40
154
155#define LCD_CMD_SET_DDRAM_ADDR 0x80
156
157#define LCD_ESCAPE_LEN 24
158#define LCD_ESCAPE_CHAR 27
159
160#define NOT_SET -1
161
162
163#define r_ctr(x) (parport_read_control((x)->port))
164#define r_dtr(x) (parport_read_data((x)->port))
165#define r_str(x) (parport_read_status((x)->port))
166#define w_ctr(x, y) (parport_write_control((x)->port, (y)))
167#define w_dtr(x, y) (parport_write_data((x)->port, (y)))
168
169
170
171static __u8 scan_mask_o;
172
173static __u8 scan_mask_i;
174
175typedef __u64 pmask_t;
176
177enum input_type {
178 INPUT_TYPE_STD,
179 INPUT_TYPE_KBD,
180};
181
182enum input_state {
183 INPUT_ST_LOW,
184 INPUT_ST_RISING,
185 INPUT_ST_HIGH,
186 INPUT_ST_FALLING,
187};
188
189struct logical_input {
190 struct list_head list;
191 pmask_t mask;
192 pmask_t value;
193 enum input_type type;
194 enum input_state state;
195 __u8 rise_time, fall_time;
196 __u8 rise_timer, fall_timer, high_timer;
197
198 union {
199 struct {
200 void (*press_fct)(int);
201 void (*release_fct)(int);
202 int press_data;
203 int release_data;
204 } std;
205 struct {
206
207 char press_str[sizeof(void *) + sizeof(int)];
208 char repeat_str[sizeof(void *) + sizeof(int)];
209 char release_str[sizeof(void *) + sizeof(int)];
210 } kbd;
211 } u;
212};
213
214static LIST_HEAD(logical_inputs);
215
216
217
218
219
220
221
222
223
224
225
226
227
228static pmask_t phys_read;
229
230static pmask_t phys_read_prev;
231
232static pmask_t phys_curr;
233
234static pmask_t phys_prev;
235
236static char inputs_stable;
237
238
239static struct {
240 bool enabled;
241} keypad;
242
243static char keypad_buffer[KEYPAD_BUFFER];
244static int keypad_buflen;
245static int keypad_start;
246static char keypressed;
247static wait_queue_head_t keypad_read_wait;
248
249
250static struct {
251 bool enabled;
252 bool initialized;
253 bool must_clear;
254
255 int height;
256 int width;
257 int bwidth;
258 int hwidth;
259 int charset;
260 int proto;
261 int light_tempo;
262
263
264 struct {
265 int e;
266 int rs;
267 int rw;
268 int cl;
269 int da;
270 int bl;
271 } pins;
272
273
274 unsigned long int flags;
275
276
277 struct {
278 unsigned long int x;
279 unsigned long int y;
280 } addr;
281
282
283 struct {
284 char buf[LCD_ESCAPE_LEN + 1];
285 int len;
286 } esc_seq;
287} lcd;
288
289
290static int selected_lcd_type = NOT_SET;
291
292
293
294
295
296
297#define BIT_CLR 0
298#define BIT_SET 1
299#define BIT_MSK 2
300#define BIT_STATES 3
301
302
303
304#define LCD_BIT_E 0
305#define LCD_BIT_RS 1
306#define LCD_BIT_RW 2
307#define LCD_BIT_BL 3
308#define LCD_BIT_CL 4
309#define LCD_BIT_DA 5
310#define LCD_BITS 6
311
312
313
314
315#define LCD_PORT_C 0
316#define LCD_PORT_D 1
317#define LCD_PORTS 2
318
319static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
320
321
322
323
324#define LCD_PROTO_PARALLEL 0
325#define LCD_PROTO_SERIAL 1
326#define LCD_PROTO_TI_DA8XX_LCD 2
327
328
329
330
331#define LCD_CHARSET_NORMAL 0
332#define LCD_CHARSET_KS0074 1
333
334
335
336
337#define LCD_TYPE_NONE 0
338#define LCD_TYPE_CUSTOM 1
339#define LCD_TYPE_OLD 2
340#define LCD_TYPE_KS0074 3
341#define LCD_TYPE_HANTRONIX 4
342#define LCD_TYPE_NEXCOM 5
343
344
345
346
347#define KEYPAD_TYPE_NONE 0
348#define KEYPAD_TYPE_OLD 1
349#define KEYPAD_TYPE_NEW 2
350#define KEYPAD_TYPE_NEXCOM 3
351
352
353
354
355#define PANEL_PROFILE_CUSTOM 0
356#define PANEL_PROFILE_OLD 1
357#define PANEL_PROFILE_NEW 2
358#define PANEL_PROFILE_HANTRONIX 3
359#define PANEL_PROFILE_NEXCOM 4
360#define PANEL_PROFILE_LARGE 5
361
362
363
364
365#define DEFAULT_PARPORT 0
366#define DEFAULT_PROFILE PANEL_PROFILE_LARGE
367#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD
368#define DEFAULT_LCD_TYPE LCD_TYPE_OLD
369#define DEFAULT_LCD_HEIGHT 2
370#define DEFAULT_LCD_WIDTH 40
371#define DEFAULT_LCD_BWIDTH 40
372#define DEFAULT_LCD_HWIDTH 64
373#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL
374#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL
375
376#define DEFAULT_LCD_PIN_E PIN_AUTOLF
377#define DEFAULT_LCD_PIN_RS PIN_SELECP
378#define DEFAULT_LCD_PIN_RW PIN_INITP
379#define DEFAULT_LCD_PIN_SCL PIN_STROBE
380#define DEFAULT_LCD_PIN_SDA PIN_D0
381#define DEFAULT_LCD_PIN_BL PIN_NOT_SET
382
383#ifdef CONFIG_PANEL_PARPORT
384#undef DEFAULT_PARPORT
385#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT
386#endif
387
388#ifdef CONFIG_PANEL_PROFILE
389#undef DEFAULT_PROFILE
390#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE
391#endif
392
393#if DEFAULT_PROFILE == 0
394#ifdef CONFIG_PANEL_KEYPAD
395#undef DEFAULT_KEYPAD_TYPE
396#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD
397#endif
398
399#ifdef CONFIG_PANEL_LCD
400#undef DEFAULT_LCD_TYPE
401#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD
402#endif
403
404#ifdef CONFIG_PANEL_LCD_HEIGHT
405#undef DEFAULT_LCD_HEIGHT
406#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT
407#endif
408
409#ifdef CONFIG_PANEL_LCD_WIDTH
410#undef DEFAULT_LCD_WIDTH
411#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH
412#endif
413
414#ifdef CONFIG_PANEL_LCD_BWIDTH
415#undef DEFAULT_LCD_BWIDTH
416#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH
417#endif
418
419#ifdef CONFIG_PANEL_LCD_HWIDTH
420#undef DEFAULT_LCD_HWIDTH
421#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH
422#endif
423
424#ifdef CONFIG_PANEL_LCD_CHARSET
425#undef DEFAULT_LCD_CHARSET
426#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET
427#endif
428
429#ifdef CONFIG_PANEL_LCD_PROTO
430#undef DEFAULT_LCD_PROTO
431#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO
432#endif
433
434#ifdef CONFIG_PANEL_LCD_PIN_E
435#undef DEFAULT_LCD_PIN_E
436#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E
437#endif
438
439#ifdef CONFIG_PANEL_LCD_PIN_RS
440#undef DEFAULT_LCD_PIN_RS
441#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS
442#endif
443
444#ifdef CONFIG_PANEL_LCD_PIN_RW
445#undef DEFAULT_LCD_PIN_RW
446#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW
447#endif
448
449#ifdef CONFIG_PANEL_LCD_PIN_SCL
450#undef DEFAULT_LCD_PIN_SCL
451#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL
452#endif
453
454#ifdef CONFIG_PANEL_LCD_PIN_SDA
455#undef DEFAULT_LCD_PIN_SDA
456#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA
457#endif
458
459#ifdef CONFIG_PANEL_LCD_PIN_BL
460#undef DEFAULT_LCD_PIN_BL
461#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL
462#endif
463
464#endif
465
466
467
468
469static atomic_t lcd_available = ATOMIC_INIT(1);
470static atomic_t keypad_available = ATOMIC_INIT(1);
471
472static struct pardevice *pprt;
473
474static int keypad_initialized;
475
476static void (*lcd_write_cmd)(int);
477static void (*lcd_write_data)(int);
478static void (*lcd_clear_fast)(void);
479
480static DEFINE_SPINLOCK(pprt_lock);
481static struct timer_list scan_timer;
482
483MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver");
484
485static int parport = DEFAULT_PARPORT;
486module_param(parport, int, 0000);
487MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)");
488
489static int profile = DEFAULT_PROFILE;
490module_param(profile, int, 0000);
491MODULE_PARM_DESC(profile,
492 "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; "
493 "4=16x2 nexcom; default=40x2, old kp");
494
495static int keypad_type = NOT_SET;
496module_param(keypad_type, int, 0000);
497MODULE_PARM_DESC(keypad_type,
498 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
499
500static int lcd_type = NOT_SET;
501module_param(lcd_type, int, 0000);
502MODULE_PARM_DESC(lcd_type,
503 "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
504
505static int lcd_height = NOT_SET;
506module_param(lcd_height, int, 0000);
507MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD");
508
509static int lcd_width = NOT_SET;
510module_param(lcd_width, int, 0000);
511MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD");
512
513static int lcd_bwidth = NOT_SET;
514module_param(lcd_bwidth, int, 0000);
515MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)");
516
517static int lcd_hwidth = NOT_SET;
518module_param(lcd_hwidth, int, 0000);
519MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)");
520
521static int lcd_charset = NOT_SET;
522module_param(lcd_charset, int, 0000);
523MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
524
525static int lcd_proto = NOT_SET;
526module_param(lcd_proto, int, 0000);
527MODULE_PARM_DESC(lcd_proto,
528 "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
529
530
531
532
533
534
535
536
537
538
539static int lcd_e_pin = PIN_NOT_SET;
540module_param(lcd_e_pin, int, 0000);
541MODULE_PARM_DESC(lcd_e_pin,
542 "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
543
544static int lcd_rs_pin = PIN_NOT_SET;
545module_param(lcd_rs_pin, int, 0000);
546MODULE_PARM_DESC(lcd_rs_pin,
547 "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
548
549static int lcd_rw_pin = PIN_NOT_SET;
550module_param(lcd_rw_pin, int, 0000);
551MODULE_PARM_DESC(lcd_rw_pin,
552 "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
553
554static int lcd_cl_pin = PIN_NOT_SET;
555module_param(lcd_cl_pin, int, 0000);
556MODULE_PARM_DESC(lcd_cl_pin,
557 "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
558
559static int lcd_da_pin = PIN_NOT_SET;
560module_param(lcd_da_pin, int, 0000);
561MODULE_PARM_DESC(lcd_da_pin,
562 "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
563
564static int lcd_bl_pin = PIN_NOT_SET;
565module_param(lcd_bl_pin, int, 0000);
566MODULE_PARM_DESC(lcd_bl_pin,
567 "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
568
569
570
571static int lcd_enabled = NOT_SET;
572module_param(lcd_enabled, int, 0000);
573MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead");
574
575static int keypad_enabled = NOT_SET;
576module_param(keypad_enabled, int, 0000);
577MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
578
579
580static const unsigned char *lcd_char_conv;
581
582
583static const unsigned char lcd_char_conv_ks0074[256] = {
584
585 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
586 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
587 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
588 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
589 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27,
590 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
591 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
592 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
593 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
594 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
595 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
596 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4,
597 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
598 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
599 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
600 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20,
601 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
602 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
603 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
604 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
605 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f,
606 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96,
607 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd,
608 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60,
609 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9,
610 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3,
611 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78,
612 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe,
613 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8,
614 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69,
615 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25,
616 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79,
617};
618
619static const char old_keypad_profile[][4][9] = {
620 {"S0", "Left\n", "Left\n", ""},
621 {"S1", "Down\n", "Down\n", ""},
622 {"S2", "Up\n", "Up\n", ""},
623 {"S3", "Right\n", "Right\n", ""},
624 {"S4", "Esc\n", "Esc\n", ""},
625 {"S5", "Ret\n", "Ret\n", ""},
626 {"", "", "", ""}
627};
628
629
630static const char new_keypad_profile[][4][9] = {
631 {"S0", "Left\n", "Left\n", ""},
632 {"S1", "Down\n", "Down\n", ""},
633 {"S2", "Up\n", "Up\n", ""},
634 {"S3", "Right\n", "Right\n", ""},
635 {"S4s5", "", "Esc\n", "Esc\n"},
636 {"s4S5", "", "Ret\n", "Ret\n"},
637 {"S4S5", "Help\n", "", ""},
638
639 {"", "", "", ""}
640};
641
642
643static const char nexcom_keypad_profile[][4][9] = {
644 {"a-p-e-", "Down\n", "Down\n", ""},
645 {"a-p-E-", "Ret\n", "Ret\n", ""},
646 {"a-P-E-", "Esc\n", "Esc\n", ""},
647 {"a-P-e-", "Up\n", "Up\n", ""},
648
649 {"", "", "", ""}
650};
651
652static const char (*keypad_profile)[4][9] = old_keypad_profile;
653
654
655static struct {
656 unsigned char e;
657 unsigned char rs;
658 unsigned char rw;
659 unsigned char bl;
660 unsigned char cl;
661 unsigned char da;
662} bits;
663
664static void init_scan_timer(void);
665
666
667static int set_data_bits(void)
668{
669 int val, bit;
670
671 val = r_dtr(pprt);
672 for (bit = 0; bit < LCD_BITS; bit++)
673 val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK];
674
675 val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e]
676 | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs]
677 | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw]
678 | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl]
679 | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl]
680 | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da];
681
682 w_dtr(pprt, val);
683 return val;
684}
685
686
687static int set_ctrl_bits(void)
688{
689 int val, bit;
690
691 val = r_ctr(pprt);
692 for (bit = 0; bit < LCD_BITS; bit++)
693 val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK];
694
695 val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e]
696 | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs]
697 | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw]
698 | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl]
699 | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl]
700 | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da];
701
702 w_ctr(pprt, val);
703 return val;
704}
705
706
707static void panel_set_bits(void)
708{
709 set_data_bits();
710 set_ctrl_bits();
711}
712
713
714
715
716
717
718
719
720
721
722static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
723{
724 int d_bit, c_bit, inv;
725
726 d_val[0] = 0;
727 c_val[0] = 0;
728 d_val[1] = 0;
729 c_val[1] = 0;
730 d_val[2] = 0xFF;
731 c_val[2] = 0xFF;
732
733 if (pin == 0)
734 return;
735
736 inv = (pin < 0);
737 if (inv)
738 pin = -pin;
739
740 d_bit = 0;
741 c_bit = 0;
742
743 switch (pin) {
744 case PIN_STROBE:
745 c_bit = PNL_PSTROBE;
746 inv = !inv;
747 break;
748 case PIN_D0...PIN_D7:
749 d_bit = 1 << (pin - 2);
750 break;
751 case PIN_AUTOLF:
752 c_bit = PNL_PAUTOLF;
753 inv = !inv;
754 break;
755 case PIN_INITP:
756 c_bit = PNL_PINITP;
757 break;
758 case PIN_SELECP:
759 c_bit = PNL_PSELECP;
760 inv = !inv;
761 break;
762 default:
763 break;
764 }
765
766 if (c_bit) {
767 c_val[2] &= ~c_bit;
768 c_val[!inv] = c_bit;
769 } else if (d_bit) {
770 d_val[2] &= ~d_bit;
771 d_val[!inv] = d_bit;
772 }
773}
774
775
776static void long_sleep(int ms)
777{
778 if (in_interrupt()) {
779 mdelay(ms);
780 } else {
781 __set_current_state(TASK_INTERRUPTIBLE);
782 schedule_timeout((ms * HZ + 999) / 1000);
783 }
784}
785
786
787
788static void lcd_send_serial(int byte)
789{
790 int bit;
791
792
793
794 for (bit = 0; bit < 8; bit++) {
795 bits.cl = BIT_CLR;
796 panel_set_bits();
797 bits.da = byte & 1;
798 panel_set_bits();
799 udelay(2);
800 bits.cl = BIT_SET;
801 panel_set_bits();
802 udelay(1);
803 byte >>= 1;
804 }
805}
806
807
808static void lcd_backlight(int on)
809{
810 if (lcd.pins.bl == PIN_NONE)
811 return;
812
813
814 spin_lock_irq(&pprt_lock);
815 bits.bl = on;
816 panel_set_bits();
817 spin_unlock_irq(&pprt_lock);
818}
819
820
821static void lcd_write_cmd_s(int cmd)
822{
823 spin_lock_irq(&pprt_lock);
824 lcd_send_serial(0x1F);
825 lcd_send_serial(cmd & 0x0F);
826 lcd_send_serial((cmd >> 4) & 0x0F);
827 udelay(40);
828 spin_unlock_irq(&pprt_lock);
829}
830
831
832static void lcd_write_data_s(int data)
833{
834 spin_lock_irq(&pprt_lock);
835 lcd_send_serial(0x5F);
836 lcd_send_serial(data & 0x0F);
837 lcd_send_serial((data >> 4) & 0x0F);
838 udelay(40);
839 spin_unlock_irq(&pprt_lock);
840}
841
842
843static void lcd_write_cmd_p8(int cmd)
844{
845 spin_lock_irq(&pprt_lock);
846
847 w_dtr(pprt, cmd);
848 udelay(20);
849
850 bits.e = BIT_SET;
851 bits.rs = BIT_CLR;
852 bits.rw = BIT_CLR;
853 set_ctrl_bits();
854
855 udelay(40);
856
857 bits.e = BIT_CLR;
858 set_ctrl_bits();
859
860 udelay(120);
861 spin_unlock_irq(&pprt_lock);
862}
863
864
865static void lcd_write_data_p8(int data)
866{
867 spin_lock_irq(&pprt_lock);
868
869 w_dtr(pprt, data);
870 udelay(20);
871
872 bits.e = BIT_SET;
873 bits.rs = BIT_SET;
874 bits.rw = BIT_CLR;
875 set_ctrl_bits();
876
877 udelay(40);
878
879 bits.e = BIT_CLR;
880 set_ctrl_bits();
881
882 udelay(45);
883 spin_unlock_irq(&pprt_lock);
884}
885
886
887static void lcd_write_cmd_tilcd(int cmd)
888{
889 spin_lock_irq(&pprt_lock);
890
891 w_ctr(pprt, cmd);
892 udelay(60);
893 spin_unlock_irq(&pprt_lock);
894}
895
896
897static void lcd_write_data_tilcd(int data)
898{
899 spin_lock_irq(&pprt_lock);
900
901 w_dtr(pprt, data);
902 udelay(60);
903 spin_unlock_irq(&pprt_lock);
904}
905
906static void lcd_gotoxy(void)
907{
908 lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR
909 | (lcd.addr.y ? lcd.hwidth : 0)
910
911
912 | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x &
913 (lcd.hwidth - 1) : lcd.bwidth - 1));
914}
915
916static void lcd_print(char c)
917{
918 if (lcd.addr.x < lcd.bwidth) {
919 if (lcd_char_conv != NULL)
920 c = lcd_char_conv[(unsigned char)c];
921 lcd_write_data(c);
922 lcd.addr.x++;
923 }
924
925 if (lcd.addr.x == lcd.bwidth)
926 lcd_gotoxy();
927}
928
929
930static void lcd_clear_fast_s(void)
931{
932 int pos;
933
934 lcd.addr.x = 0;
935 lcd.addr.y = 0;
936 lcd_gotoxy();
937
938 spin_lock_irq(&pprt_lock);
939 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) {
940 lcd_send_serial(0x5F);
941 lcd_send_serial(' ' & 0x0F);
942 lcd_send_serial((' ' >> 4) & 0x0F);
943 udelay(40);
944 }
945 spin_unlock_irq(&pprt_lock);
946
947 lcd.addr.x = 0;
948 lcd.addr.y = 0;
949 lcd_gotoxy();
950}
951
952
953static void lcd_clear_fast_p8(void)
954{
955 int pos;
956
957 lcd.addr.x = 0;
958 lcd.addr.y = 0;
959 lcd_gotoxy();
960
961 spin_lock_irq(&pprt_lock);
962 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) {
963
964 w_dtr(pprt, ' ');
965
966
967 udelay(20);
968
969 bits.e = BIT_SET;
970 bits.rs = BIT_SET;
971 bits.rw = BIT_CLR;
972 set_ctrl_bits();
973
974
975 udelay(40);
976
977 bits.e = BIT_CLR;
978 set_ctrl_bits();
979
980
981 udelay(45);
982 }
983 spin_unlock_irq(&pprt_lock);
984
985 lcd.addr.x = 0;
986 lcd.addr.y = 0;
987 lcd_gotoxy();
988}
989
990
991static void lcd_clear_fast_tilcd(void)
992{
993 int pos;
994
995 lcd.addr.x = 0;
996 lcd.addr.y = 0;
997 lcd_gotoxy();
998
999 spin_lock_irq(&pprt_lock);
1000 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) {
1001
1002 w_dtr(pprt, ' ');
1003 udelay(60);
1004 }
1005
1006 spin_unlock_irq(&pprt_lock);
1007
1008 lcd.addr.x = 0;
1009 lcd.addr.y = 0;
1010 lcd_gotoxy();
1011}
1012
1013
1014static void lcd_clear_display(void)
1015{
1016 lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR);
1017 lcd.addr.x = 0;
1018 lcd.addr.y = 0;
1019
1020 long_sleep(15);
1021}
1022
1023static void lcd_init_display(void)
1024{
1025 lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0)
1026 | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B;
1027
1028 long_sleep(20);
1029
1030
1031 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1032 long_sleep(10);
1033 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1034 long_sleep(10);
1035 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1036 long_sleep(10);
1037
1038
1039 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS
1040 | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0)
1041 | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0)
1042 );
1043 long_sleep(10);
1044
1045
1046 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL);
1047 long_sleep(10);
1048
1049 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL
1050 | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0)
1051 | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0)
1052 | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0)
1053 );
1054
1055 lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0);
1056
1057 long_sleep(10);
1058
1059
1060 lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
1061
1062 lcd_clear_display();
1063}
1064
1065
1066
1067
1068
1069
1070
1071
1072static inline int handle_lcd_special_code(void)
1073{
1074
1075
1076 int processed = 0;
1077
1078 char *esc = lcd.esc_seq.buf + 2;
1079 int oldflags = lcd.flags;
1080
1081
1082 switch (*esc) {
1083 case 'D':
1084 lcd.flags |= LCD_FLAG_D;
1085 processed = 1;
1086 break;
1087 case 'd':
1088 lcd.flags &= ~LCD_FLAG_D;
1089 processed = 1;
1090 break;
1091 case 'C':
1092 lcd.flags |= LCD_FLAG_C;
1093 processed = 1;
1094 break;
1095 case 'c':
1096 lcd.flags &= ~LCD_FLAG_C;
1097 processed = 1;
1098 break;
1099 case 'B':
1100 lcd.flags |= LCD_FLAG_B;
1101 processed = 1;
1102 break;
1103 case 'b':
1104 lcd.flags &= ~LCD_FLAG_B;
1105 processed = 1;
1106 break;
1107 case '+':
1108 lcd.flags |= LCD_FLAG_L;
1109 processed = 1;
1110 break;
1111 case '-':
1112 lcd.flags &= ~LCD_FLAG_L;
1113 processed = 1;
1114 break;
1115 case '*':
1116
1117 if (scan_timer.function != NULL) {
1118 if (lcd.light_tempo == 0
1119 && ((lcd.flags & LCD_FLAG_L) == 0))
1120 lcd_backlight(1);
1121 lcd.light_tempo = FLASH_LIGHT_TEMPO;
1122 }
1123 processed = 1;
1124 break;
1125 case 'f':
1126 lcd.flags &= ~LCD_FLAG_F;
1127 processed = 1;
1128 break;
1129 case 'F':
1130 lcd.flags |= LCD_FLAG_F;
1131 processed = 1;
1132 break;
1133 case 'n':
1134 lcd.flags &= ~LCD_FLAG_N;
1135 processed = 1;
1136 break;
1137 case 'N':
1138 lcd.flags |= LCD_FLAG_N;
1139 break;
1140 case 'l':
1141 if (lcd.addr.x > 0) {
1142
1143 if (lcd.addr.x < lcd.bwidth)
1144 lcd_write_cmd(LCD_CMD_SHIFT);
1145 lcd.addr.x--;
1146 }
1147 processed = 1;
1148 break;
1149 case 'r':
1150 if (lcd.addr.x < lcd.width) {
1151
1152 if (lcd.addr.x < (lcd.bwidth - 1))
1153 lcd_write_cmd(LCD_CMD_SHIFT |
1154 LCD_CMD_SHIFT_RIGHT);
1155 lcd.addr.x++;
1156 }
1157 processed = 1;
1158 break;
1159 case 'L':
1160 lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
1161 processed = 1;
1162 break;
1163 case 'R':
1164 lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT |
1165 LCD_CMD_SHIFT_RIGHT);
1166 processed = 1;
1167 break;
1168 case 'k': {
1169 int x;
1170
1171 for (x = lcd.addr.x; x < lcd.bwidth; x++)
1172 lcd_write_data(' ');
1173
1174
1175 lcd_gotoxy();
1176 processed = 1;
1177 break;
1178 }
1179 case 'I':
1180 lcd_init_display();
1181 processed = 1;
1182 break;
1183 case 'G': {
1184
1185
1186
1187
1188
1189
1190
1191
1192 unsigned char cgbytes[8];
1193 unsigned char cgaddr;
1194 int cgoffset;
1195 int shift;
1196 char value;
1197 int addr;
1198
1199 if (strchr(esc, ';') == NULL)
1200 break;
1201
1202 esc++;
1203
1204 cgaddr = *(esc++) - '0';
1205 if (cgaddr > 7) {
1206 processed = 1;
1207 break;
1208 }
1209
1210 cgoffset = 0;
1211 shift = 0;
1212 value = 0;
1213 while (*esc && cgoffset < 8) {
1214 shift ^= 4;
1215 if (*esc >= '0' && *esc <= '9') {
1216 value |= (*esc - '0') << shift;
1217 } else if (*esc >= 'A' && *esc <= 'Z') {
1218 value |= (*esc - 'A' + 10) << shift;
1219 } else if (*esc >= 'a' && *esc <= 'z') {
1220 value |= (*esc - 'a' + 10) << shift;
1221 } else {
1222 esc++;
1223 continue;
1224 }
1225
1226 if (shift == 0) {
1227 cgbytes[cgoffset++] = value;
1228 value = 0;
1229 }
1230
1231 esc++;
1232 }
1233
1234 lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
1235 for (addr = 0; addr < cgoffset; addr++)
1236 lcd_write_data(cgbytes[addr]);
1237
1238
1239 lcd_gotoxy();
1240 processed = 1;
1241 break;
1242 }
1243 case 'x':
1244 case 'y':
1245 if (strchr(esc, ';') == NULL)
1246 break;
1247
1248 while (*esc) {
1249 if (*esc == 'x') {
1250 esc++;
1251 if (kstrtoul(esc, 10, &lcd.addr.x) < 0)
1252 break;
1253 } else if (*esc == 'y') {
1254 esc++;
1255 if (kstrtoul(esc, 10, &lcd.addr.y) < 0)
1256 break;
1257 } else {
1258 break;
1259 }
1260 }
1261
1262 lcd_gotoxy();
1263 processed = 1;
1264 break;
1265 }
1266
1267
1268
1269 if (oldflags != lcd.flags) {
1270
1271 if ((oldflags ^ lcd.flags) &
1272 (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
1273
1274 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL
1275 | ((lcd.flags & LCD_FLAG_D)
1276 ? LCD_CMD_DISPLAY_ON : 0)
1277 | ((lcd.flags & LCD_FLAG_C)
1278 ? LCD_CMD_CURSOR_ON : 0)
1279 | ((lcd.flags & LCD_FLAG_B)
1280 ? LCD_CMD_BLINK_ON : 0));
1281
1282 else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N))
1283 lcd_write_cmd(LCD_CMD_FUNCTION_SET
1284 | LCD_CMD_DATA_LEN_8BITS
1285 | ((lcd.flags & LCD_FLAG_F)
1286 ? LCD_CMD_TWO_LINES : 0)
1287 | ((lcd.flags & LCD_FLAG_N)
1288 ? LCD_CMD_FONT_5X10_DOTS
1289 : 0));
1290
1291 else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) {
1292 if (lcd.flags & (LCD_FLAG_L))
1293 lcd_backlight(1);
1294 else if (lcd.light_tempo == 0)
1295
1296
1297 lcd_backlight(0);
1298 }
1299 }
1300
1301 return processed;
1302}
1303
1304static void lcd_write_char(char c)
1305{
1306
1307 if ((c != '\n') && lcd.esc_seq.len >= 0) {
1308
1309 lcd.esc_seq.buf[lcd.esc_seq.len++] = c;
1310 lcd.esc_seq.buf[lcd.esc_seq.len] = 0;
1311 } else {
1312
1313 lcd.esc_seq.len = -1;
1314
1315 switch (c) {
1316 case LCD_ESCAPE_CHAR:
1317
1318 lcd.esc_seq.len = 0;
1319 lcd.esc_seq.buf[lcd.esc_seq.len] = 0;
1320 break;
1321 case '\b':
1322
1323 if (lcd.addr.x > 0) {
1324
1325
1326 if (lcd.addr.x < lcd.bwidth)
1327
1328 lcd_write_cmd(LCD_CMD_SHIFT);
1329 lcd.addr.x--;
1330 }
1331
1332 lcd_write_data(' ');
1333
1334 lcd_write_cmd(LCD_CMD_SHIFT);
1335 break;
1336 case '\014':
1337
1338 lcd_clear_fast();
1339 break;
1340 case '\n':
1341
1342
1343 for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++)
1344 lcd_write_data(' ');
1345 lcd.addr.x = 0;
1346 lcd.addr.y = (lcd.addr.y + 1) % lcd.height;
1347 lcd_gotoxy();
1348 break;
1349 case '\r':
1350
1351 lcd.addr.x = 0;
1352 lcd_gotoxy();
1353 break;
1354 case '\t':
1355
1356 lcd_print(' ');
1357 break;
1358 default:
1359
1360 lcd_print(c);
1361 break;
1362 }
1363 }
1364
1365
1366
1367 if (lcd.esc_seq.len >= 2) {
1368 int processed = 0;
1369
1370 if (!strcmp(lcd.esc_seq.buf, "[2J")) {
1371
1372 lcd_clear_fast();
1373 processed = 1;
1374 } else if (!strcmp(lcd.esc_seq.buf, "[H")) {
1375
1376 lcd.addr.x = 0;
1377 lcd.addr.y = 0;
1378 lcd_gotoxy();
1379 processed = 1;
1380 }
1381
1382 else if ((lcd.esc_seq.len >= 3) &&
1383 (lcd.esc_seq.buf[0] == '[') &&
1384 (lcd.esc_seq.buf[1] == 'L')) {
1385 processed = handle_lcd_special_code();
1386 }
1387
1388
1389
1390
1391 if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN))
1392 lcd.esc_seq.len = -1;
1393 }
1394}
1395
1396static ssize_t lcd_write(struct file *file,
1397 const char __user *buf, size_t count, loff_t *ppos)
1398{
1399 const char __user *tmp = buf;
1400 char c;
1401
1402 for (; count-- > 0; (*ppos)++, tmp++) {
1403 if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
1404
1405
1406 schedule();
1407
1408 if (get_user(c, tmp))
1409 return -EFAULT;
1410
1411 lcd_write_char(c);
1412 }
1413
1414 return tmp - buf;
1415}
1416
1417static int lcd_open(struct inode *inode, struct file *file)
1418{
1419 if (!atomic_dec_and_test(&lcd_available))
1420 return -EBUSY;
1421
1422 if (file->f_mode & FMODE_READ)
1423 return -EPERM;
1424
1425 if (lcd.must_clear) {
1426 lcd_clear_display();
1427 lcd.must_clear = false;
1428 }
1429 return nonseekable_open(inode, file);
1430}
1431
1432static int lcd_release(struct inode *inode, struct file *file)
1433{
1434 atomic_inc(&lcd_available);
1435 return 0;
1436}
1437
1438static const struct file_operations lcd_fops = {
1439 .write = lcd_write,
1440 .open = lcd_open,
1441 .release = lcd_release,
1442 .llseek = no_llseek,
1443};
1444
1445static struct miscdevice lcd_dev = {
1446 .minor = LCD_MINOR,
1447 .name = "lcd",
1448 .fops = &lcd_fops,
1449};
1450
1451
1452static void panel_lcd_print(const char *s)
1453{
1454 const char *tmp = s;
1455 int count = strlen(s);
1456
1457 if (lcd.enabled && lcd.initialized) {
1458 for (; count-- > 0; tmp++) {
1459 if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
1460
1461
1462 schedule();
1463
1464 lcd_write_char(*tmp);
1465 }
1466 }
1467}
1468
1469
1470static void lcd_init(void)
1471{
1472 switch (selected_lcd_type) {
1473 case LCD_TYPE_OLD:
1474
1475 lcd.proto = LCD_PROTO_PARALLEL;
1476 lcd.charset = LCD_CHARSET_NORMAL;
1477 lcd.pins.e = PIN_STROBE;
1478 lcd.pins.rs = PIN_AUTOLF;
1479
1480 lcd.width = 40;
1481 lcd.bwidth = 40;
1482 lcd.hwidth = 64;
1483 lcd.height = 2;
1484 break;
1485 case LCD_TYPE_KS0074:
1486
1487 lcd.proto = LCD_PROTO_SERIAL;
1488 lcd.charset = LCD_CHARSET_KS0074;
1489 lcd.pins.bl = PIN_AUTOLF;
1490 lcd.pins.cl = PIN_STROBE;
1491 lcd.pins.da = PIN_D0;
1492
1493 lcd.width = 16;
1494 lcd.bwidth = 40;
1495 lcd.hwidth = 16;
1496 lcd.height = 2;
1497 break;
1498 case LCD_TYPE_NEXCOM:
1499
1500 lcd.proto = LCD_PROTO_PARALLEL;
1501 lcd.charset = LCD_CHARSET_NORMAL;
1502 lcd.pins.e = PIN_AUTOLF;
1503 lcd.pins.rs = PIN_SELECP;
1504 lcd.pins.rw = PIN_INITP;
1505
1506 lcd.width = 16;
1507 lcd.bwidth = 40;
1508 lcd.hwidth = 64;
1509 lcd.height = 2;
1510 break;
1511 case LCD_TYPE_CUSTOM:
1512
1513 lcd.proto = DEFAULT_LCD_PROTO;
1514 lcd.charset = DEFAULT_LCD_CHARSET;
1515
1516 break;
1517 case LCD_TYPE_HANTRONIX:
1518
1519 default:
1520 lcd.proto = LCD_PROTO_PARALLEL;
1521 lcd.charset = LCD_CHARSET_NORMAL;
1522 lcd.pins.e = PIN_STROBE;
1523 lcd.pins.rs = PIN_SELECP;
1524
1525 lcd.width = 16;
1526 lcd.bwidth = 40;
1527 lcd.hwidth = 64;
1528 lcd.height = 2;
1529 break;
1530 }
1531
1532
1533 if (lcd_height != NOT_SET)
1534 lcd.height = lcd_height;
1535 if (lcd_width != NOT_SET)
1536 lcd.width = lcd_width;
1537 if (lcd_bwidth != NOT_SET)
1538 lcd.bwidth = lcd_bwidth;
1539 if (lcd_hwidth != NOT_SET)
1540 lcd.hwidth = lcd_hwidth;
1541 if (lcd_charset != NOT_SET)
1542 lcd.charset = lcd_charset;
1543 if (lcd_proto != NOT_SET)
1544 lcd.proto = lcd_proto;
1545 if (lcd_e_pin != PIN_NOT_SET)
1546 lcd.pins.e = lcd_e_pin;
1547 if (lcd_rs_pin != PIN_NOT_SET)
1548 lcd.pins.rs = lcd_rs_pin;
1549 if (lcd_rw_pin != PIN_NOT_SET)
1550 lcd.pins.rw = lcd_rw_pin;
1551 if (lcd_cl_pin != PIN_NOT_SET)
1552 lcd.pins.cl = lcd_cl_pin;
1553 if (lcd_da_pin != PIN_NOT_SET)
1554 lcd.pins.da = lcd_da_pin;
1555 if (lcd_bl_pin != PIN_NOT_SET)
1556 lcd.pins.bl = lcd_bl_pin;
1557
1558
1559 if (lcd.width <= 0)
1560 lcd.width = DEFAULT_LCD_WIDTH;
1561 if (lcd.bwidth <= 0)
1562 lcd.bwidth = DEFAULT_LCD_BWIDTH;
1563 if (lcd.hwidth <= 0)
1564 lcd.hwidth = DEFAULT_LCD_HWIDTH;
1565 if (lcd.height <= 0)
1566 lcd.height = DEFAULT_LCD_HEIGHT;
1567
1568 if (lcd.proto == LCD_PROTO_SERIAL) {
1569 lcd_write_cmd = lcd_write_cmd_s;
1570 lcd_write_data = lcd_write_data_s;
1571 lcd_clear_fast = lcd_clear_fast_s;
1572
1573 if (lcd.pins.cl == PIN_NOT_SET)
1574 lcd.pins.cl = DEFAULT_LCD_PIN_SCL;
1575 if (lcd.pins.da == PIN_NOT_SET)
1576 lcd.pins.da = DEFAULT_LCD_PIN_SDA;
1577
1578 } else if (lcd.proto == LCD_PROTO_PARALLEL) {
1579 lcd_write_cmd = lcd_write_cmd_p8;
1580 lcd_write_data = lcd_write_data_p8;
1581 lcd_clear_fast = lcd_clear_fast_p8;
1582
1583 if (lcd.pins.e == PIN_NOT_SET)
1584 lcd.pins.e = DEFAULT_LCD_PIN_E;
1585 if (lcd.pins.rs == PIN_NOT_SET)
1586 lcd.pins.rs = DEFAULT_LCD_PIN_RS;
1587 if (lcd.pins.rw == PIN_NOT_SET)
1588 lcd.pins.rw = DEFAULT_LCD_PIN_RW;
1589 } else {
1590 lcd_write_cmd = lcd_write_cmd_tilcd;
1591 lcd_write_data = lcd_write_data_tilcd;
1592 lcd_clear_fast = lcd_clear_fast_tilcd;
1593 }
1594
1595 if (lcd.pins.bl == PIN_NOT_SET)
1596 lcd.pins.bl = DEFAULT_LCD_PIN_BL;
1597
1598 if (lcd.pins.e == PIN_NOT_SET)
1599 lcd.pins.e = PIN_NONE;
1600 if (lcd.pins.rs == PIN_NOT_SET)
1601 lcd.pins.rs = PIN_NONE;
1602 if (lcd.pins.rw == PIN_NOT_SET)
1603 lcd.pins.rw = PIN_NONE;
1604 if (lcd.pins.bl == PIN_NOT_SET)
1605 lcd.pins.bl = PIN_NONE;
1606 if (lcd.pins.cl == PIN_NOT_SET)
1607 lcd.pins.cl = PIN_NONE;
1608 if (lcd.pins.da == PIN_NOT_SET)
1609 lcd.pins.da = PIN_NONE;
1610
1611 if (lcd.charset == NOT_SET)
1612 lcd.charset = DEFAULT_LCD_CHARSET;
1613
1614 if (lcd.charset == LCD_CHARSET_KS0074)
1615 lcd_char_conv = lcd_char_conv_ks0074;
1616 else
1617 lcd_char_conv = NULL;
1618
1619 if (lcd.pins.bl != PIN_NONE)
1620 init_scan_timer();
1621
1622 pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E],
1623 lcd_bits[LCD_PORT_C][LCD_BIT_E]);
1624 pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS],
1625 lcd_bits[LCD_PORT_C][LCD_BIT_RS]);
1626 pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW],
1627 lcd_bits[LCD_PORT_C][LCD_BIT_RW]);
1628 pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL],
1629 lcd_bits[LCD_PORT_C][LCD_BIT_BL]);
1630 pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL],
1631 lcd_bits[LCD_PORT_C][LCD_BIT_CL]);
1632 pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA],
1633 lcd_bits[LCD_PORT_C][LCD_BIT_DA]);
1634
1635
1636
1637
1638 lcd.initialized = true;
1639 lcd_init_display();
1640
1641
1642#ifdef CONFIG_PANEL_CHANGE_MESSAGE
1643#ifdef CONFIG_PANEL_BOOT_MESSAGE
1644 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
1645#endif
1646#else
1647 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-"
1648 PANEL_VERSION);
1649#endif
1650 lcd.addr.x = 0;
1651 lcd.addr.y = 0;
1652
1653 lcd.must_clear = true;
1654 lcd_gotoxy();
1655}
1656
1657
1658
1659
1660
1661static ssize_t keypad_read(struct file *file,
1662 char __user *buf, size_t count, loff_t *ppos)
1663{
1664 unsigned i = *ppos;
1665 char __user *tmp = buf;
1666
1667 if (keypad_buflen == 0) {
1668 if (file->f_flags & O_NONBLOCK)
1669 return -EAGAIN;
1670
1671 if (wait_event_interruptible(keypad_read_wait,
1672 keypad_buflen != 0))
1673 return -EINTR;
1674 }
1675
1676 for (; count-- > 0 && (keypad_buflen > 0);
1677 ++i, ++tmp, --keypad_buflen) {
1678 put_user(keypad_buffer[keypad_start], tmp);
1679 keypad_start = (keypad_start + 1) % KEYPAD_BUFFER;
1680 }
1681 *ppos = i;
1682
1683 return tmp - buf;
1684}
1685
1686static int keypad_open(struct inode *inode, struct file *file)
1687{
1688 if (!atomic_dec_and_test(&keypad_available))
1689 return -EBUSY;
1690
1691 if (file->f_mode & FMODE_WRITE)
1692 return -EPERM;
1693
1694 keypad_buflen = 0;
1695 return 0;
1696}
1697
1698static int keypad_release(struct inode *inode, struct file *file)
1699{
1700 atomic_inc(&keypad_available);
1701 return 0;
1702}
1703
1704static const struct file_operations keypad_fops = {
1705 .read = keypad_read,
1706 .open = keypad_open,
1707 .release = keypad_release,
1708 .llseek = default_llseek,
1709};
1710
1711static struct miscdevice keypad_dev = {
1712 .minor = KEYPAD_MINOR,
1713 .name = "keypad",
1714 .fops = &keypad_fops,
1715};
1716
1717static void keypad_send_key(const char *string, int max_len)
1718{
1719
1720 if (!atomic_read(&keypad_available)) {
1721 while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
1722 keypad_buffer[(keypad_start + keypad_buflen++) %
1723 KEYPAD_BUFFER] = *string++;
1724 }
1725 wake_up_interruptible(&keypad_read_wait);
1726 }
1727}
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739static void phys_scan_contacts(void)
1740{
1741 int bit, bitval;
1742 char oldval;
1743 char bitmask;
1744 char gndmask;
1745
1746 phys_prev = phys_curr;
1747 phys_read_prev = phys_read;
1748 phys_read = 0;
1749
1750
1751 oldval = r_dtr(pprt) | scan_mask_o;
1752
1753 w_dtr(pprt, oldval & ~scan_mask_o);
1754
1755
1756 bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
1757
1758 w_dtr(pprt, oldval);
1759
1760
1761
1762
1763
1764
1765 gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
1766
1767
1768 phys_read |= (pmask_t) gndmask << 40;
1769
1770 if (bitmask != gndmask) {
1771
1772
1773
1774
1775 for (bit = 0; bit < 8; bit++) {
1776 bitval = 1 << bit;
1777
1778 if (!(scan_mask_o & bitval))
1779 continue;
1780
1781 w_dtr(pprt, oldval & ~bitval);
1782 bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask;
1783 phys_read |= (pmask_t) bitmask << (5 * bit);
1784 }
1785 w_dtr(pprt, oldval);
1786 }
1787
1788
1789 phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) |
1790 (phys_read & ~(phys_read ^ phys_read_prev));
1791}
1792
1793static inline int input_state_high(struct logical_input *input)
1794{
1795#if 0
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813 if (((phys_prev & input->mask) == input->value) &&
1814 ((phys_curr & input->mask) > input->value)) {
1815 input->state = INPUT_ST_LOW;
1816 return 1;
1817 }
1818#endif
1819
1820 if ((phys_curr & input->mask) == input->value) {
1821 if ((input->type == INPUT_TYPE_STD) &&
1822 (input->high_timer == 0)) {
1823 input->high_timer++;
1824 if (input->u.std.press_fct != NULL)
1825 input->u.std.press_fct(input->u.std.press_data);
1826 } else if (input->type == INPUT_TYPE_KBD) {
1827
1828 keypressed = 1;
1829
1830 if (input->high_timer == 0) {
1831 char *press_str = input->u.kbd.press_str;
1832
1833 if (press_str[0]) {
1834 int s = sizeof(input->u.kbd.press_str);
1835
1836 keypad_send_key(press_str, s);
1837 }
1838 }
1839
1840 if (input->u.kbd.repeat_str[0]) {
1841 char *repeat_str = input->u.kbd.repeat_str;
1842
1843 if (input->high_timer >= KEYPAD_REP_START) {
1844 int s = sizeof(input->u.kbd.repeat_str);
1845
1846 input->high_timer -= KEYPAD_REP_DELAY;
1847 keypad_send_key(repeat_str, s);
1848 }
1849
1850 inputs_stable = 0;
1851 }
1852
1853 if (input->high_timer < 255)
1854 input->high_timer++;
1855 }
1856 return 1;
1857 }
1858
1859
1860 input->state = INPUT_ST_FALLING;
1861 input->fall_timer = 0;
1862
1863 return 0;
1864}
1865
1866static inline void input_state_falling(struct logical_input *input)
1867{
1868#if 0
1869
1870 if (((phys_prev & input->mask) == input->value) &&
1871 ((phys_curr & input->mask) > input->value)) {
1872 input->state = INPUT_ST_LOW;
1873 return;
1874 }
1875#endif
1876
1877 if ((phys_curr & input->mask) == input->value) {
1878 if (input->type == INPUT_TYPE_KBD) {
1879
1880 keypressed = 1;
1881
1882 if (input->u.kbd.repeat_str[0]) {
1883 char *repeat_str = input->u.kbd.repeat_str;
1884
1885 if (input->high_timer >= KEYPAD_REP_START) {
1886 int s = sizeof(input->u.kbd.repeat_str);
1887
1888 input->high_timer -= KEYPAD_REP_DELAY;
1889 keypad_send_key(repeat_str, s);
1890 }
1891
1892 inputs_stable = 0;
1893 }
1894
1895 if (input->high_timer < 255)
1896 input->high_timer++;
1897 }
1898 input->state = INPUT_ST_HIGH;
1899 } else if (input->fall_timer >= input->fall_time) {
1900
1901 if (input->type == INPUT_TYPE_STD) {
1902 void (*release_fct)(int) = input->u.std.release_fct;
1903
1904 if (release_fct != NULL)
1905 release_fct(input->u.std.release_data);
1906 } else if (input->type == INPUT_TYPE_KBD) {
1907 char *release_str = input->u.kbd.release_str;
1908
1909 if (release_str[0]) {
1910 int s = sizeof(input->u.kbd.release_str);
1911
1912 keypad_send_key(release_str, s);
1913 }
1914 }
1915
1916 input->state = INPUT_ST_LOW;
1917 } else {
1918 input->fall_timer++;
1919 inputs_stable = 0;
1920 }
1921}
1922
1923static void panel_process_inputs(void)
1924{
1925 struct list_head *item;
1926 struct logical_input *input;
1927
1928 keypressed = 0;
1929 inputs_stable = 1;
1930 list_for_each(item, &logical_inputs) {
1931 input = list_entry(item, struct logical_input, list);
1932
1933 switch (input->state) {
1934 case INPUT_ST_LOW:
1935 if ((phys_curr & input->mask) != input->value)
1936 break;
1937
1938
1939
1940
1941
1942
1943
1944 if ((phys_prev & input->mask) == input->value)
1945 break;
1946 input->rise_timer = 0;
1947 input->state = INPUT_ST_RISING;
1948
1949 case INPUT_ST_RISING:
1950 if ((phys_curr & input->mask) != input->value) {
1951 input->state = INPUT_ST_LOW;
1952 break;
1953 }
1954 if (input->rise_timer < input->rise_time) {
1955 inputs_stable = 0;
1956 input->rise_timer++;
1957 break;
1958 }
1959 input->high_timer = 0;
1960 input->state = INPUT_ST_HIGH;
1961
1962 case INPUT_ST_HIGH:
1963 if (input_state_high(input))
1964 break;
1965
1966 case INPUT_ST_FALLING:
1967 input_state_falling(input);
1968 }
1969 }
1970}
1971
1972static void panel_scan_timer(void)
1973{
1974 if (keypad.enabled && keypad_initialized) {
1975 if (spin_trylock_irq(&pprt_lock)) {
1976 phys_scan_contacts();
1977
1978
1979 spin_unlock_irq(&pprt_lock);
1980 }
1981
1982 if (!inputs_stable || phys_curr != phys_prev)
1983 panel_process_inputs();
1984 }
1985
1986 if (lcd.enabled && lcd.initialized) {
1987 if (keypressed) {
1988 if (lcd.light_tempo == 0
1989 && ((lcd.flags & LCD_FLAG_L) == 0))
1990 lcd_backlight(1);
1991 lcd.light_tempo = FLASH_LIGHT_TEMPO;
1992 } else if (lcd.light_tempo > 0) {
1993 lcd.light_tempo--;
1994 if (lcd.light_tempo == 0
1995 && ((lcd.flags & LCD_FLAG_L) == 0))
1996 lcd_backlight(0);
1997 }
1998 }
1999
2000 mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
2001}
2002
2003static void init_scan_timer(void)
2004{
2005 if (scan_timer.function != NULL)
2006 return;
2007
2008 setup_timer(&scan_timer, (void *)&panel_scan_timer, 0);
2009 scan_timer.expires = jiffies + INPUT_POLL_TIME;
2010 add_timer(&scan_timer);
2011}
2012
2013
2014
2015
2016
2017
2018static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value,
2019 char *imask, char *omask)
2020{
2021 static char sigtab[10] = "EeSsPpAaBb";
2022 char im, om;
2023 pmask_t m, v;
2024
2025 om = 0ULL;
2026 im = 0ULL;
2027 m = 0ULL;
2028 v = 0ULL;
2029 while (*name) {
2030 int in, out, bit, neg;
2031
2032 for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name);
2033 in++)
2034 ;
2035
2036 if (in >= sizeof(sigtab))
2037 return 0;
2038 neg = (in & 1);
2039 in >>= 1;
2040 im |= (1 << in);
2041
2042 name++;
2043 if (isdigit(*name)) {
2044 out = *name - '0';
2045 om |= (1 << out);
2046 } else if (*name == '-') {
2047 out = 8;
2048 } else {
2049 return 0;
2050 }
2051
2052 bit = (out * 5) + in;
2053
2054 m |= 1ULL << bit;
2055 if (!neg)
2056 v |= 1ULL << bit;
2057 name++;
2058 }
2059 *mask = m;
2060 *value = v;
2061 if (imask)
2062 *imask |= im;
2063 if (omask)
2064 *omask |= om;
2065 return 1;
2066}
2067
2068
2069
2070
2071
2072static struct logical_input *panel_bind_key(const char *name, const char *press,
2073 const char *repeat,
2074 const char *release)
2075{
2076 struct logical_input *key;
2077
2078 key = kzalloc(sizeof(*key), GFP_KERNEL);
2079 if (!key)
2080 return NULL;
2081
2082 if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i,
2083 &scan_mask_o)) {
2084 kfree(key);
2085 return NULL;
2086 }
2087
2088 key->type = INPUT_TYPE_KBD;
2089 key->state = INPUT_ST_LOW;
2090 key->rise_time = 1;
2091 key->fall_time = 1;
2092
2093 strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str));
2094 strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str));
2095 strncpy(key->u.kbd.release_str, release,
2096 sizeof(key->u.kbd.release_str));
2097 list_add(&key->list, &logical_inputs);
2098 return key;
2099}
2100
2101#if 0
2102
2103
2104
2105
2106
2107
2108static struct logical_input *panel_bind_callback(char *name,
2109 void (*press_fct)(int),
2110 int press_data,
2111 void (*release_fct)(int),
2112 int release_data)
2113{
2114 struct logical_input *callback;
2115
2116 callback = kmalloc(sizeof(*callback), GFP_KERNEL);
2117 if (!callback)
2118 return NULL;
2119
2120 memset(callback, 0, sizeof(struct logical_input));
2121 if (!input_name2mask(name, &callback->mask, &callback->value,
2122 &scan_mask_i, &scan_mask_o))
2123 return NULL;
2124
2125 callback->type = INPUT_TYPE_STD;
2126 callback->state = INPUT_ST_LOW;
2127 callback->rise_time = 1;
2128 callback->fall_time = 1;
2129 callback->u.std.press_fct = press_fct;
2130 callback->u.std.press_data = press_data;
2131 callback->u.std.release_fct = release_fct;
2132 callback->u.std.release_data = release_data;
2133 list_add(&callback->list, &logical_inputs);
2134 return callback;
2135}
2136#endif
2137
2138static void keypad_init(void)
2139{
2140 int keynum;
2141
2142 init_waitqueue_head(&keypad_read_wait);
2143 keypad_buflen = 0;
2144
2145
2146
2147 for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) {
2148 panel_bind_key(keypad_profile[keynum][0],
2149 keypad_profile[keynum][1],
2150 keypad_profile[keynum][2],
2151 keypad_profile[keynum][3]);
2152 }
2153
2154 init_scan_timer();
2155 keypad_initialized = 1;
2156}
2157
2158
2159
2160
2161
2162static int panel_notify_sys(struct notifier_block *this, unsigned long code,
2163 void *unused)
2164{
2165 if (lcd.enabled && lcd.initialized) {
2166 switch (code) {
2167 case SYS_DOWN:
2168 panel_lcd_print
2169 ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
2170 break;
2171 case SYS_HALT:
2172 panel_lcd_print
2173 ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
2174 break;
2175 case SYS_POWER_OFF:
2176 panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
2177 break;
2178 default:
2179 break;
2180 }
2181 }
2182 return NOTIFY_DONE;
2183}
2184
2185static struct notifier_block panel_notifier = {
2186 panel_notify_sys,
2187 NULL,
2188 0
2189};
2190
2191static void panel_attach(struct parport *port)
2192{
2193 if (port->number != parport)
2194 return;
2195
2196 if (pprt) {
2197 pr_err("%s: port->number=%d parport=%d, already registered!\n",
2198 __func__, port->number, parport);
2199 return;
2200 }
2201
2202 pprt = parport_register_device(port, "panel", NULL, NULL,
2203 NULL,
2204
2205 0, (void *)&pprt);
2206 if (pprt == NULL) {
2207 pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n",
2208 __func__, port->number, parport);
2209 return;
2210 }
2211
2212 if (parport_claim(pprt)) {
2213 pr_err("could not claim access to parport%d. Aborting.\n",
2214 parport);
2215 goto err_unreg_device;
2216 }
2217
2218
2219
2220
2221 if (lcd.enabled) {
2222 lcd_init();
2223 if (misc_register(&lcd_dev))
2224 goto err_unreg_device;
2225 }
2226
2227 if (keypad.enabled) {
2228 keypad_init();
2229 if (misc_register(&keypad_dev))
2230 goto err_lcd_unreg;
2231 }
2232 register_reboot_notifier(&panel_notifier);
2233 return;
2234
2235err_lcd_unreg:
2236 if (lcd.enabled)
2237 misc_deregister(&lcd_dev);
2238err_unreg_device:
2239 parport_unregister_device(pprt);
2240 pprt = NULL;
2241}
2242
2243static void panel_detach(struct parport *port)
2244{
2245 if (port->number != parport)
2246 return;
2247
2248 if (!pprt) {
2249 pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n",
2250 __func__, port->number, parport);
2251 return;
2252 }
2253
2254 unregister_reboot_notifier(&panel_notifier);
2255
2256 if (keypad.enabled && keypad_initialized) {
2257 misc_deregister(&keypad_dev);
2258 keypad_initialized = 0;
2259 }
2260
2261 if (lcd.enabled && lcd.initialized) {
2262 misc_deregister(&lcd_dev);
2263 lcd.initialized = false;
2264 }
2265
2266 parport_release(pprt);
2267 parport_unregister_device(pprt);
2268 pprt = NULL;
2269}
2270
2271static struct parport_driver panel_driver = {
2272 .name = "panel",
2273 .attach = panel_attach,
2274 .detach = panel_detach,
2275};
2276
2277
2278static int __init panel_init_module(void)
2279{
2280 int selected_keypad_type = NOT_SET, err;
2281
2282
2283 switch (profile) {
2284 case PANEL_PROFILE_CUSTOM:
2285
2286 selected_keypad_type = DEFAULT_KEYPAD_TYPE;
2287 selected_lcd_type = DEFAULT_LCD_TYPE;
2288 break;
2289 case PANEL_PROFILE_OLD:
2290
2291 selected_keypad_type = KEYPAD_TYPE_OLD;
2292 selected_lcd_type = LCD_TYPE_OLD;
2293
2294
2295 if (lcd_width == NOT_SET)
2296 lcd_width = 16;
2297 if (lcd_hwidth == NOT_SET)
2298 lcd_hwidth = 16;
2299 break;
2300 case PANEL_PROFILE_NEW:
2301
2302 selected_keypad_type = KEYPAD_TYPE_NEW;
2303 selected_lcd_type = LCD_TYPE_KS0074;
2304 break;
2305 case PANEL_PROFILE_HANTRONIX:
2306
2307 selected_keypad_type = KEYPAD_TYPE_NONE;
2308 selected_lcd_type = LCD_TYPE_HANTRONIX;
2309 break;
2310 case PANEL_PROFILE_NEXCOM:
2311
2312 selected_keypad_type = KEYPAD_TYPE_NEXCOM;
2313 selected_lcd_type = LCD_TYPE_NEXCOM;
2314 break;
2315 case PANEL_PROFILE_LARGE:
2316
2317 selected_keypad_type = KEYPAD_TYPE_OLD;
2318 selected_lcd_type = LCD_TYPE_OLD;
2319 break;
2320 }
2321
2322
2323
2324
2325
2326 if (keypad_enabled != NOT_SET)
2327 selected_keypad_type = keypad_enabled;
2328 if (keypad_type != NOT_SET)
2329 selected_keypad_type = keypad_type;
2330
2331 keypad.enabled = (selected_keypad_type > 0);
2332
2333 if (lcd_enabled != NOT_SET)
2334 selected_lcd_type = lcd_enabled;
2335 if (lcd_type != NOT_SET)
2336 selected_lcd_type = lcd_type;
2337
2338 lcd.enabled = (selected_lcd_type > 0);
2339
2340 if (lcd.enabled) {
2341
2342
2343
2344
2345 lcd.height = lcd_height;
2346 lcd.width = lcd_width;
2347 lcd.bwidth = lcd_bwidth;
2348 lcd.hwidth = lcd_hwidth;
2349 lcd.charset = lcd_charset;
2350 lcd.proto = lcd_proto;
2351 lcd.pins.e = lcd_e_pin;
2352 lcd.pins.rs = lcd_rs_pin;
2353 lcd.pins.rw = lcd_rw_pin;
2354 lcd.pins.cl = lcd_cl_pin;
2355 lcd.pins.da = lcd_da_pin;
2356 lcd.pins.bl = lcd_bl_pin;
2357
2358
2359 lcd.esc_seq.len = -1;
2360 }
2361
2362 switch (selected_keypad_type) {
2363 case KEYPAD_TYPE_OLD:
2364 keypad_profile = old_keypad_profile;
2365 break;
2366 case KEYPAD_TYPE_NEW:
2367 keypad_profile = new_keypad_profile;
2368 break;
2369 case KEYPAD_TYPE_NEXCOM:
2370 keypad_profile = nexcom_keypad_profile;
2371 break;
2372 default:
2373 keypad_profile = NULL;
2374 break;
2375 }
2376
2377 if (!lcd.enabled && !keypad.enabled) {
2378
2379 pr_err("driver version " PANEL_VERSION " disabled.\n");
2380 return -ENODEV;
2381 }
2382
2383 err = parport_register_driver(&panel_driver);
2384 if (err) {
2385 pr_err("could not register with parport. Aborting.\n");
2386 return err;
2387 }
2388
2389 if (pprt)
2390 pr_info("driver version " PANEL_VERSION
2391 " registered on parport%d (io=0x%lx).\n", parport,
2392 pprt->port->base);
2393 else
2394 pr_info("driver version " PANEL_VERSION
2395 " not yet registered\n");
2396 return 0;
2397}
2398
2399static void __exit panel_cleanup_module(void)
2400{
2401
2402 if (scan_timer.function != NULL)
2403 del_timer_sync(&scan_timer);
2404
2405 if (pprt != NULL) {
2406 if (keypad.enabled) {
2407 misc_deregister(&keypad_dev);
2408 keypad_initialized = 0;
2409 }
2410
2411 if (lcd.enabled) {
2412 panel_lcd_print("\x0cLCD driver " PANEL_VERSION
2413 "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
2414 misc_deregister(&lcd_dev);
2415 lcd.initialized = false;
2416 }
2417
2418
2419 parport_release(pprt);
2420 parport_unregister_device(pprt);
2421 pprt = NULL;
2422 }
2423 parport_unregister_driver(&panel_driver);
2424}
2425
2426module_init(panel_init_module);
2427module_exit(panel_cleanup_module);
2428MODULE_AUTHOR("Willy Tarreau");
2429MODULE_LICENSE("GPL");
2430
2431
2432
2433
2434
2435
2436
2437