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