diff options
Diffstat (limited to 'drivers/staging/panel/panel.c')
-rw-r--r-- | drivers/staging/panel/panel.c | 807 |
1 files changed, 425 insertions, 382 deletions
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 6d1a32097d3c..98325b7b4462 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -133,6 +133,8 @@ #define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ #define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ +#define NOT_SET -1 + /* macros to simplify use of the parallel port */ #define r_ctr(x) (parport_read_control((x)->port)) #define r_dtr(x) (parport_read_data((x)->port)) @@ -210,6 +212,10 @@ static pmask_t phys_prev; static char inputs_stable; /* these variables are specific to the keypad */ +static struct { + bool enabled; +} keypad; + static char keypad_buffer[KEYPAD_BUFFER]; static int keypad_buflen; static int keypad_start; @@ -217,17 +223,50 @@ static char keypressed; static wait_queue_head_t keypad_read_wait; /* lcd-specific variables */ - -/* contains the LCD config state */ -static unsigned long int lcd_flags; -/* contains the LCD X offset */ -static unsigned long int lcd_addr_x; -/* contains the LCD Y offset */ -static unsigned long int lcd_addr_y; -/* current escape sequence, 0 terminated */ -static char lcd_escape[LCD_ESCAPE_LEN + 1]; -/* not in escape state. >=0 = escape cmd len */ -static int lcd_escape_len = -1; +static struct { + bool enabled; + bool initialized; + bool must_clear; + + /* TODO: use bool here? */ + char left_shift; + + int height; + int width; + int bwidth; + int hwidth; + int charset; + int proto; + int light_tempo; + + /* TODO: use union here? */ + struct { + int e; + int rs; + int rw; + int cl; + int da; + int bl; + } pins; + + /* contains the LCD config state */ + unsigned long int flags; + + /* Contains the LCD X and Y offset */ + struct { + unsigned long int x; + unsigned long int y; + } addr; + + /* Current escape sequence and it's length or -1 if outside */ + struct { + char buf[LCD_ESCAPE_LEN + 1]; + int len; + } esc_seq; +} lcd; + +/* Needed only for init */ +static int selected_lcd_type = NOT_SET; /* * Bit masks to convert LCD signals to parallel port outputs. @@ -302,14 +341,15 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; /* * Construct custom config from the kernel's configuration */ -#define DEFAULT_PROFILE PANEL_PROFILE_LARGE #define DEFAULT_PARPORT 0 -#define DEFAULT_LCD LCD_TYPE_OLD -#define DEFAULT_KEYPAD KEYPAD_TYPE_OLD +#define DEFAULT_PROFILE PANEL_PROFILE_LARGE +#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD +#define DEFAULT_LCD_TYPE LCD_TYPE_OLD +#define DEFAULT_LCD_HEIGHT 2 #define DEFAULT_LCD_WIDTH 40 #define DEFAULT_LCD_BWIDTH 40 #define DEFAULT_LCD_HWIDTH 64 -#define DEFAULT_LCD_HEIGHT 2 +#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL #define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL #define DEFAULT_LCD_PIN_E PIN_AUTOLF @@ -318,27 +358,31 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; #define DEFAULT_LCD_PIN_SCL PIN_STROBE #define DEFAULT_LCD_PIN_SDA PIN_D0 #define DEFAULT_LCD_PIN_BL PIN_NOT_SET -#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL - -#ifdef CONFIG_PANEL_PROFILE -#undef DEFAULT_PROFILE -#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE -#endif #ifdef CONFIG_PANEL_PARPORT #undef DEFAULT_PARPORT #define DEFAULT_PARPORT CONFIG_PANEL_PARPORT #endif +#ifdef CONFIG_PANEL_PROFILE +#undef DEFAULT_PROFILE +#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE +#endif + #if DEFAULT_PROFILE == 0 /* custom */ #ifdef CONFIG_PANEL_KEYPAD -#undef DEFAULT_KEYPAD -#define DEFAULT_KEYPAD CONFIG_PANEL_KEYPAD +#undef DEFAULT_KEYPAD_TYPE +#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD #endif #ifdef CONFIG_PANEL_LCD -#undef DEFAULT_LCD -#define DEFAULT_LCD CONFIG_PANEL_LCD +#undef DEFAULT_LCD_TYPE +#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD +#endif + +#ifdef CONFIG_PANEL_LCD_HEIGHT +#undef DEFAULT_LCD_HEIGHT +#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT #endif #ifdef CONFIG_PANEL_LCD_WIDTH @@ -356,9 +400,9 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; #define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH #endif -#ifdef CONFIG_PANEL_LCD_HEIGHT -#undef DEFAULT_LCD_HEIGHT -#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT +#ifdef CONFIG_PANEL_LCD_CHARSET +#undef DEFAULT_LCD_CHARSET +#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET #endif #ifdef CONFIG_PANEL_LCD_PROTO @@ -396,25 +440,18 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; #define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL #endif -#ifdef CONFIG_PANEL_LCD_CHARSET -#undef DEFAULT_LCD_CHARSET -#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET -#endif - #endif /* DEFAULT_PROFILE == 0 */ /* global variables */ -static int keypad_open_cnt; /* #times opened */ -static int lcd_open_cnt; /* #times opened */ + +/* Device single-open policy control */ +static atomic_t lcd_available = ATOMIC_INIT(1); +static atomic_t keypad_available = ATOMIC_INIT(1); + static struct pardevice *pprt; -static int lcd_initialized; static int keypad_initialized; -static int light_tempo; - -static char lcd_must_clear; -static char lcd_left_shift; static char init_in_progress; static void (*lcd_write_cmd)(int); @@ -426,59 +463,51 @@ static struct timer_list scan_timer; MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver"); -static int parport = -1; +static int parport = DEFAULT_PARPORT; module_param(parport, int, 0000); MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)"); -static int lcd_height = -1; +static int profile = DEFAULT_PROFILE; +module_param(profile, int, 0000); +MODULE_PARM_DESC(profile, + "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " + "4=16x2 nexcom; default=40x2, old kp"); + +static int keypad_type = NOT_SET; +module_param(keypad_type, int, 0000); +MODULE_PARM_DESC(keypad_type, + "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); + +static int lcd_type = NOT_SET; +module_param(lcd_type, int, 0000); +MODULE_PARM_DESC(lcd_type, + "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in"); + +static int lcd_height = NOT_SET; module_param(lcd_height, int, 0000); MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD"); -static int lcd_width = -1; +static int lcd_width = NOT_SET; module_param(lcd_width, int, 0000); MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD"); -static int lcd_bwidth = -1; /* internal buffer width (usually 40) */ +static int lcd_bwidth = NOT_SET; /* internal buffer width (usually 40) */ module_param(lcd_bwidth, int, 0000); MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)"); -static int lcd_hwidth = -1; /* hardware buffer width (usually 64) */ +static int lcd_hwidth = NOT_SET; /* hardware buffer width (usually 64) */ module_param(lcd_hwidth, int, 0000); MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)"); -static int lcd_enabled = -1; -module_param(lcd_enabled, int, 0000); -MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); - -static int keypad_enabled = -1; -module_param(keypad_enabled, int, 0000); -MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); - -static int lcd_type = -1; -module_param(lcd_type, int, 0000); -MODULE_PARM_DESC(lcd_type, - "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in"); +static int lcd_charset = NOT_SET; +module_param(lcd_charset, int, 0000); +MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); -static int lcd_proto = -1; +static int lcd_proto = NOT_SET; module_param(lcd_proto, int, 0000); MODULE_PARM_DESC(lcd_proto, "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface"); -static int lcd_charset = -1; -module_param(lcd_charset, int, 0000); -MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); - -static int keypad_type = -1; -module_param(keypad_type, int, 0000); -MODULE_PARM_DESC(keypad_type, - "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); - -static int profile = DEFAULT_PROFILE; -module_param(profile, int, 0000); -MODULE_PARM_DESC(profile, - "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " - "4=16x2 nexcom; default=40x2, old kp"); - /* * These are the parallel port pins the LCD control signals are connected to. * Set this to 0 if the signal is not used. Set it to its opposite value @@ -503,20 +532,31 @@ module_param(lcd_rw_pin, int, 0000); MODULE_PARM_DESC(lcd_rw_pin, "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)"); -static int lcd_bl_pin = PIN_NOT_SET; -module_param(lcd_bl_pin, int, 0000); -MODULE_PARM_DESC(lcd_bl_pin, - "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); +static int lcd_cl_pin = PIN_NOT_SET; +module_param(lcd_cl_pin, int, 0000); +MODULE_PARM_DESC(lcd_cl_pin, + "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); static int lcd_da_pin = PIN_NOT_SET; module_param(lcd_da_pin, int, 0000); MODULE_PARM_DESC(lcd_da_pin, "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)"); -static int lcd_cl_pin = PIN_NOT_SET; -module_param(lcd_cl_pin, int, 0000); -MODULE_PARM_DESC(lcd_cl_pin, - "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); +static int lcd_bl_pin = PIN_NOT_SET; +module_param(lcd_bl_pin, int, 0000); +MODULE_PARM_DESC(lcd_bl_pin, + "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); + +/* Deprecated module parameters - consider not using them anymore */ + +static int lcd_enabled = NOT_SET; +module_param(lcd_enabled, int, 0000); +MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); + +static int keypad_enabled = NOT_SET; +module_param(keypad_enabled, int, 0000); +MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); + static const unsigned char *lcd_char_conv; @@ -748,7 +788,7 @@ static void lcd_send_serial(int byte) /* turn the backlight on or off */ static void lcd_backlight(int on) { - if (lcd_bl_pin == PIN_NONE) + if (lcd.pins.bl == PIN_NONE) return; /* The backlight is activated by setting the AUTOFEED line to +5V */ @@ -847,23 +887,23 @@ static void lcd_write_data_tilcd(int data) static void lcd_gotoxy(void) { lcd_write_cmd(0x80 /* set DDRAM address */ - | (lcd_addr_y ? lcd_hwidth : 0) + | (lcd.addr.y ? lcd.hwidth : 0) /* we force the cursor to stay at the end of the line if it wants to go farther */ - | ((lcd_addr_x < lcd_bwidth) ? lcd_addr_x & - (lcd_hwidth - 1) : lcd_bwidth - 1)); + | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x & + (lcd.hwidth - 1) : lcd.bwidth - 1)); } static void lcd_print(char c) { - if (lcd_addr_x < lcd_bwidth) { + if (lcd.addr.x < lcd.bwidth) { if (lcd_char_conv != NULL) c = lcd_char_conv[(unsigned char)c]; lcd_write_data(c); - lcd_addr_x++; + lcd.addr.x++; } /* prevents the cursor from wrapping onto the next line */ - if (lcd_addr_x == lcd_bwidth) + if (lcd.addr.x == lcd.bwidth) lcd_gotoxy(); } @@ -872,12 +912,12 @@ static void lcd_clear_fast_s(void) { int pos; - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(' ' & 0x0F); lcd_send_serial((' ' >> 4) & 0x0F); @@ -885,8 +925,8 @@ static void lcd_clear_fast_s(void) } spin_unlock_irq(&pprt_lock); - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); } @@ -895,12 +935,12 @@ static void lcd_clear_fast_p8(void) { int pos; - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { /* present the data to the data port */ w_dtr(pprt, ' '); @@ -923,8 +963,8 @@ static void lcd_clear_fast_p8(void) } spin_unlock_irq(&pprt_lock); - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); } @@ -933,12 +973,12 @@ static void lcd_clear_fast_tilcd(void) { int pos; - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) { + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { /* present the data to the data port */ w_dtr(pprt, ' '); udelay(60); @@ -946,8 +986,8 @@ static void lcd_clear_fast_tilcd(void) spin_unlock_irq(&pprt_lock); - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); } @@ -955,15 +995,15 @@ static void lcd_clear_fast_tilcd(void) static void lcd_clear_display(void) { lcd_write_cmd(0x01); /* clear display */ - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; /* we must wait a few milliseconds (15) */ long_sleep(15); } static void lcd_init_display(void) { - lcd_flags = ((lcd_height > 1) ? LCD_FLAG_N : 0) + lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; long_sleep(20); /* wait 20 ms after power-up for the paranoid */ @@ -976,8 +1016,8 @@ static void lcd_init_display(void) long_sleep(10); lcd_write_cmd(0x30 /* set font height and lines number */ - | ((lcd_flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd_flags & LCD_FLAG_N) ? 8 : 0) + | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) + | ((lcd.flags & LCD_FLAG_N) ? 8 : 0) ); long_sleep(10); @@ -985,12 +1025,12 @@ static void lcd_init_display(void) long_sleep(10); lcd_write_cmd(0x08 /* set display mode */ - | ((lcd_flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd_flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd_flags & LCD_FLAG_B) ? 1 : 0) + | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) + | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) + | ((lcd.flags & LCD_FLAG_B) ? 1 : 0) ); - lcd_backlight((lcd_flags & LCD_FLAG_L) ? 1 : 0); + lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); long_sleep(10); @@ -1013,100 +1053,101 @@ static inline int handle_lcd_special_code(void) int processed = 0; - char *esc = lcd_escape + 2; - int oldflags = lcd_flags; + char *esc = lcd.esc_seq.buf + 2; + int oldflags = lcd.flags; /* check for display mode flags */ switch (*esc) { case 'D': /* Display ON */ - lcd_flags |= LCD_FLAG_D; + lcd.flags |= LCD_FLAG_D; processed = 1; break; case 'd': /* Display OFF */ - lcd_flags &= ~LCD_FLAG_D; + lcd.flags &= ~LCD_FLAG_D; processed = 1; break; case 'C': /* Cursor ON */ - lcd_flags |= LCD_FLAG_C; + lcd.flags |= LCD_FLAG_C; processed = 1; break; case 'c': /* Cursor OFF */ - lcd_flags &= ~LCD_FLAG_C; + lcd.flags &= ~LCD_FLAG_C; processed = 1; break; case 'B': /* Blink ON */ - lcd_flags |= LCD_FLAG_B; + lcd.flags |= LCD_FLAG_B; processed = 1; break; case 'b': /* Blink OFF */ - lcd_flags &= ~LCD_FLAG_B; + lcd.flags &= ~LCD_FLAG_B; processed = 1; break; case '+': /* Back light ON */ - lcd_flags |= LCD_FLAG_L; + lcd.flags |= LCD_FLAG_L; processed = 1; break; case '-': /* Back light OFF */ - lcd_flags &= ~LCD_FLAG_L; + lcd.flags &= ~LCD_FLAG_L; processed = 1; break; case '*': /* flash back light using the keypad timer */ if (scan_timer.function != NULL) { - if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0)) + if (lcd.light_tempo == 0 + && ((lcd.flags & LCD_FLAG_L) == 0)) lcd_backlight(1); - light_tempo = FLASH_LIGHT_TEMPO; + lcd.light_tempo = FLASH_LIGHT_TEMPO; } processed = 1; break; case 'f': /* Small Font */ - lcd_flags &= ~LCD_FLAG_F; + lcd.flags &= ~LCD_FLAG_F; processed = 1; break; case 'F': /* Large Font */ - lcd_flags |= LCD_FLAG_F; + lcd.flags |= LCD_FLAG_F; processed = 1; break; case 'n': /* One Line */ - lcd_flags &= ~LCD_FLAG_N; + lcd.flags &= ~LCD_FLAG_N; processed = 1; break; case 'N': /* Two Lines */ - lcd_flags |= LCD_FLAG_N; + lcd.flags |= LCD_FLAG_N; break; case 'l': /* Shift Cursor Left */ - if (lcd_addr_x > 0) { + if (lcd.addr.x > 0) { /* back one char if not at end of line */ - if (lcd_addr_x < lcd_bwidth) + if (lcd.addr.x < lcd.bwidth) lcd_write_cmd(0x10); - lcd_addr_x--; + lcd.addr.x--; } processed = 1; break; case 'r': /* shift cursor right */ - if (lcd_addr_x < lcd_width) { + if (lcd.addr.x < lcd.width) { /* allow the cursor to pass the end of the line */ - if (lcd_addr_x < - (lcd_bwidth - 1)) + if (lcd.addr.x < + (lcd.bwidth - 1)) lcd_write_cmd(0x14); - lcd_addr_x++; + lcd.addr.x++; } processed = 1; break; case 'L': /* shift display left */ - lcd_left_shift++; + lcd.left_shift++; lcd_write_cmd(0x18); processed = 1; break; case 'R': /* shift display right */ - lcd_left_shift--; + lcd.left_shift--; lcd_write_cmd(0x1C); processed = 1; break; case 'k': { /* kill end of line */ int x; - for (x = lcd_addr_x; x < lcd_bwidth; x++) + for (x = lcd.addr.x; x < lcd.bwidth; x++) lcd_write_data(' '); /* restore cursor position */ @@ -1116,7 +1157,7 @@ static inline int handle_lcd_special_code(void) } case 'I': /* reinitialize display */ lcd_init_display(); - lcd_left_shift = 0; + lcd.left_shift = 0; processed = 1; break; case 'G': { @@ -1187,11 +1228,11 @@ static inline int handle_lcd_special_code(void) while (*esc) { if (*esc == 'x') { esc++; - if (kstrtoul(esc, 10, &lcd_addr_x) < 0) + if (kstrtoul(esc, 10, &lcd.addr.x) < 0) break; } else if (*esc == 'y') { esc++; - if (kstrtoul(esc, 10, &lcd_addr_y) < 0) + if (kstrtoul(esc, 10, &lcd.addr.y) < 0) break; } else { break; @@ -1204,25 +1245,25 @@ static inline int handle_lcd_special_code(void) } /* Check whether one flag was changed */ - if (oldflags != lcd_flags) { + if (oldflags != lcd.flags) { /* check whether one of B,C,D flags were changed */ - if ((oldflags ^ lcd_flags) & + if ((oldflags ^ lcd.flags) & (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) /* set display mode */ lcd_write_cmd(0x08 - | ((lcd_flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd_flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd_flags & LCD_FLAG_B) ? 1 : 0)); + | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) + | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) + | ((lcd.flags & LCD_FLAG_B) ? 1 : 0)); /* check whether one of F,N flags was changed */ - else if ((oldflags ^ lcd_flags) & (LCD_FLAG_F | LCD_FLAG_N)) + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) lcd_write_cmd(0x30 - | ((lcd_flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd_flags & LCD_FLAG_N) ? 8 : 0)); + | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) + | ((lcd.flags & LCD_FLAG_N) ? 8 : 0)); /* check whether L flag was changed */ - else if ((oldflags ^ lcd_flags) & (LCD_FLAG_L)) { - if (lcd_flags & (LCD_FLAG_L)) + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { + if (lcd.flags & (LCD_FLAG_L)) lcd_backlight(1); - else if (light_tempo == 0) + else if (lcd.light_tempo == 0) /* switch off the light only when the tempo lighting is gone */ lcd_backlight(0); @@ -1235,29 +1276,29 @@ static inline int handle_lcd_special_code(void) static void lcd_write_char(char c) { /* first, we'll test if we're in escape mode */ - if ((c != '\n') && lcd_escape_len >= 0) { + if ((c != '\n') && lcd.esc_seq.len >= 0) { /* yes, let's add this char to the buffer */ - lcd_escape[lcd_escape_len++] = c; - lcd_escape[lcd_escape_len] = 0; + lcd.esc_seq.buf[lcd.esc_seq.len++] = c; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; } else { /* aborts any previous escape sequence */ - lcd_escape_len = -1; + lcd.esc_seq.len = -1; switch (c) { case LCD_ESCAPE_CHAR: /* start of an escape sequence */ - lcd_escape_len = 0; - lcd_escape[lcd_escape_len] = 0; + lcd.esc_seq.len = 0; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; break; case '\b': /* go back one char and clear it */ - if (lcd_addr_x > 0) { + if (lcd.addr.x > 0) { /* check if we're not at the end of the line */ - if (lcd_addr_x < lcd_bwidth) + if (lcd.addr.x < lcd.bwidth) /* back one char */ lcd_write_cmd(0x10); - lcd_addr_x--; + lcd.addr.x--; } /* replace with a space */ lcd_write_data(' '); @@ -1271,15 +1312,15 @@ static void lcd_write_char(char c) case '\n': /* flush the remainder of the current line and go to the beginning of the next line */ - for (; lcd_addr_x < lcd_bwidth; lcd_addr_x++) + for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++) lcd_write_data(' '); - lcd_addr_x = 0; - lcd_addr_y = (lcd_addr_y + 1) % lcd_height; + lcd.addr.x = 0; + lcd.addr.y = (lcd.addr.y + 1) % lcd.height; lcd_gotoxy(); break; case '\r': /* go to the beginning of the same line */ - lcd_addr_x = 0; + lcd.addr.x = 0; lcd_gotoxy(); break; case '\t': @@ -1295,32 +1336,32 @@ static void lcd_write_char(char c) /* now we'll see if we're in an escape mode and if the current escape sequence can be understood. */ - if (lcd_escape_len >= 2) { + if (lcd.esc_seq.len >= 2) { int processed = 0; - if (!strcmp(lcd_escape, "[2J")) { + if (!strcmp(lcd.esc_seq.buf, "[2J")) { /* clear the display */ lcd_clear_fast(); processed = 1; - } else if (!strcmp(lcd_escape, "[H")) { + } else if (!strcmp(lcd.esc_seq.buf, "[H")) { /* cursor to home */ - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; lcd_gotoxy(); processed = 1; } /* codes starting with ^[[L */ - else if ((lcd_escape_len >= 3) && - (lcd_escape[0] == '[') && - (lcd_escape[1] == 'L')) { + else if ((lcd.esc_seq.len >= 3) && + (lcd.esc_seq.buf[0] == '[') && + (lcd.esc_seq.buf[1] == 'L')) { processed = handle_lcd_special_code(); } /* LCD special escape codes */ /* flush the escape sequence if it's been processed or if it is getting too long. */ - if (processed || (lcd_escape_len >= LCD_ESCAPE_LEN)) - lcd_escape_len = -1; + if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN)) + lcd.esc_seq.len = -1; } /* escape codes */ } @@ -1347,23 +1388,22 @@ static ssize_t lcd_write(struct file *file, static int lcd_open(struct inode *inode, struct file *file) { - if (lcd_open_cnt) + if (!atomic_dec_and_test(&lcd_available)) return -EBUSY; /* open only once at a time */ if (file->f_mode & FMODE_READ) /* device is write-only */ return -EPERM; - if (lcd_must_clear) { + if (lcd.must_clear) { lcd_clear_display(); - lcd_must_clear = 0; + lcd.must_clear = false; } - lcd_open_cnt++; return nonseekable_open(inode, file); } static int lcd_release(struct inode *inode, struct file *file) { - lcd_open_cnt--; + atomic_inc(&lcd_available); return 0; } @@ -1375,9 +1415,9 @@ static const struct file_operations lcd_fops = { }; static struct miscdevice lcd_dev = { - LCD_MINOR, - "lcd", - &lcd_fops + .minor = LCD_MINOR, + .name = "lcd", + .fops = &lcd_fops, }; /* public function usable from the kernel for any purpose */ @@ -1386,7 +1426,7 @@ static void panel_lcd_print(const char *s) const char *tmp = s; int count = strlen(s); - if (lcd_enabled && lcd_initialized) { + if (lcd.enabled && lcd.initialized) { for (; count-- > 0; tmp++) { if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) /* let's be a little nice with other processes @@ -1401,183 +1441,173 @@ static void panel_lcd_print(const char *s) /* initialize the LCD driver */ static void lcd_init(void) { - switch (lcd_type) { + switch (selected_lcd_type) { case LCD_TYPE_OLD: /* parallel mode, 8 bits */ - if (lcd_proto < 0) - lcd_proto = LCD_PROTO_PARALLEL; - if (lcd_charset < 0) - lcd_charset = LCD_CHARSET_NORMAL; - if (lcd_e_pin == PIN_NOT_SET) - lcd_e_pin = PIN_STROBE; - if (lcd_rs_pin == PIN_NOT_SET) - lcd_rs_pin = PIN_AUTOLF; - - if (lcd_width < 0) - lcd_width = 40; - if (lcd_bwidth < 0) - lcd_bwidth = 40; - if (lcd_hwidth < 0) - lcd_hwidth = 64; - if (lcd_height < 0) - lcd_height = 2; + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_AUTOLF; + + lcd.width = 40; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; break; case LCD_TYPE_KS0074: /* serial mode, ks0074 */ - if (lcd_proto < 0) - lcd_proto = LCD_PROTO_SERIAL; - if (lcd_charset < 0) - lcd_charset = LCD_CHARSET_KS0074; - if (lcd_bl_pin == PIN_NOT_SET) - lcd_bl_pin = PIN_AUTOLF; - if (lcd_cl_pin == PIN_NOT_SET) - lcd_cl_pin = PIN_STROBE; - if (lcd_da_pin == PIN_NOT_SET) - lcd_da_pin = PIN_D0; - - if (lcd_width < 0) - lcd_width = 16; - if (lcd_bwidth < 0) - lcd_bwidth = 40; - if (lcd_hwidth < 0) - lcd_hwidth = 16; - if (lcd_height < 0) - lcd_height = 2; + lcd.proto = LCD_PROTO_SERIAL; + lcd.charset = LCD_CHARSET_KS0074; + lcd.pins.bl = PIN_AUTOLF; + lcd.pins.cl = PIN_STROBE; + lcd.pins.da = PIN_D0; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 16; + lcd.height = 2; break; case LCD_TYPE_NEXCOM: /* parallel mode, 8 bits, generic */ - if (lcd_proto < 0) - lcd_proto = LCD_PROTO_PARALLEL; - if (lcd_charset < 0) - lcd_charset = LCD_CHARSET_NORMAL; - if (lcd_e_pin == PIN_NOT_SET) - lcd_e_pin = PIN_AUTOLF; - if (lcd_rs_pin == PIN_NOT_SET) - lcd_rs_pin = PIN_SELECP; - if (lcd_rw_pin == PIN_NOT_SET) - lcd_rw_pin = PIN_INITP; - - if (lcd_width < 0) - lcd_width = 16; - if (lcd_bwidth < 0) - lcd_bwidth = 40; - if (lcd_hwidth < 0) - lcd_hwidth = 64; - if (lcd_height < 0) - lcd_height = 2; + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_AUTOLF; + lcd.pins.rs = PIN_SELECP; + lcd.pins.rw = PIN_INITP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; break; case LCD_TYPE_CUSTOM: /* customer-defined */ - if (lcd_proto < 0) - lcd_proto = DEFAULT_LCD_PROTO; - if (lcd_charset < 0) - lcd_charset = DEFAULT_LCD_CHARSET; + lcd.proto = DEFAULT_LCD_PROTO; + lcd.charset = DEFAULT_LCD_CHARSET; /* default geometry will be set later */ break; case LCD_TYPE_HANTRONIX: /* parallel mode, 8 bits, hantronix-like */ default: - if (lcd_proto < 0) - lcd_proto = LCD_PROTO_PARALLEL; - if (lcd_charset < 0) - lcd_charset = LCD_CHARSET_NORMAL; - if (lcd_e_pin == PIN_NOT_SET) - lcd_e_pin = PIN_STROBE; - if (lcd_rs_pin == PIN_NOT_SET) - lcd_rs_pin = PIN_SELECP; - - if (lcd_width < 0) - lcd_width = 16; - if (lcd_bwidth < 0) - lcd_bwidth = 40; - if (lcd_hwidth < 0) - lcd_hwidth = 64; - if (lcd_height < 0) - lcd_height = 2; + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_SELECP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; break; } + /* Overwrite with module params set on loading */ + if (lcd_height != NOT_SET) + lcd.height = lcd_height; + if (lcd_width != NOT_SET) + lcd.width = lcd_width; + if (lcd_bwidth != NOT_SET) + lcd.bwidth = lcd_bwidth; + if (lcd_hwidth != NOT_SET) + lcd.hwidth = lcd_hwidth; + if (lcd_charset != NOT_SET) + lcd.charset = lcd_charset; + if (lcd_proto != NOT_SET) + lcd.proto = lcd_proto; + if (lcd_e_pin != PIN_NOT_SET) + lcd.pins.e = lcd_e_pin; + if (lcd_rs_pin != PIN_NOT_SET) + lcd.pins.rs = lcd_rs_pin; + if (lcd_rw_pin != PIN_NOT_SET) + lcd.pins.rw = lcd_rw_pin; + if (lcd_cl_pin != PIN_NOT_SET) + lcd.pins.cl = lcd_cl_pin; + if (lcd_da_pin != PIN_NOT_SET) + lcd.pins.da = lcd_da_pin; + if (lcd_bl_pin != PIN_NOT_SET) + lcd.pins.bl = lcd_bl_pin; + /* this is used to catch wrong and default values */ - if (lcd_width <= 0) - lcd_width = DEFAULT_LCD_WIDTH; - if (lcd_bwidth <= 0) - lcd_bwidth = DEFAULT_LCD_BWIDTH; - if (lcd_hwidth <= 0) - lcd_hwidth = DEFAULT_LCD_HWIDTH; - if (lcd_height <= 0) - lcd_height = DEFAULT_LCD_HEIGHT; - - if (lcd_proto == LCD_PROTO_SERIAL) { /* SERIAL */ + if (lcd.width <= 0) + lcd.width = DEFAULT_LCD_WIDTH; + if (lcd.bwidth <= 0) + lcd.bwidth = DEFAULT_LCD_BWIDTH; + if (lcd.hwidth <= 0) + lcd.hwidth = DEFAULT_LCD_HWIDTH; + if (lcd.height <= 0) + lcd.height = DEFAULT_LCD_HEIGHT; + + if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ lcd_write_cmd = lcd_write_cmd_s; lcd_write_data = lcd_write_data_s; lcd_clear_fast = lcd_clear_fast_s; - if (lcd_cl_pin == PIN_NOT_SET) - lcd_cl_pin = DEFAULT_LCD_PIN_SCL; - if (lcd_da_pin == PIN_NOT_SET) - lcd_da_pin = DEFAULT_LCD_PIN_SDA; + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = DEFAULT_LCD_PIN_SCL; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = DEFAULT_LCD_PIN_SDA; - } else if (lcd_proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ + } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ lcd_write_cmd = lcd_write_cmd_p8; lcd_write_data = lcd_write_data_p8; lcd_clear_fast = lcd_clear_fast_p8; - if (lcd_e_pin == PIN_NOT_SET) - lcd_e_pin = DEFAULT_LCD_PIN_E; - if (lcd_rs_pin == PIN_NOT_SET) - lcd_rs_pin = DEFAULT_LCD_PIN_RS; - if (lcd_rw_pin == PIN_NOT_SET) - lcd_rw_pin = DEFAULT_LCD_PIN_RW; + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = DEFAULT_LCD_PIN_E; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = DEFAULT_LCD_PIN_RS; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = DEFAULT_LCD_PIN_RW; } else { lcd_write_cmd = lcd_write_cmd_tilcd; lcd_write_data = lcd_write_data_tilcd; lcd_clear_fast = lcd_clear_fast_tilcd; } - if (lcd_bl_pin == PIN_NOT_SET) - lcd_bl_pin = DEFAULT_LCD_PIN_BL; - - if (lcd_e_pin == PIN_NOT_SET) - lcd_e_pin = PIN_NONE; - if (lcd_rs_pin == PIN_NOT_SET) - lcd_rs_pin = PIN_NONE; - if (lcd_rw_pin == PIN_NOT_SET) - lcd_rw_pin = PIN_NONE; - if (lcd_bl_pin == PIN_NOT_SET) - lcd_bl_pin = PIN_NONE; - if (lcd_cl_pin == PIN_NOT_SET) - lcd_cl_pin = PIN_NONE; - if (lcd_da_pin == PIN_NOT_SET) - lcd_da_pin = PIN_NONE; - - if (lcd_charset < 0) - lcd_charset = DEFAULT_LCD_CHARSET; - - if (lcd_charset == LCD_CHARSET_KS0074) + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = DEFAULT_LCD_PIN_BL; + + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = PIN_NONE; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = PIN_NONE; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = PIN_NONE; + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = PIN_NONE; + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = PIN_NONE; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = PIN_NONE; + + if (lcd.charset == NOT_SET) + lcd.charset = DEFAULT_LCD_CHARSET; + + if (lcd.charset == LCD_CHARSET_KS0074) lcd_char_conv = lcd_char_conv_ks0074; else lcd_char_conv = NULL; - if (lcd_bl_pin != PIN_NONE) + if (lcd.pins.bl != PIN_NONE) init_scan_timer(); - pin_to_bits(lcd_e_pin, lcd_bits[LCD_PORT_D][LCD_BIT_E], + pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], lcd_bits[LCD_PORT_C][LCD_BIT_E]); - pin_to_bits(lcd_rs_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RS], + pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS], lcd_bits[LCD_PORT_C][LCD_BIT_RS]); - pin_to_bits(lcd_rw_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RW], + pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW], lcd_bits[LCD_PORT_C][LCD_BIT_RW]); - pin_to_bits(lcd_bl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_BL], + pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL], lcd_bits[LCD_PORT_C][LCD_BIT_BL]); - pin_to_bits(lcd_cl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_CL], + pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL], lcd_bits[LCD_PORT_C][LCD_BIT_CL]); - pin_to_bits(lcd_da_pin, lcd_bits[LCD_PORT_D][LCD_BIT_DA], + pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], lcd_bits[LCD_PORT_C][LCD_BIT_DA]); /* before this line, we must NOT send anything to the display. * Since lcd_init_display() needs to write data, we have to * enable mark the LCD initialized just before. */ - lcd_initialized = 1; + lcd.initialized = true; lcd_init_display(); /* display a short message */ @@ -1589,10 +1619,10 @@ static void lcd_init(void) panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-" PANEL_VERSION); #endif - lcd_addr_x = 0; - lcd_addr_y = 0; + lcd.addr.x = 0; + lcd.addr.y = 0; /* clear the display on the next device opening */ - lcd_must_clear = 1; + lcd.must_clear = true; lcd_gotoxy(); } @@ -1627,20 +1657,19 @@ static ssize_t keypad_read(struct file *file, static int keypad_open(struct inode *inode, struct file *file) { - if (keypad_open_cnt) + if (!atomic_dec_and_test(&keypad_available)) return -EBUSY; /* open only once at a time */ if (file->f_mode & FMODE_WRITE) /* device is read-only */ return -EPERM; keypad_buflen = 0; /* flush the buffer on opening */ - keypad_open_cnt++; return 0; } static int keypad_release(struct inode *inode, struct file *file) { - keypad_open_cnt--; + atomic_inc(&keypad_available); return 0; } @@ -1652,9 +1681,9 @@ static const struct file_operations keypad_fops = { }; static struct miscdevice keypad_dev = { - KEYPAD_MINOR, - "keypad", - &keypad_fops + .minor = KEYPAD_MINOR, + .name = "keypad", + .fops = &keypad_fops, }; static void keypad_send_key(const char *string, int max_len) @@ -1663,7 +1692,7 @@ static void keypad_send_key(const char *string, int max_len) return; /* send the key to the device only if a process is attached to it. */ - if (keypad_open_cnt > 0) { + if (!atomic_read(&keypad_available)) { while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { keypad_buffer[(keypad_start + keypad_buflen++) % KEYPAD_BUFFER] = *string++; @@ -1917,7 +1946,7 @@ static void panel_process_inputs(void) static void panel_scan_timer(void) { - if (keypad_enabled && keypad_initialized) { + if (keypad.enabled && keypad_initialized) { if (spin_trylock_irq(&pprt_lock)) { phys_scan_contacts(); @@ -1929,14 +1958,16 @@ static void panel_scan_timer(void) panel_process_inputs(); } - if (lcd_enabled && lcd_initialized) { + if (lcd.enabled && lcd.initialized) { if (keypressed) { - if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0)) + if (lcd.light_tempo == 0 + && ((lcd.flags & LCD_FLAG_L) == 0)) lcd_backlight(1); - light_tempo = FLASH_LIGHT_TEMPO; - } else if (light_tempo > 0) { - light_tempo--; - if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0)) + lcd.light_tempo = FLASH_LIGHT_TEMPO; + } else if (lcd.light_tempo > 0) { + lcd.light_tempo--; + if (lcd.light_tempo == 0 + && ((lcd.flags & LCD_FLAG_L) == 0)) lcd_backlight(0); } } @@ -2108,7 +2139,7 @@ static void keypad_init(void) static int panel_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if (lcd_enabled && lcd_initialized) { + if (lcd.enabled && lcd.initialized) { switch (code) { case SYS_DOWN: panel_lcd_print @@ -2164,13 +2195,13 @@ static void panel_attach(struct parport *port) /* must init LCD first, just in case an IRQ from the keypad is * generated at keypad init */ - if (lcd_enabled) { + if (lcd.enabled) { lcd_init(); if (misc_register(&lcd_dev)) goto err_unreg_device; } - if (keypad_enabled) { + if (keypad.enabled) { keypad_init(); if (misc_register(&keypad_dev)) goto err_lcd_unreg; @@ -2178,7 +2209,7 @@ static void panel_attach(struct parport *port) return; err_lcd_unreg: - if (lcd_enabled) + if (lcd.enabled) misc_deregister(&lcd_dev); err_unreg_device: parport_unregister_device(pprt); @@ -2196,14 +2227,14 @@ static void panel_detach(struct parport *port) return; } - if (keypad_enabled && keypad_initialized) { + if (keypad.enabled && keypad_initialized) { misc_deregister(&keypad_dev); keypad_initialized = 0; } - if (lcd_enabled && lcd_initialized) { + if (lcd.enabled && lcd.initialized) { misc_deregister(&lcd_dev); - lcd_initialized = 0; + lcd.initialized = false; } parport_release(pprt); @@ -2218,72 +2249,89 @@ static struct parport_driver panel_driver = { }; /* init function */ -static int panel_init(void) +static int __init panel_init_module(void) { - /* for backwards compatibility */ - if (keypad_type < 0) - keypad_type = keypad_enabled; - - if (lcd_type < 0) - lcd_type = lcd_enabled; - - if (parport < 0) - parport = DEFAULT_PARPORT; + int selected_keypad_type = NOT_SET; /* take care of an eventual profile */ switch (profile) { case PANEL_PROFILE_CUSTOM: /* custom profile */ - if (keypad_type < 0) - keypad_type = DEFAULT_KEYPAD; - if (lcd_type < 0) - lcd_type = DEFAULT_LCD; + selected_keypad_type = DEFAULT_KEYPAD_TYPE; + selected_lcd_type = DEFAULT_LCD_TYPE; break; case PANEL_PROFILE_OLD: /* 8 bits, 2*16, old keypad */ - if (keypad_type < 0) - keypad_type = KEYPAD_TYPE_OLD; - if (lcd_type < 0) - lcd_type = LCD_TYPE_OLD; - if (lcd_width < 0) + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; + + /* TODO: This two are a little hacky, sort it out later */ + if (lcd_width == NOT_SET) lcd_width = 16; - if (lcd_hwidth < 0) + if (lcd_hwidth == NOT_SET) lcd_hwidth = 16; break; case PANEL_PROFILE_NEW: /* serial, 2*16, new keypad */ - if (keypad_type < 0) - keypad_type = KEYPAD_TYPE_NEW; - if (lcd_type < 0) - lcd_type = LCD_TYPE_KS0074; + selected_keypad_type = KEYPAD_TYPE_NEW; + selected_lcd_type = LCD_TYPE_KS0074; break; case PANEL_PROFILE_HANTRONIX: /* 8 bits, 2*16 hantronix-like, no keypad */ - if (keypad_type < 0) - keypad_type = KEYPAD_TYPE_NONE; - if (lcd_type < 0) - lcd_type = LCD_TYPE_HANTRONIX; + selected_keypad_type = KEYPAD_TYPE_NONE; + selected_lcd_type = LCD_TYPE_HANTRONIX; break; case PANEL_PROFILE_NEXCOM: /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */ - if (keypad_type < 0) - keypad_type = KEYPAD_TYPE_NEXCOM; - if (lcd_type < 0) - lcd_type = LCD_TYPE_NEXCOM; + selected_keypad_type = KEYPAD_TYPE_NEXCOM; + selected_lcd_type = LCD_TYPE_NEXCOM; break; case PANEL_PROFILE_LARGE: /* 8 bits, 2*40, old keypad */ - if (keypad_type < 0) - keypad_type = KEYPAD_TYPE_OLD; - if (lcd_type < 0) - lcd_type = LCD_TYPE_OLD; + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; break; } - lcd_enabled = (lcd_type > 0); - keypad_enabled = (keypad_type > 0); + /* + * Init lcd struct with load-time values to preserve exact current + * functionality (at least for now). + */ + lcd.height = lcd_height; + lcd.width = lcd_width; + lcd.bwidth = lcd_bwidth; + lcd.hwidth = lcd_hwidth; + lcd.charset = lcd_charset; + lcd.proto = lcd_proto; + lcd.pins.e = lcd_e_pin; + lcd.pins.rs = lcd_rs_pin; + lcd.pins.rw = lcd_rw_pin; + lcd.pins.cl = lcd_cl_pin; + lcd.pins.da = lcd_da_pin; + lcd.pins.bl = lcd_bl_pin; + + /* Leave it for now, just in case */ + lcd.esc_seq.len = -1; + + /* + * Overwrite selection with module param values (both keypad and lcd), + * where the deprecated params have lower prio. + */ + if (keypad_enabled != NOT_SET) + selected_keypad_type = keypad_enabled; + if (keypad_type != NOT_SET) + selected_keypad_type = keypad_type; - switch (keypad_type) { + keypad.enabled = (selected_keypad_type > 0); + + if (lcd_enabled != NOT_SET) + selected_lcd_type = lcd_enabled; + if (lcd_type != NOT_SET) + selected_lcd_type = lcd_type; + + lcd.enabled = (selected_lcd_type > 0); + + switch (selected_keypad_type) { case KEYPAD_TYPE_OLD: keypad_profile = old_keypad_profile; break; @@ -2306,7 +2354,7 @@ static int panel_init(void) return -EIO; } - if (!lcd_enabled && !keypad_enabled) { + if (!lcd.enabled && !keypad.enabled) { /* no device enabled, let's release the parport */ if (pprt) { parport_release(pprt); @@ -2333,11 +2381,6 @@ static int panel_init(void) return 0; } -static int __init panel_init_module(void) -{ - return panel_init(); -} - static void __exit panel_cleanup_module(void) { unregister_reboot_notifier(&panel_notifier); @@ -2346,16 +2389,16 @@ static void __exit panel_cleanup_module(void) del_timer_sync(&scan_timer); if (pprt != NULL) { - if (keypad_enabled) { + if (keypad.enabled) { misc_deregister(&keypad_dev); keypad_initialized = 0; } - if (lcd_enabled) { + if (lcd.enabled) { panel_lcd_print("\x0cLCD driver " PANEL_VERSION "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); misc_deregister(&lcd_dev); - lcd_initialized = 0; + lcd.initialized = false; } /* TODO: free all input signals */ |