aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/panel/panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/panel/panel.c')
-rw-r--r--drivers/staging/panel/panel.c310
1 files changed, 177 insertions, 133 deletions
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 08f9a4896116..4e9229363c36 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -462,7 +462,7 @@ MODULE_PARM_DESC(lcd_type,
static int lcd_proto = -1;
module_param(lcd_proto, int, 0000);
MODULE_PARM_DESC(lcd_proto,
- "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
+ "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
static int lcd_charset = -1;
module_param(lcd_charset, int, 0000);
@@ -664,8 +664,12 @@ static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
{
int d_bit, c_bit, inv;
- d_val[0] = c_val[0] = d_val[1] = c_val[1] = 0;
- d_val[2] = c_val[2] = 0xFF;
+ d_val[0] = 0;
+ c_val[0] = 0;
+ d_val[1] = 0;
+ c_val[1] = 0;
+ d_val[2] = 0xFF;
+ c_val[2] = 0xFF;
if (pin == 0)
return;
@@ -674,7 +678,8 @@ static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
if (inv)
pin = -pin;
- d_bit = c_bit = 0;
+ d_bit = 0;
+ c_bit = 0;
switch (pin) {
case PIN_STROBE: /* strobe, inverted */
@@ -711,10 +716,9 @@ static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
/* sleeps that many milliseconds with a reschedule */
static void long_sleep(int ms)
{
-
- if (in_interrupt())
+ if (in_interrupt()) {
mdelay(ms);
- else {
+ } else {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout((ms * HZ + 999) / 1000);
}
@@ -867,7 +871,9 @@ static void lcd_print(char c)
static void lcd_clear_fast_s(void)
{
int pos;
- lcd_addr_x = lcd_addr_y = 0;
+
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
spin_lock_irq(&pprt_lock);
@@ -879,7 +885,8 @@ static void lcd_clear_fast_s(void)
}
spin_unlock_irq(&pprt_lock);
- lcd_addr_x = lcd_addr_y = 0;
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
}
@@ -887,7 +894,9 @@ static void lcd_clear_fast_s(void)
static void lcd_clear_fast_p8(void)
{
int pos;
- lcd_addr_x = lcd_addr_y = 0;
+
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
spin_lock_irq(&pprt_lock);
@@ -914,7 +923,8 @@ static void lcd_clear_fast_p8(void)
}
spin_unlock_irq(&pprt_lock);
- lcd_addr_x = lcd_addr_y = 0;
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
}
@@ -922,7 +932,9 @@ static void lcd_clear_fast_p8(void)
static void lcd_clear_fast_tilcd(void)
{
int pos;
- lcd_addr_x = lcd_addr_y = 0;
+
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
spin_lock_irq(&pprt_lock);
@@ -934,7 +946,8 @@ static void lcd_clear_fast_tilcd(void)
spin_unlock_irq(&pprt_lock);
- lcd_addr_x = lcd_addr_y = 0;
+ lcd_addr_x = 0;
+ lcd_addr_y = 0;
lcd_gotoxy();
}
@@ -942,14 +955,14 @@ static void lcd_clear_fast_tilcd(void)
static void lcd_clear_display(void)
{
lcd_write_cmd(0x01); /* clear display */
- lcd_addr_x = 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_FLAG_D | LCD_FLAG_C | LCD_FLAG_B;
@@ -1092,6 +1105,7 @@ static inline int handle_lcd_special_code(void)
break;
case 'k': { /* kill end of line */
int x;
+
for (x = lcd_addr_x; x < lcd_bwidth; x++)
lcd_write_data(' ');
@@ -1137,13 +1151,13 @@ static inline int handle_lcd_special_code(void)
value = 0;
while (*esc && cgoffset < 8) {
shift ^= 4;
- if (*esc >= '0' && *esc <= '9')
+ if (*esc >= '0' && *esc <= '9') {
value |= (*esc - '0') << shift;
- else if (*esc >= 'A' && *esc <= 'Z')
+ } else if (*esc >= 'A' && *esc <= 'Z') {
value |= (*esc - 'A' + 10) << shift;
- else if (*esc >= 'a' && *esc <= 'z')
+ } else if (*esc >= 'a' && *esc <= 'z') {
value |= (*esc - 'a' + 10) << shift;
- else {
+ } else {
esc++;
continue;
}
@@ -1179,8 +1193,9 @@ static inline int handle_lcd_special_code(void)
esc++;
if (kstrtoul(esc, 10, &lcd_addr_y) < 0)
break;
- } else
+ } else {
break;
+ }
}
lcd_gotoxy();
@@ -1217,111 +1232,114 @@ static inline int handle_lcd_special_code(void)
return processed;
}
+static void lcd_write_char(char c)
+{
+ /* first, we'll test if we're in escape mode */
+ if ((c != '\n') && lcd_escape_len >= 0) {
+ /* yes, let's add this char to the buffer */
+ lcd_escape[lcd_escape_len++] = c;
+ lcd_escape[lcd_escape_len] = 0;
+ } else {
+ /* aborts any previous escape sequence */
+ lcd_escape_len = -1;
+
+ switch (c) {
+ case LCD_ESCAPE_CHAR:
+ /* start of an escape sequence */
+ lcd_escape_len = 0;
+ lcd_escape[lcd_escape_len] = 0;
+ break;
+ case '\b':
+ /* go back one char and clear it */
+ if (lcd_addr_x > 0) {
+ /* check if we're not at the
+ end of the line */
+ if (lcd_addr_x < lcd_bwidth)
+ /* back one char */
+ lcd_write_cmd(0x10);
+ lcd_addr_x--;
+ }
+ /* replace with a space */
+ lcd_write_data(' ');
+ /* back one char again */
+ lcd_write_cmd(0x10);
+ break;
+ case '\014':
+ /* quickly clear the display */
+ lcd_clear_fast();
+ break;
+ 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++)
+ lcd_write_data(' ');
+ 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_gotoxy();
+ break;
+ case '\t':
+ /* print a space instead of the tab */
+ lcd_print(' ');
+ break;
+ default:
+ /* simply print this char */
+ lcd_print(c);
+ break;
+ }
+ }
+
+ /* 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) {
+ int processed = 0;
+
+ if (!strcmp(lcd_escape, "[2J")) {
+ /* clear the display */
+ lcd_clear_fast();
+ processed = 1;
+ } else if (!strcmp(lcd_escape, "[H")) {
+ /* cursor to home */
+ 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')) {
+ 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;
+ } /* escape codes */
+}
+
static ssize_t lcd_write(struct file *file,
- const char *buf, size_t count, loff_t *ppos)
+ const char __user *buf, size_t count, loff_t *ppos)
{
- const char *tmp = buf;
+ const char __user *tmp = buf;
char c;
- for (; count-- > 0; (ppos ? (*ppos)++ : 0), ++tmp) {
+ for (; count-- > 0; (*ppos)++, tmp++) {
if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
/* let's be a little nice with other processes
that need some CPU */
schedule();
- if (ppos == NULL && file == NULL)
- /* let's not use get_user() from the kernel ! */
- c = *tmp;
- else if (get_user(c, tmp))
+ if (get_user(c, tmp))
return -EFAULT;
- /* first, we'll test if we're in escape mode */
- if ((c != '\n') && lcd_escape_len >= 0) {
- /* yes, let's add this char to the buffer */
- lcd_escape[lcd_escape_len++] = c;
- lcd_escape[lcd_escape_len] = 0;
- } else {
- /* aborts any previous escape sequence */
- lcd_escape_len = -1;
-
- switch (c) {
- case LCD_ESCAPE_CHAR:
- /* start of an escape sequence */
- lcd_escape_len = 0;
- lcd_escape[lcd_escape_len] = 0;
- break;
- case '\b':
- /* go back one char and clear it */
- if (lcd_addr_x > 0) {
- /* check if we're not at the
- end of the line */
- if (lcd_addr_x < lcd_bwidth)
- /* back one char */
- lcd_write_cmd(0x10);
- lcd_addr_x--;
- }
- /* replace with a space */
- lcd_write_data(' ');
- /* back one char again */
- lcd_write_cmd(0x10);
- break;
- case '\014':
- /* quickly clear the display */
- lcd_clear_fast();
- break;
- 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++)
- lcd_write_data(' ');
- 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_gotoxy();
- break;
- case '\t':
- /* print a space instead of the tab */
- lcd_print(' ');
- break;
- default:
- /* simply print this char */
- lcd_print(c);
- break;
- }
- }
-
- /* 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) {
- int processed = 0;
-
- if (!strcmp(lcd_escape, "[2J")) {
- /* clear the display */
- lcd_clear_fast();
- processed = 1;
- } else if (!strcmp(lcd_escape, "[H")) {
- /* cursor to home */
- lcd_addr_x = 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')) {
- 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;
- } /* escape codes */
+ lcd_write_char(c);
}
return tmp - buf;
@@ -1365,8 +1383,19 @@ static struct miscdevice lcd_dev = {
/* public function usable from the kernel for any purpose */
static void panel_lcd_print(const char *s)
{
- if (lcd_enabled && lcd_initialized)
- lcd_write(NULL, s, strlen(s), NULL);
+ const char *tmp = s;
+ int count = strlen(s);
+
+ 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
+ that need some CPU */
+ schedule();
+
+ lcd_write_char(*tmp);
+ }
+ }
}
/* initialize the LCD driver */
@@ -1560,7 +1589,8 @@ static void lcd_init(void)
panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-"
PANEL_VERSION);
#endif
- lcd_addr_x = 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_gotoxy();
@@ -1571,11 +1601,10 @@ static void lcd_init(void)
*/
static ssize_t keypad_read(struct file *file,
- char *buf, size_t count, loff_t *ppos)
+ char __user *buf, size_t count, loff_t *ppos)
{
-
unsigned i = *ppos;
- char *tmp = buf;
+ char __user *tmp = buf;
if (keypad_buflen == 0) {
if (file->f_flags & O_NONBLOCK)
@@ -1598,7 +1627,6 @@ static ssize_t keypad_read(struct file *file,
static int keypad_open(struct inode *inode, struct file *file)
{
-
if (keypad_open_cnt)
return -EBUSY; /* open only once at a time */
@@ -1728,8 +1756,8 @@ static inline int input_state_high(struct logical_input *input)
* release function.
* eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release.
*/
- if (((phys_prev & input->mask) == input->value)
- && ((phys_curr & input->mask) > input->value)) {
+ if (((phys_prev & input->mask) == input->value) &&
+ ((phys_curr & input->mask) > input->value)) {
input->state = INPUT_ST_LOW; /* invalidate */
return 1;
}
@@ -1747,16 +1775,20 @@ static inline int input_state_high(struct logical_input *input)
if (input->high_timer == 0) {
char *press_str = input->u.kbd.press_str;
+
if (press_str[0]) {
int s = sizeof(input->u.kbd.press_str);
+
keypad_send_key(press_str, s);
}
}
if (input->u.kbd.repeat_str[0]) {
char *repeat_str = input->u.kbd.repeat_str;
+
if (input->high_timer >= KEYPAD_REP_START) {
int s = sizeof(input->u.kbd.repeat_str);
+
input->high_timer -= KEYPAD_REP_DELAY;
keypad_send_key(repeat_str, s);
}
@@ -1780,8 +1812,8 @@ static inline void input_state_falling(struct logical_input *input)
{
#if 0
/* FIXME !!! same comment as in input_state_high */
- if (((phys_prev & input->mask) == input->value)
- && ((phys_curr & input->mask) > input->value)) {
+ if (((phys_prev & input->mask) == input->value) &&
+ ((phys_curr & input->mask) > input->value)) {
input->state = INPUT_ST_LOW; /* invalidate */
return;
}
@@ -1794,8 +1826,10 @@ static inline void input_state_falling(struct logical_input *input)
if (input->u.kbd.repeat_str[0]) {
char *repeat_str = input->u.kbd.repeat_str;
+
if (input->high_timer >= KEYPAD_REP_START) {
int s = sizeof(input->u.kbd.repeat_str);
+
input->high_timer -= KEYPAD_REP_DELAY;
keypad_send_key(repeat_str, s);
}
@@ -1811,12 +1845,15 @@ static inline void input_state_falling(struct logical_input *input)
/* call release event */
if (input->type == INPUT_TYPE_STD) {
void (*release_fct)(int) = input->u.std.release_fct;
+
if (release_fct != NULL)
release_fct(input->u.std.release_data);
} else if (input->type == INPUT_TYPE_KBD) {
char *release_str = input->u.kbd.release_str;
+
if (release_str[0]) {
int s = sizeof(input->u.kbd.release_str);
+
keypad_send_key(release_str, s);
}
}
@@ -1930,12 +1967,17 @@ static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value,
char im, om;
pmask_t m, v;
- om = im = m = v = 0ULL;
+ om = 0ULL;
+ im = 0ULL;
+ m = 0ULL;
+ v = 0ULL;
while (*name) {
int in, out, bit, neg;
- for (in = 0; (in < sizeof(sigtab)) &&
- (sigtab[in] != *name); in++)
+
+ for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name);
+ in++)
;
+
if (in >= sizeof(sigtab))
return 0; /* input name not found */
neg = (in & 1); /* odd (lower) names are negated */
@@ -1946,10 +1988,11 @@ static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value,
if (isdigit(*name)) {
out = *name - '0';
om |= (1 << out);
- } else if (*name == '-')
+ } else if (*name == '-') {
out = 8;
- else
+ } else {
return 0; /* unknown bit name */
+ }
bit = (out * 5) + in;
@@ -1977,7 +2020,7 @@ static struct logical_input *panel_bind_key(const char *name, const char *press,
{
struct logical_input *key;
- key = kzalloc(sizeof(struct logical_input), GFP_KERNEL);
+ key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key)
return NULL;
@@ -2015,7 +2058,7 @@ static struct logical_input *panel_bind_callback(char *name,
{
struct logical_input *callback;
- callback = kmalloc(sizeof(struct logical_input), GFP_KERNEL);
+ callback = kmalloc(sizeof(*callback), GFP_KERNEL);
if (!callback)
return NULL;
@@ -2040,6 +2083,7 @@ static struct logical_input *panel_bind_callback(char *name,
static void keypad_init(void)
{
int keynum;
+
init_waitqueue_head(&keypad_read_wait);
keypad_buflen = 0; /* flushes any eventual noisy keystroke */
@@ -2298,7 +2342,7 @@ static void __exit panel_cleanup_module(void)
unregister_reboot_notifier(&panel_notifier);
if (scan_timer.function != NULL)
- del_timer(&scan_timer);
+ del_timer_sync(&scan_timer);
if (pprt != NULL) {
if (keypad_enabled) {