aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/panel.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2017-03-10 09:15:17 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-17 02:10:49 -0400
commit39f8ea46724efbed3ca021863a22337c31be264c (patch)
tree964039ba139e443b76937522f4762dc27a24b673 /drivers/misc/panel.c
parent2eec10807a2fbf0f240c55070b71b8cd5c09ab23 (diff)
auxdisplay: charlcd: Extract character LCD core from misc/panel
Extract the character LCD core from the Parallel port LCD/Keypad Panel driver in the misc subsystem, and convert it into a subdriver in the auxdisplay subsystem. This allows the character LCD core to be used by other drivers later. Compilation is controlled by its own Kconfig symbol CHARLCD, which is to be selected by its users, but can be enabled manually for compile-testing. All functions changed their prefix from "lcd_" to "charlcd_", and gained a "struct charlcd *" parameter to operate on a specific instance. While the driver API thus is ready to support multiple instances, the current limitation of a single display (/dev/lcd has a single misc minor assigned) is retained. No functional changes intended. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/panel.c')
-rw-r--r--drivers/misc/panel.c827
1 files changed, 92 insertions, 735 deletions
diff --git a/drivers/misc/panel.c b/drivers/misc/panel.c
index ef2ece0f26af..e0c014c2356f 100644
--- a/drivers/misc/panel.c
+++ b/drivers/misc/panel.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Front panel driver for Linux 2 * Front panel driver for Linux
3 * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu> 3 * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
4 * Copyright (C) 2016-2017 Glider bvba
4 * 5 *
5 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
@@ -54,15 +55,12 @@
54#include <linux/ctype.h> 55#include <linux/ctype.h>
55#include <linux/parport.h> 56#include <linux/parport.h>
56#include <linux/list.h> 57#include <linux/list.h>
57#include <linux/notifier.h>
58#include <linux/reboot.h>
59#include <linux/workqueue.h>
60#include <generated/utsrelease.h>
61 58
62#include <linux/io.h> 59#include <linux/io.h>
63#include <linux/uaccess.h> 60#include <linux/uaccess.h>
64 61
65#define LCD_MINOR 156 62#include <misc/charlcd.h>
63
66#define KEYPAD_MINOR 185 64#define KEYPAD_MINOR 185
67 65
68#define LCD_MAXBYTES 256 /* max burst write */ 66#define LCD_MAXBYTES 256 /* max burst write */
@@ -76,9 +74,6 @@
76/* a key repeats this times INPUT_POLL_TIME */ 74/* a key repeats this times INPUT_POLL_TIME */
77#define KEYPAD_REP_DELAY (2) 75#define KEYPAD_REP_DELAY (2)
78 76
79/* keep the light on this many seconds for each flash */
80#define FLASH_LIGHT_TEMPO (4)
81
82/* converts an r_str() input to an active high, bits string : 000BAOSE */ 77/* converts an r_str() input to an active high, bits string : 000BAOSE */
83#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) 78#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3)
84 79
@@ -120,40 +115,6 @@
120#define PIN_SELECP 17 115#define PIN_SELECP 17
121#define PIN_NOT_SET 127 116#define PIN_NOT_SET 127
122 117
123#define LCD_FLAG_B 0x0004 /* blink on */
124#define LCD_FLAG_C 0x0008 /* cursor on */
125#define LCD_FLAG_D 0x0010 /* display on */
126#define LCD_FLAG_F 0x0020 /* large font mode */
127#define LCD_FLAG_N 0x0040 /* 2-rows mode */
128#define LCD_FLAG_L 0x0080 /* backlight enabled */
129
130/* LCD commands */
131#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */
132
133#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */
134#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */
135
136#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */
137#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */
138#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */
139#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */
140
141#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */
142#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */
143#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */
144
145#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */
146#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */
147#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */
148#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */
149
150#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */
151
152#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */
153
154#define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */
155#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */
156
157#define NOT_SET -1 118#define NOT_SET -1
158 119
159/* macros to simplify use of the parallel port */ 120/* macros to simplify use of the parallel port */
@@ -245,19 +206,10 @@ static wait_queue_head_t keypad_read_wait;
245static struct { 206static struct {
246 bool enabled; 207 bool enabled;
247 bool initialized; 208 bool initialized;
248 bool must_clear;
249 209
250 int height;
251 int width;
252 int bwidth;
253 int hwidth;
254 int charset; 210 int charset;
255 int proto; 211 int proto;
256 212
257 struct delayed_work bl_work;
258 struct mutex bl_tempo_lock; /* Protects access to bl_tempo */
259 bool bl_tempo;
260
261 /* TODO: use union here? */ 213 /* TODO: use union here? */
262 struct { 214 struct {
263 int e; 215 int e;
@@ -268,20 +220,7 @@ static struct {
268 int bl; 220 int bl;
269 } pins; 221 } pins;
270 222
271 /* contains the LCD config state */ 223 struct charlcd *charlcd;
272 unsigned long int flags;
273
274 /* Contains the LCD X and Y offset */
275 struct {
276 unsigned long int x;
277 unsigned long int y;
278 } addr;
279
280 /* Current escape sequence and it's length or -1 if outside */
281 struct {
282 char buf[LCD_ESCAPE_LEN + 1];
283 int len;
284 } esc_seq;
285} lcd; 224} lcd;
286 225
287/* Needed only for init */ 226/* Needed only for init */
@@ -464,17 +403,12 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
464/* global variables */ 403/* global variables */
465 404
466/* Device single-open policy control */ 405/* Device single-open policy control */
467static atomic_t lcd_available = ATOMIC_INIT(1);
468static atomic_t keypad_available = ATOMIC_INIT(1); 406static atomic_t keypad_available = ATOMIC_INIT(1);
469 407
470static struct pardevice *pprt; 408static struct pardevice *pprt;
471 409
472static int keypad_initialized; 410static int keypad_initialized;
473 411
474static void (*lcd_write_cmd)(int);
475static void (*lcd_write_data)(int);
476static void (*lcd_clear_fast)(void);
477
478static DEFINE_SPINLOCK(pprt_lock); 412static DEFINE_SPINLOCK(pprt_lock);
479static struct timer_list scan_timer; 413static struct timer_list scan_timer;
480 414
@@ -574,8 +508,6 @@ static int keypad_enabled = NOT_SET;
574module_param(keypad_enabled, int, 0000); 508module_param(keypad_enabled, int, 0000);
575MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); 509MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
576 510
577static const unsigned char *lcd_char_conv;
578
579/* for some LCD drivers (ks0074) we need a charset conversion table. */ 511/* for some LCD drivers (ks0074) we need a charset conversion table. */
580static const unsigned char lcd_char_conv_ks0074[256] = { 512static const unsigned char lcd_char_conv_ks0074[256] = {
581 /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */ 513 /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */
@@ -752,15 +684,6 @@ static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
752 } 684 }
753} 685}
754 686
755/* sleeps that many milliseconds with a reschedule */
756static void long_sleep(int ms)
757{
758 if (in_interrupt())
759 mdelay(ms);
760 else
761 schedule_timeout_interruptible(msecs_to_jiffies(ms));
762}
763
764/* 687/*
765 * send a serial byte to the LCD panel. The caller is responsible for locking 688 * send a serial byte to the LCD panel. The caller is responsible for locking
766 * if needed. 689 * if needed.
@@ -792,8 +715,11 @@ static void lcd_send_serial(int byte)
792} 715}
793 716
794/* turn the backlight on or off */ 717/* turn the backlight on or off */
795static void __lcd_backlight(int on) 718static void lcd_backlight(struct charlcd *charlcd, int on)
796{ 719{
720 if (lcd.pins.bl == PIN_NONE)
721 return;
722
797 /* The backlight is activated by setting the AUTOFEED line to +5V */ 723 /* The backlight is activated by setting the AUTOFEED line to +5V */
798 spin_lock_irq(&pprt_lock); 724 spin_lock_irq(&pprt_lock);
799 if (on) 725 if (on)
@@ -804,46 +730,8 @@ static void __lcd_backlight(int on)
804 spin_unlock_irq(&pprt_lock); 730 spin_unlock_irq(&pprt_lock);
805} 731}
806 732
807static void lcd_backlight(int on)
808{
809 if (lcd.pins.bl == PIN_NONE)
810 return;
811
812 mutex_lock(&lcd.bl_tempo_lock);
813 if (!lcd.bl_tempo)
814 __lcd_backlight(on);
815 mutex_unlock(&lcd.bl_tempo_lock);
816}
817
818static void lcd_bl_off(struct work_struct *work)
819{
820 mutex_lock(&lcd.bl_tempo_lock);
821 if (lcd.bl_tempo) {
822 lcd.bl_tempo = false;
823 if (!(lcd.flags & LCD_FLAG_L))
824 __lcd_backlight(0);
825 }
826 mutex_unlock(&lcd.bl_tempo_lock);
827}
828
829/* turn the backlight on for a little while */
830static void lcd_poke(void)
831{
832 if (lcd.pins.bl == PIN_NONE)
833 return;
834
835 cancel_delayed_work_sync(&lcd.bl_work);
836
837 mutex_lock(&lcd.bl_tempo_lock);
838 if (!lcd.bl_tempo && !(lcd.flags & LCD_FLAG_L))
839 __lcd_backlight(1);
840 lcd.bl_tempo = true;
841 schedule_delayed_work(&lcd.bl_work, FLASH_LIGHT_TEMPO * HZ);
842 mutex_unlock(&lcd.bl_tempo_lock);
843}
844
845/* send a command to the LCD panel in serial mode */ 733/* send a command to the LCD panel in serial mode */
846static void lcd_write_cmd_s(int cmd) 734static void lcd_write_cmd_s(struct charlcd *charlcd, int cmd)
847{ 735{
848 spin_lock_irq(&pprt_lock); 736 spin_lock_irq(&pprt_lock);
849 lcd_send_serial(0x1F); /* R/W=W, RS=0 */ 737 lcd_send_serial(0x1F); /* R/W=W, RS=0 */
@@ -854,7 +742,7 @@ static void lcd_write_cmd_s(int cmd)
854} 742}
855 743
856/* send data to the LCD panel in serial mode */ 744/* send data to the LCD panel in serial mode */
857static void lcd_write_data_s(int data) 745static void lcd_write_data_s(struct charlcd *charlcd, int data)
858{ 746{
859 spin_lock_irq(&pprt_lock); 747 spin_lock_irq(&pprt_lock);
860 lcd_send_serial(0x5F); /* R/W=W, RS=1 */ 748 lcd_send_serial(0x5F); /* R/W=W, RS=1 */
@@ -865,7 +753,7 @@ static void lcd_write_data_s(int data)
865} 753}
866 754
867/* send a command to the LCD panel in 8 bits parallel mode */ 755/* send a command to the LCD panel in 8 bits parallel mode */
868static void lcd_write_cmd_p8(int cmd) 756static void lcd_write_cmd_p8(struct charlcd *charlcd, int cmd)
869{ 757{
870 spin_lock_irq(&pprt_lock); 758 spin_lock_irq(&pprt_lock);
871 /* present the data to the data port */ 759 /* present the data to the data port */
@@ -887,7 +775,7 @@ static void lcd_write_cmd_p8(int cmd)
887} 775}
888 776
889/* send data to the LCD panel in 8 bits parallel mode */ 777/* send data to the LCD panel in 8 bits parallel mode */
890static void lcd_write_data_p8(int data) 778static void lcd_write_data_p8(struct charlcd *charlcd, int data)
891{ 779{
892 spin_lock_irq(&pprt_lock); 780 spin_lock_irq(&pprt_lock);
893 /* present the data to the data port */ 781 /* present the data to the data port */
@@ -909,7 +797,7 @@ static void lcd_write_data_p8(int data)
909} 797}
910 798
911/* send a command to the TI LCD panel */ 799/* send a command to the TI LCD panel */
912static void lcd_write_cmd_tilcd(int cmd) 800static void lcd_write_cmd_tilcd(struct charlcd *charlcd, int cmd)
913{ 801{
914 spin_lock_irq(&pprt_lock); 802 spin_lock_irq(&pprt_lock);
915 /* present the data to the control port */ 803 /* present the data to the control port */
@@ -919,7 +807,7 @@ static void lcd_write_cmd_tilcd(int cmd)
919} 807}
920 808
921/* send data to the TI LCD panel */ 809/* send data to the TI LCD panel */
922static void lcd_write_data_tilcd(int data) 810static void lcd_write_data_tilcd(struct charlcd *charlcd, int data)
923{ 811{
924 spin_lock_irq(&pprt_lock); 812 spin_lock_irq(&pprt_lock);
925 /* present the data to the data port */ 813 /* present the data to the data port */
@@ -928,47 +816,13 @@ static void lcd_write_data_tilcd(int data)
928 spin_unlock_irq(&pprt_lock); 816 spin_unlock_irq(&pprt_lock);
929} 817}
930 818
931static void lcd_gotoxy(void)
932{
933 lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR
934 | (lcd.addr.y ? lcd.hwidth : 0)
935 /*
936 * we force the cursor to stay at the end of the
937 * line if it wants to go farther
938 */
939 | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x &
940 (lcd.hwidth - 1) : lcd.bwidth - 1));
941}
942
943static void lcd_home(void)
944{
945 lcd.addr.x = 0;
946 lcd.addr.y = 0;
947 lcd_gotoxy();
948}
949
950static void lcd_print(char c)
951{
952 if (lcd.addr.x < lcd.bwidth) {
953 if (lcd_char_conv)
954 c = lcd_char_conv[(unsigned char)c];
955 lcd_write_data(c);
956 lcd.addr.x++;
957 }
958 /* prevents the cursor from wrapping onto the next line */
959 if (lcd.addr.x == lcd.bwidth)
960 lcd_gotoxy();
961}
962
963/* fills the display with spaces and resets X/Y */ 819/* fills the display with spaces and resets X/Y */
964static void lcd_clear_fast_s(void) 820static void lcd_clear_fast_s(struct charlcd *charlcd)
965{ 821{
966 int pos; 822 int pos;
967 823
968 lcd_home();
969
970 spin_lock_irq(&pprt_lock); 824 spin_lock_irq(&pprt_lock);
971 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { 825 for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
972 lcd_send_serial(0x5F); /* R/W=W, RS=1 */ 826 lcd_send_serial(0x5F); /* R/W=W, RS=1 */
973 lcd_send_serial(' ' & 0x0F); 827 lcd_send_serial(' ' & 0x0F);
974 lcd_send_serial((' ' >> 4) & 0x0F); 828 lcd_send_serial((' ' >> 4) & 0x0F);
@@ -976,19 +830,15 @@ static void lcd_clear_fast_s(void)
976 udelay(40); 830 udelay(40);
977 } 831 }
978 spin_unlock_irq(&pprt_lock); 832 spin_unlock_irq(&pprt_lock);
979
980 lcd_home();
981} 833}
982 834
983/* fills the display with spaces and resets X/Y */ 835/* fills the display with spaces and resets X/Y */
984static void lcd_clear_fast_p8(void) 836static void lcd_clear_fast_p8(struct charlcd *charlcd)
985{ 837{
986 int pos; 838 int pos;
987 839
988 lcd_home();
989
990 spin_lock_irq(&pprt_lock); 840 spin_lock_irq(&pprt_lock);
991 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { 841 for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
992 /* present the data to the data port */ 842 /* present the data to the data port */
993 w_dtr(pprt, ' '); 843 w_dtr(pprt, ' ');
994 844
@@ -1010,488 +860,62 @@ static void lcd_clear_fast_p8(void)
1010 udelay(45); 860 udelay(45);
1011 } 861 }
1012 spin_unlock_irq(&pprt_lock); 862 spin_unlock_irq(&pprt_lock);
1013
1014 lcd_home();
1015} 863}
1016 864
1017/* fills the display with spaces and resets X/Y */ 865/* fills the display with spaces and resets X/Y */
1018static void lcd_clear_fast_tilcd(void) 866static void lcd_clear_fast_tilcd(struct charlcd *charlcd)
1019{ 867{
1020 int pos; 868 int pos;
1021 869
1022 lcd_home();
1023
1024 spin_lock_irq(&pprt_lock); 870 spin_lock_irq(&pprt_lock);
1025 for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { 871 for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
1026 /* present the data to the data port */ 872 /* present the data to the data port */
1027 w_dtr(pprt, ' '); 873 w_dtr(pprt, ' ');
1028 udelay(60); 874 udelay(60);
1029 } 875 }
1030 876
1031 spin_unlock_irq(&pprt_lock); 877 spin_unlock_irq(&pprt_lock);
1032
1033 lcd_home();
1034}
1035
1036/* clears the display and resets X/Y */
1037static void lcd_clear_display(void)
1038{
1039 lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR);
1040 lcd.addr.x = 0;
1041 lcd.addr.y = 0;
1042 /* we must wait a few milliseconds (15) */
1043 long_sleep(15);
1044} 878}
1045 879
1046static void lcd_init_display(void) 880static struct charlcd_ops charlcd_serial_ops = {
1047{ 881 .write_cmd = lcd_write_cmd_s,
1048 lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) 882 .write_data = lcd_write_data_s,
1049 | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; 883 .clear_fast = lcd_clear_fast_s,
1050 884 .backlight = lcd_backlight,
1051 long_sleep(20); /* wait 20 ms after power-up for the paranoid */ 885};
1052
1053 /* 8bits, 1 line, small fonts; let's do it 3 times */
1054 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1055 long_sleep(10);
1056 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1057 long_sleep(10);
1058 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS);
1059 long_sleep(10);
1060
1061 /* set font height and lines number */
1062 lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS
1063 | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0)
1064 | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0)
1065 );
1066 long_sleep(10);
1067
1068 /* display off, cursor off, blink off */
1069 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL);
1070 long_sleep(10);
1071
1072 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */
1073 | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0)
1074 | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0)
1075 | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0)
1076 );
1077
1078 lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0);
1079
1080 long_sleep(10);
1081
1082 /* entry mode set : increment, cursor shifting */
1083 lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
1084 886
1085 lcd_clear_display(); 887static struct charlcd_ops charlcd_parallel_ops = {
1086} 888 .write_cmd = lcd_write_cmd_p8,
889 .write_data = lcd_write_data_p8,
890 .clear_fast = lcd_clear_fast_p8,
891 .backlight = lcd_backlight,
892};
1087 893
1088/* 894static struct charlcd_ops charlcd_tilcd_ops = {
1089 * These are the file operation function for user access to /dev/lcd 895 .write_cmd = lcd_write_cmd_tilcd,
1090 * This function can also be called from inside the kernel, by 896 .write_data = lcd_write_data_tilcd,
1091 * setting file and ppos to NULL. 897 .clear_fast = lcd_clear_fast_tilcd,
1092 * 898 .backlight = lcd_backlight,
1093 */ 899};
1094 900
1095static inline int handle_lcd_special_code(void) 901/* initialize the LCD driver */
902static void lcd_init(void)
1096{ 903{
1097 /* LCD special codes */ 904 struct charlcd *charlcd;
1098
1099 int processed = 0;
1100 905
1101 char *esc = lcd.esc_seq.buf + 2; 906 charlcd = charlcd_alloc(0);
1102 int oldflags = lcd.flags; 907 if (!charlcd)
1103 908 return;
1104 /* check for display mode flags */
1105 switch (*esc) {
1106 case 'D': /* Display ON */
1107 lcd.flags |= LCD_FLAG_D;
1108 processed = 1;
1109 break;
1110 case 'd': /* Display OFF */
1111 lcd.flags &= ~LCD_FLAG_D;
1112 processed = 1;
1113 break;
1114 case 'C': /* Cursor ON */
1115 lcd.flags |= LCD_FLAG_C;
1116 processed = 1;
1117 break;
1118 case 'c': /* Cursor OFF */
1119 lcd.flags &= ~LCD_FLAG_C;
1120 processed = 1;
1121 break;
1122 case 'B': /* Blink ON */
1123 lcd.flags |= LCD_FLAG_B;
1124 processed = 1;
1125 break;
1126 case 'b': /* Blink OFF */
1127 lcd.flags &= ~LCD_FLAG_B;
1128 processed = 1;
1129 break;
1130 case '+': /* Back light ON */
1131 lcd.flags |= LCD_FLAG_L;
1132 processed = 1;
1133 break;
1134 case '-': /* Back light OFF */
1135 lcd.flags &= ~LCD_FLAG_L;
1136 processed = 1;
1137 break;
1138 case '*':
1139 /* flash back light */
1140 lcd_poke();
1141 processed = 1;
1142 break;
1143 case 'f': /* Small Font */
1144 lcd.flags &= ~LCD_FLAG_F;
1145 processed = 1;
1146 break;
1147 case 'F': /* Large Font */
1148 lcd.flags |= LCD_FLAG_F;
1149 processed = 1;
1150 break;
1151 case 'n': /* One Line */
1152 lcd.flags &= ~LCD_FLAG_N;
1153 processed = 1;
1154 break;
1155 case 'N': /* Two Lines */
1156 lcd.flags |= LCD_FLAG_N;
1157 break;
1158 case 'l': /* Shift Cursor Left */
1159 if (lcd.addr.x > 0) {
1160 /* back one char if not at end of line */
1161 if (lcd.addr.x < lcd.bwidth)
1162 lcd_write_cmd(LCD_CMD_SHIFT);
1163 lcd.addr.x--;
1164 }
1165 processed = 1;
1166 break;
1167 case 'r': /* shift cursor right */
1168 if (lcd.addr.x < lcd.width) {
1169 /* allow the cursor to pass the end of the line */
1170 if (lcd.addr.x < (lcd.bwidth - 1))
1171 lcd_write_cmd(LCD_CMD_SHIFT |
1172 LCD_CMD_SHIFT_RIGHT);
1173 lcd.addr.x++;
1174 }
1175 processed = 1;
1176 break;
1177 case 'L': /* shift display left */
1178 lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
1179 processed = 1;
1180 break;
1181 case 'R': /* shift display right */
1182 lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT |
1183 LCD_CMD_SHIFT_RIGHT);
1184 processed = 1;
1185 break;
1186 case 'k': { /* kill end of line */
1187 int x;
1188
1189 for (x = lcd.addr.x; x < lcd.bwidth; x++)
1190 lcd_write_data(' ');
1191
1192 /* restore cursor position */
1193 lcd_gotoxy();
1194 processed = 1;
1195 break;
1196 }
1197 case 'I': /* reinitialize display */
1198 lcd_init_display();
1199 processed = 1;
1200 break;
1201 case 'G': {
1202 /* Generator : LGcxxxxx...xx; must have <c> between '0'
1203 * and '7', representing the numerical ASCII code of the
1204 * redefined character, and <xx...xx> a sequence of 16
1205 * hex digits representing 8 bytes for each character.
1206 * Most LCDs will only use 5 lower bits of the 7 first
1207 * bytes.
1208 */
1209
1210 unsigned char cgbytes[8];
1211 unsigned char cgaddr;
1212 int cgoffset;
1213 int shift;
1214 char value;
1215 int addr;
1216
1217 if (!strchr(esc, ';'))
1218 break;
1219
1220 esc++;
1221
1222 cgaddr = *(esc++) - '0';
1223 if (cgaddr > 7) {
1224 processed = 1;
1225 break;
1226 }
1227
1228 cgoffset = 0;
1229 shift = 0;
1230 value = 0;
1231 while (*esc && cgoffset < 8) {
1232 shift ^= 4;
1233 if (*esc >= '0' && *esc <= '9') {
1234 value |= (*esc - '0') << shift;
1235 } else if (*esc >= 'A' && *esc <= 'Z') {
1236 value |= (*esc - 'A' + 10) << shift;
1237 } else if (*esc >= 'a' && *esc <= 'z') {
1238 value |= (*esc - 'a' + 10) << shift;
1239 } else {
1240 esc++;
1241 continue;
1242 }
1243
1244 if (shift == 0) {
1245 cgbytes[cgoffset++] = value;
1246 value = 0;
1247 }
1248
1249 esc++;
1250 }
1251
1252 lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
1253 for (addr = 0; addr < cgoffset; addr++)
1254 lcd_write_data(cgbytes[addr]);
1255
1256 /* ensures that we stop writing to CGRAM */
1257 lcd_gotoxy();
1258 processed = 1;
1259 break;
1260 }
1261 case 'x': /* gotoxy : LxXXX[yYYY]; */
1262 case 'y': /* gotoxy : LyYYY[xXXX]; */
1263 if (!strchr(esc, ';'))
1264 break;
1265
1266 while (*esc) {
1267 if (*esc == 'x') {
1268 esc++;
1269 if (kstrtoul(esc, 10, &lcd.addr.x) < 0)
1270 break;
1271 } else if (*esc == 'y') {
1272 esc++;
1273 if (kstrtoul(esc, 10, &lcd.addr.y) < 0)
1274 break;
1275 } else {
1276 break;
1277 }
1278 }
1279
1280 lcd_gotoxy();
1281 processed = 1;
1282 break;
1283 }
1284
1285 /* TODO: This indent party here got ugly, clean it! */
1286 /* Check whether one flag was changed */
1287 if (oldflags != lcd.flags) {
1288 /* check whether one of B,C,D flags were changed */
1289 if ((oldflags ^ lcd.flags) &
1290 (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
1291 /* set display mode */
1292 lcd_write_cmd(LCD_CMD_DISPLAY_CTRL
1293 | ((lcd.flags & LCD_FLAG_D)
1294 ? LCD_CMD_DISPLAY_ON : 0)
1295 | ((lcd.flags & LCD_FLAG_C)
1296 ? LCD_CMD_CURSOR_ON : 0)
1297 | ((lcd.flags & LCD_FLAG_B)
1298 ? LCD_CMD_BLINK_ON : 0));
1299 /* check whether one of F,N flags was changed */
1300 else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N))
1301 lcd_write_cmd(LCD_CMD_FUNCTION_SET
1302 | LCD_CMD_DATA_LEN_8BITS
1303 | ((lcd.flags & LCD_FLAG_F)
1304 ? LCD_CMD_FONT_5X10_DOTS
1305 : 0)
1306 | ((lcd.flags & LCD_FLAG_N)
1307 ? LCD_CMD_TWO_LINES
1308 : 0));
1309 /* check whether L flag was changed */
1310 else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L))
1311 lcd_backlight(!!(lcd.flags & LCD_FLAG_L));
1312 }
1313
1314 return processed;
1315}
1316
1317static void lcd_write_char(char c)
1318{
1319 /* first, we'll test if we're in escape mode */
1320 if ((c != '\n') && lcd.esc_seq.len >= 0) {
1321 /* yes, let's add this char to the buffer */
1322 lcd.esc_seq.buf[lcd.esc_seq.len++] = c;
1323 lcd.esc_seq.buf[lcd.esc_seq.len] = 0;
1324 } else {
1325 /* aborts any previous escape sequence */
1326 lcd.esc_seq.len = -1;
1327
1328 switch (c) {
1329 case LCD_ESCAPE_CHAR:
1330 /* start of an escape sequence */
1331 lcd.esc_seq.len = 0;
1332 lcd.esc_seq.buf[lcd.esc_seq.len] = 0;
1333 break;
1334 case '\b':
1335 /* go back one char and clear it */
1336 if (lcd.addr.x > 0) {
1337 /*
1338 * check if we're not at the
1339 * end of the line
1340 */
1341 if (lcd.addr.x < lcd.bwidth)
1342 /* back one char */
1343 lcd_write_cmd(LCD_CMD_SHIFT);
1344 lcd.addr.x--;
1345 }
1346 /* replace with a space */
1347 lcd_write_data(' ');
1348 /* back one char again */
1349 lcd_write_cmd(LCD_CMD_SHIFT);
1350 break;
1351 case '\014':
1352 /* quickly clear the display */
1353 lcd_clear_fast();
1354 break;
1355 case '\n':
1356 /*
1357 * flush the remainder of the current line and
1358 * go to the beginning of the next line
1359 */
1360 for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++)
1361 lcd_write_data(' ');
1362 lcd.addr.x = 0;
1363 lcd.addr.y = (lcd.addr.y + 1) % lcd.height;
1364 lcd_gotoxy();
1365 break;
1366 case '\r':
1367 /* go to the beginning of the same line */
1368 lcd.addr.x = 0;
1369 lcd_gotoxy();
1370 break;
1371 case '\t':
1372 /* print a space instead of the tab */
1373 lcd_print(' ');
1374 break;
1375 default:
1376 /* simply print this char */
1377 lcd_print(c);
1378 break;
1379 }
1380 }
1381 909
1382 /* 910 /*
1383 * now we'll see if we're in an escape mode and if the current 911 * Init lcd struct with load-time values to preserve exact
1384 * escape sequence can be understood. 912 * current functionality (at least for now).
1385 */ 913 */
1386 if (lcd.esc_seq.len >= 2) { 914 charlcd->height = lcd_height;
1387 int processed = 0; 915 charlcd->width = lcd_width;
1388 916 charlcd->bwidth = lcd_bwidth;
1389 if (!strcmp(lcd.esc_seq.buf, "[2J")) { 917 charlcd->hwidth = lcd_hwidth;
1390 /* clear the display */
1391 lcd_clear_fast();
1392 processed = 1;
1393 } else if (!strcmp(lcd.esc_seq.buf, "[H")) {
1394 /* cursor to home */
1395 lcd_home();
1396 processed = 1;
1397 }
1398 /* codes starting with ^[[L */
1399 else if ((lcd.esc_seq.len >= 3) &&
1400 (lcd.esc_seq.buf[0] == '[') &&
1401 (lcd.esc_seq.buf[1] == 'L')) {
1402 processed = handle_lcd_special_code();
1403 }
1404
1405 /* LCD special escape codes */
1406 /*
1407 * flush the escape sequence if it's been processed
1408 * or if it is getting too long.
1409 */
1410 if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN))
1411 lcd.esc_seq.len = -1;
1412 } /* escape codes */
1413}
1414 918
1415static ssize_t lcd_write(struct file *file,
1416 const char __user *buf, size_t count, loff_t *ppos)
1417{
1418 const char __user *tmp = buf;
1419 char c;
1420
1421 for (; count-- > 0; (*ppos)++, tmp++) {
1422 if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
1423 /*
1424 * let's be a little nice with other processes
1425 * that need some CPU
1426 */
1427 schedule();
1428
1429 if (get_user(c, tmp))
1430 return -EFAULT;
1431
1432 lcd_write_char(c);
1433 }
1434
1435 return tmp - buf;
1436}
1437
1438static int lcd_open(struct inode *inode, struct file *file)
1439{
1440 if (!atomic_dec_and_test(&lcd_available))
1441 return -EBUSY; /* open only once at a time */
1442
1443 if (file->f_mode & FMODE_READ) /* device is write-only */
1444 return -EPERM;
1445
1446 if (lcd.must_clear) {
1447 lcd_clear_display();
1448 lcd.must_clear = false;
1449 }
1450 return nonseekable_open(inode, file);
1451}
1452
1453static int lcd_release(struct inode *inode, struct file *file)
1454{
1455 atomic_inc(&lcd_available);
1456 return 0;
1457}
1458
1459static const struct file_operations lcd_fops = {
1460 .write = lcd_write,
1461 .open = lcd_open,
1462 .release = lcd_release,
1463 .llseek = no_llseek,
1464};
1465
1466static struct miscdevice lcd_dev = {
1467 .minor = LCD_MINOR,
1468 .name = "lcd",
1469 .fops = &lcd_fops,
1470};
1471
1472/* public function usable from the kernel for any purpose */
1473static void panel_lcd_print(const char *s)
1474{
1475 const char *tmp = s;
1476 int count = strlen(s);
1477
1478 if (lcd.enabled && lcd.initialized) {
1479 for (; count-- > 0; tmp++) {
1480 if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
1481 /*
1482 * let's be a little nice with other processes
1483 * that need some CPU
1484 */
1485 schedule();
1486
1487 lcd_write_char(*tmp);
1488 }
1489 }
1490}
1491
1492/* initialize the LCD driver */
1493static void lcd_init(void)
1494{
1495 switch (selected_lcd_type) { 919 switch (selected_lcd_type) {
1496 case LCD_TYPE_OLD: 920 case LCD_TYPE_OLD:
1497 /* parallel mode, 8 bits */ 921 /* parallel mode, 8 bits */
@@ -1500,10 +924,10 @@ static void lcd_init(void)
1500 lcd.pins.e = PIN_STROBE; 924 lcd.pins.e = PIN_STROBE;
1501 lcd.pins.rs = PIN_AUTOLF; 925 lcd.pins.rs = PIN_AUTOLF;
1502 926
1503 lcd.width = 40; 927 charlcd->width = 40;
1504 lcd.bwidth = 40; 928 charlcd->bwidth = 40;
1505 lcd.hwidth = 64; 929 charlcd->hwidth = 64;
1506 lcd.height = 2; 930 charlcd->height = 2;
1507 break; 931 break;
1508 case LCD_TYPE_KS0074: 932 case LCD_TYPE_KS0074:
1509 /* serial mode, ks0074 */ 933 /* serial mode, ks0074 */
@@ -1513,10 +937,10 @@ static void lcd_init(void)
1513 lcd.pins.cl = PIN_STROBE; 937 lcd.pins.cl = PIN_STROBE;
1514 lcd.pins.da = PIN_D0; 938 lcd.pins.da = PIN_D0;
1515 939
1516 lcd.width = 16; 940 charlcd->width = 16;
1517 lcd.bwidth = 40; 941 charlcd->bwidth = 40;
1518 lcd.hwidth = 16; 942 charlcd->hwidth = 16;
1519 lcd.height = 2; 943 charlcd->height = 2;
1520 break; 944 break;
1521 case LCD_TYPE_NEXCOM: 945 case LCD_TYPE_NEXCOM:
1522 /* parallel mode, 8 bits, generic */ 946 /* parallel mode, 8 bits, generic */
@@ -1526,10 +950,10 @@ static void lcd_init(void)
1526 lcd.pins.rs = PIN_SELECP; 950 lcd.pins.rs = PIN_SELECP;
1527 lcd.pins.rw = PIN_INITP; 951 lcd.pins.rw = PIN_INITP;
1528 952
1529 lcd.width = 16; 953 charlcd->width = 16;
1530 lcd.bwidth = 40; 954 charlcd->bwidth = 40;
1531 lcd.hwidth = 64; 955 charlcd->hwidth = 64;
1532 lcd.height = 2; 956 charlcd->height = 2;
1533 break; 957 break;
1534 case LCD_TYPE_CUSTOM: 958 case LCD_TYPE_CUSTOM:
1535 /* customer-defined */ 959 /* customer-defined */
@@ -1545,22 +969,22 @@ static void lcd_init(void)
1545 lcd.pins.e = PIN_STROBE; 969 lcd.pins.e = PIN_STROBE;
1546 lcd.pins.rs = PIN_SELECP; 970 lcd.pins.rs = PIN_SELECP;
1547 971
1548 lcd.width = 16; 972 charlcd->width = 16;
1549 lcd.bwidth = 40; 973 charlcd->bwidth = 40;
1550 lcd.hwidth = 64; 974 charlcd->hwidth = 64;
1551 lcd.height = 2; 975 charlcd->height = 2;
1552 break; 976 break;
1553 } 977 }
1554 978
1555 /* Overwrite with module params set on loading */ 979 /* Overwrite with module params set on loading */
1556 if (lcd_height != NOT_SET) 980 if (lcd_height != NOT_SET)
1557 lcd.height = lcd_height; 981 charlcd->height = lcd_height;
1558 if (lcd_width != NOT_SET) 982 if (lcd_width != NOT_SET)
1559 lcd.width = lcd_width; 983 charlcd->width = lcd_width;
1560 if (lcd_bwidth != NOT_SET) 984 if (lcd_bwidth != NOT_SET)
1561 lcd.bwidth = lcd_bwidth; 985 charlcd->bwidth = lcd_bwidth;
1562 if (lcd_hwidth != NOT_SET) 986 if (lcd_hwidth != NOT_SET)
1563 lcd.hwidth = lcd_hwidth; 987 charlcd->hwidth = lcd_hwidth;
1564 if (lcd_charset != NOT_SET) 988 if (lcd_charset != NOT_SET)
1565 lcd.charset = lcd_charset; 989 lcd.charset = lcd_charset;
1566 if (lcd_proto != NOT_SET) 990 if (lcd_proto != NOT_SET)
@@ -1579,19 +1003,17 @@ static void lcd_init(void)
1579 lcd.pins.bl = lcd_bl_pin; 1003 lcd.pins.bl = lcd_bl_pin;
1580 1004
1581 /* this is used to catch wrong and default values */ 1005 /* this is used to catch wrong and default values */
1582 if (lcd.width <= 0) 1006 if (charlcd->width <= 0)
1583 lcd.width = DEFAULT_LCD_WIDTH; 1007 charlcd->width = DEFAULT_LCD_WIDTH;
1584 if (lcd.bwidth <= 0) 1008 if (charlcd->bwidth <= 0)
1585 lcd.bwidth = DEFAULT_LCD_BWIDTH; 1009 charlcd->bwidth = DEFAULT_LCD_BWIDTH;
1586 if (lcd.hwidth <= 0) 1010 if (charlcd->hwidth <= 0)
1587 lcd.hwidth = DEFAULT_LCD_HWIDTH; 1011 charlcd->hwidth = DEFAULT_LCD_HWIDTH;
1588 if (lcd.height <= 0) 1012 if (charlcd->height <= 0)
1589 lcd.height = DEFAULT_LCD_HEIGHT; 1013 charlcd->height = DEFAULT_LCD_HEIGHT;
1590 1014
1591 if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ 1015 if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */
1592 lcd_write_cmd = lcd_write_cmd_s; 1016 charlcd->ops = &charlcd_serial_ops;
1593 lcd_write_data = lcd_write_data_s;
1594 lcd_clear_fast = lcd_clear_fast_s;
1595 1017
1596 if (lcd.pins.cl == PIN_NOT_SET) 1018 if (lcd.pins.cl == PIN_NOT_SET)
1597 lcd.pins.cl = DEFAULT_LCD_PIN_SCL; 1019 lcd.pins.cl = DEFAULT_LCD_PIN_SCL;
@@ -1599,9 +1021,7 @@ static void lcd_init(void)
1599 lcd.pins.da = DEFAULT_LCD_PIN_SDA; 1021 lcd.pins.da = DEFAULT_LCD_PIN_SDA;
1600 1022
1601 } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ 1023 } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */
1602 lcd_write_cmd = lcd_write_cmd_p8; 1024 charlcd->ops = &charlcd_parallel_ops;
1603 lcd_write_data = lcd_write_data_p8;
1604 lcd_clear_fast = lcd_clear_fast_p8;
1605 1025
1606 if (lcd.pins.e == PIN_NOT_SET) 1026 if (lcd.pins.e == PIN_NOT_SET)
1607 lcd.pins.e = DEFAULT_LCD_PIN_E; 1027 lcd.pins.e = DEFAULT_LCD_PIN_E;
@@ -1610,9 +1030,7 @@ static void lcd_init(void)
1610 if (lcd.pins.rw == PIN_NOT_SET) 1030 if (lcd.pins.rw == PIN_NOT_SET)
1611 lcd.pins.rw = DEFAULT_LCD_PIN_RW; 1031 lcd.pins.rw = DEFAULT_LCD_PIN_RW;
1612 } else { 1032 } else {
1613 lcd_write_cmd = lcd_write_cmd_tilcd; 1033 charlcd->ops = &charlcd_tilcd_ops;
1614 lcd_write_data = lcd_write_data_tilcd;
1615 lcd_clear_fast = lcd_clear_fast_tilcd;
1616 } 1034 }
1617 1035
1618 if (lcd.pins.bl == PIN_NOT_SET) 1036 if (lcd.pins.bl == PIN_NOT_SET)
@@ -1635,14 +1053,9 @@ static void lcd_init(void)
1635 lcd.charset = DEFAULT_LCD_CHARSET; 1053 lcd.charset = DEFAULT_LCD_CHARSET;
1636 1054
1637 if (lcd.charset == LCD_CHARSET_KS0074) 1055 if (lcd.charset == LCD_CHARSET_KS0074)
1638 lcd_char_conv = lcd_char_conv_ks0074; 1056 charlcd->char_conv = lcd_char_conv_ks0074;
1639 else 1057 else
1640 lcd_char_conv = NULL; 1058 charlcd->char_conv = NULL;
1641
1642 if (lcd.pins.bl != PIN_NONE) {
1643 mutex_init(&lcd.bl_tempo_lock);
1644 INIT_DELAYED_WORK(&lcd.bl_work, lcd_bl_off);
1645 }
1646 1059
1647 pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], 1060 pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E],
1648 lcd_bits[LCD_PORT_C][LCD_BIT_E]); 1061 lcd_bits[LCD_PORT_C][LCD_BIT_E]);
@@ -1657,25 +1070,8 @@ static void lcd_init(void)
1657 pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], 1070 pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA],
1658 lcd_bits[LCD_PORT_C][LCD_BIT_DA]); 1071 lcd_bits[LCD_PORT_C][LCD_BIT_DA]);
1659 1072
1660 /* 1073 lcd.charlcd = charlcd;
1661 * before this line, we must NOT send anything to the display.
1662 * Since lcd_init_display() needs to write data, we have to
1663 * enable mark the LCD initialized just before.
1664 */
1665 lcd.initialized = true; 1074 lcd.initialized = true;
1666 lcd_init_display();
1667
1668 /* display a short message */
1669#ifdef CONFIG_PANEL_CHANGE_MESSAGE
1670#ifdef CONFIG_PANEL_BOOT_MESSAGE
1671 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
1672#endif
1673#else
1674 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE);
1675#endif
1676 /* clear the display on the next device opening */
1677 lcd.must_clear = true;
1678 lcd_home();
1679} 1075}
1680 1076
1681/* 1077/*
@@ -2011,7 +1407,7 @@ static void panel_scan_timer(void)
2011 } 1407 }
2012 1408
2013 if (keypressed && lcd.enabled && lcd.initialized) 1409 if (keypressed && lcd.enabled && lcd.initialized)
2014 lcd_poke(); 1410 charlcd_poke(lcd.charlcd);
2015 1411
2016 mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); 1412 mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
2017} 1413}
@@ -2175,35 +1571,6 @@ static void keypad_init(void)
2175/* device initialization */ 1571/* device initialization */
2176/**************************************************/ 1572/**************************************************/
2177 1573
2178static int panel_notify_sys(struct notifier_block *this, unsigned long code,
2179 void *unused)
2180{
2181 if (lcd.enabled && lcd.initialized) {
2182 switch (code) {
2183 case SYS_DOWN:
2184 panel_lcd_print
2185 ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
2186 break;
2187 case SYS_HALT:
2188 panel_lcd_print
2189 ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
2190 break;
2191 case SYS_POWER_OFF:
2192 panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
2193 break;
2194 default:
2195 break;
2196 }
2197 }
2198 return NOTIFY_DONE;
2199}
2200
2201static struct notifier_block panel_notifier = {
2202 panel_notify_sys,
2203 NULL,
2204 0
2205};
2206
2207static void panel_attach(struct parport *port) 1574static void panel_attach(struct parport *port)
2208{ 1575{
2209 struct pardev_cb panel_cb; 1576 struct pardev_cb panel_cb;
@@ -2239,7 +1606,7 @@ static void panel_attach(struct parport *port)
2239 */ 1606 */
2240 if (lcd.enabled) { 1607 if (lcd.enabled) {
2241 lcd_init(); 1608 lcd_init();
2242 if (misc_register(&lcd_dev)) 1609 if (!lcd.charlcd || charlcd_register(lcd.charlcd))
2243 goto err_unreg_device; 1610 goto err_unreg_device;
2244 } 1611 }
2245 1612
@@ -2248,13 +1615,14 @@ static void panel_attach(struct parport *port)
2248 if (misc_register(&keypad_dev)) 1615 if (misc_register(&keypad_dev))
2249 goto err_lcd_unreg; 1616 goto err_lcd_unreg;
2250 } 1617 }
2251 register_reboot_notifier(&panel_notifier);
2252 return; 1618 return;
2253 1619
2254err_lcd_unreg: 1620err_lcd_unreg:
2255 if (lcd.enabled) 1621 if (lcd.enabled)
2256 misc_deregister(&lcd_dev); 1622 charlcd_unregister(lcd.charlcd);
2257err_unreg_device: 1623err_unreg_device:
1624 kfree(lcd.charlcd);
1625 lcd.charlcd = NULL;
2258 parport_unregister_device(pprt); 1626 parport_unregister_device(pprt);
2259 pprt = NULL; 1627 pprt = NULL;
2260} 1628}
@@ -2278,20 +1646,16 @@ static void panel_detach(struct parport *port)
2278 } 1646 }
2279 1647
2280 if (lcd.enabled) { 1648 if (lcd.enabled) {
2281 panel_lcd_print("\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-"); 1649 charlcd_unregister(lcd.charlcd);
2282 misc_deregister(&lcd_dev);
2283 if (lcd.pins.bl != PIN_NONE) {
2284 cancel_delayed_work_sync(&lcd.bl_work);
2285 __lcd_backlight(0);
2286 }
2287 lcd.initialized = false; 1650 lcd.initialized = false;
1651 kfree(lcd.charlcd);
1652 lcd.charlcd = NULL;
2288 } 1653 }
2289 1654
2290 /* TODO: free all input signals */ 1655 /* TODO: free all input signals */
2291 parport_release(pprt); 1656 parport_release(pprt);
2292 parport_unregister_device(pprt); 1657 parport_unregister_device(pprt);
2293 pprt = NULL; 1658 pprt = NULL;
2294 unregister_reboot_notifier(&panel_notifier);
2295} 1659}
2296 1660
2297static struct parport_driver panel_driver = { 1661static struct parport_driver panel_driver = {
@@ -2369,10 +1733,6 @@ static int __init panel_init_module(void)
2369 * Init lcd struct with load-time values to preserve exact 1733 * Init lcd struct with load-time values to preserve exact
2370 * current functionality (at least for now). 1734 * current functionality (at least for now).
2371 */ 1735 */
2372 lcd.height = lcd_height;
2373 lcd.width = lcd_width;
2374 lcd.bwidth = lcd_bwidth;
2375 lcd.hwidth = lcd_hwidth;
2376 lcd.charset = lcd_charset; 1736 lcd.charset = lcd_charset;
2377 lcd.proto = lcd_proto; 1737 lcd.proto = lcd_proto;
2378 lcd.pins.e = lcd_e_pin; 1738 lcd.pins.e = lcd_e_pin;
@@ -2381,9 +1741,6 @@ static int __init panel_init_module(void)
2381 lcd.pins.cl = lcd_cl_pin; 1741 lcd.pins.cl = lcd_cl_pin;
2382 lcd.pins.da = lcd_da_pin; 1742 lcd.pins.da = lcd_da_pin;
2383 lcd.pins.bl = lcd_bl_pin; 1743 lcd.pins.bl = lcd_bl_pin;
2384
2385 /* Leave it for now, just in case */
2386 lcd.esc_seq.len = -1;
2387 } 1744 }
2388 1745
2389 switch (selected_keypad_type) { 1746 switch (selected_keypad_type) {