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