.. | .. |
---|
20 | 20 | |
---|
21 | 21 | #include <generated/utsrelease.h> |
---|
22 | 22 | |
---|
23 | | -#include <misc/charlcd.h> |
---|
24 | | - |
---|
25 | | -#define LCD_MINOR 156 |
---|
| 23 | +#include "charlcd.h" |
---|
26 | 24 | |
---|
27 | 25 | #define DEFAULT_LCD_BWIDTH 40 |
---|
28 | 26 | #define DEFAULT_LCD_HWIDTH 64 |
---|
.. | .. |
---|
88 | 86 | int len; |
---|
89 | 87 | } esc_seq; |
---|
90 | 88 | |
---|
91 | | - unsigned long long drvdata[0]; |
---|
| 89 | + unsigned long long drvdata[]; |
---|
92 | 90 | }; |
---|
93 | 91 | |
---|
94 | | -#define to_priv(p) container_of(p, struct charlcd_priv, lcd) |
---|
| 92 | +#define charlcd_to_priv(p) container_of(p, struct charlcd_priv, lcd) |
---|
95 | 93 | |
---|
96 | 94 | /* Device single-open policy control */ |
---|
97 | 95 | static atomic_t charlcd_available = ATOMIC_INIT(1); |
---|
.. | .. |
---|
105 | 103 | /* turn the backlight on or off */ |
---|
106 | 104 | static void charlcd_backlight(struct charlcd *lcd, int on) |
---|
107 | 105 | { |
---|
108 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 106 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
109 | 107 | |
---|
110 | 108 | if (!lcd->ops->backlight) |
---|
111 | 109 | return; |
---|
.. | .. |
---|
134 | 132 | /* turn the backlight on for a little while */ |
---|
135 | 133 | void charlcd_poke(struct charlcd *lcd) |
---|
136 | 134 | { |
---|
137 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 135 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
138 | 136 | |
---|
139 | 137 | if (!lcd->ops->backlight) |
---|
140 | 138 | return; |
---|
.. | .. |
---|
152 | 150 | |
---|
153 | 151 | static void charlcd_gotoxy(struct charlcd *lcd) |
---|
154 | 152 | { |
---|
155 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 153 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
156 | 154 | unsigned int addr; |
---|
157 | 155 | |
---|
158 | 156 | /* |
---|
.. | .. |
---|
170 | 168 | |
---|
171 | 169 | static void charlcd_home(struct charlcd *lcd) |
---|
172 | 170 | { |
---|
173 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 171 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
174 | 172 | |
---|
175 | 173 | priv->addr.x = 0; |
---|
176 | 174 | priv->addr.y = 0; |
---|
.. | .. |
---|
179 | 177 | |
---|
180 | 178 | static void charlcd_print(struct charlcd *lcd, char c) |
---|
181 | 179 | { |
---|
182 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 180 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
183 | 181 | |
---|
184 | 182 | if (priv->addr.x < lcd->bwidth) { |
---|
185 | 183 | if (lcd->char_conv) |
---|
.. | .. |
---|
211 | 209 | /* clears the display and resets X/Y */ |
---|
212 | 210 | static void charlcd_clear_display(struct charlcd *lcd) |
---|
213 | 211 | { |
---|
214 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 212 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
215 | 213 | |
---|
216 | 214 | lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR); |
---|
217 | 215 | priv->addr.x = 0; |
---|
.. | .. |
---|
223 | 221 | static int charlcd_init_display(struct charlcd *lcd) |
---|
224 | 222 | { |
---|
225 | 223 | void (*write_cmd_raw)(struct charlcd *lcd, int cmd); |
---|
226 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 224 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
227 | 225 | u8 init; |
---|
228 | 226 | |
---|
229 | 227 | if (lcd->ifwidth != 4 && lcd->ifwidth != 8) |
---|
.. | .. |
---|
288 | 286 | } |
---|
289 | 287 | |
---|
290 | 288 | /* |
---|
291 | | - * Parses an unsigned integer from a string, until a non-digit character |
---|
292 | | - * is found. The empty string is not accepted. No overflow checks are done. |
---|
293 | | - * |
---|
294 | | - * Returns whether the parsing was successful. Only in that case |
---|
295 | | - * the output parameters are written to. |
---|
296 | | - * |
---|
297 | | - * TODO: If the kernel adds an inplace version of kstrtoul(), this function |
---|
298 | | - * could be easily replaced by that. |
---|
299 | | - */ |
---|
300 | | -static bool parse_n(const char *s, unsigned long *res, const char **next_s) |
---|
301 | | -{ |
---|
302 | | - if (!isdigit(*s)) |
---|
303 | | - return false; |
---|
304 | | - |
---|
305 | | - *res = 0; |
---|
306 | | - while (isdigit(*s)) { |
---|
307 | | - *res = *res * 10 + (*s - '0'); |
---|
308 | | - ++s; |
---|
309 | | - } |
---|
310 | | - |
---|
311 | | - *next_s = s; |
---|
312 | | - return true; |
---|
313 | | -} |
---|
314 | | - |
---|
315 | | -/* |
---|
316 | 289 | * Parses a movement command of the form "(.*);", where the group can be |
---|
317 | 290 | * any number of subcommands of the form "(x|y)[0-9]+". |
---|
318 | 291 | * |
---|
.. | .. |
---|
336 | 309 | { |
---|
337 | 310 | unsigned long new_x = *x; |
---|
338 | 311 | unsigned long new_y = *y; |
---|
| 312 | + char *p; |
---|
339 | 313 | |
---|
340 | 314 | for (;;) { |
---|
341 | 315 | if (!*s) |
---|
.. | .. |
---|
345 | 319 | break; |
---|
346 | 320 | |
---|
347 | 321 | if (*s == 'x') { |
---|
348 | | - if (!parse_n(s + 1, &new_x, &s)) |
---|
| 322 | + new_x = simple_strtoul(s + 1, &p, 10); |
---|
| 323 | + if (p == s + 1) |
---|
349 | 324 | return false; |
---|
| 325 | + s = p; |
---|
350 | 326 | } else if (*s == 'y') { |
---|
351 | | - if (!parse_n(s + 1, &new_y, &s)) |
---|
| 327 | + new_y = simple_strtoul(s + 1, &p, 10); |
---|
| 328 | + if (p == s + 1) |
---|
352 | 329 | return false; |
---|
| 330 | + s = p; |
---|
353 | 331 | } else { |
---|
354 | 332 | return false; |
---|
355 | 333 | } |
---|
.. | .. |
---|
369 | 347 | |
---|
370 | 348 | static inline int handle_lcd_special_code(struct charlcd *lcd) |
---|
371 | 349 | { |
---|
372 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 350 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
373 | 351 | |
---|
374 | 352 | /* LCD special codes */ |
---|
375 | 353 | |
---|
.. | .. |
---|
507 | 485 | shift = 0; |
---|
508 | 486 | value = 0; |
---|
509 | 487 | while (*esc && cgoffset < 8) { |
---|
510 | | - shift ^= 4; |
---|
511 | | - if (*esc >= '0' && *esc <= '9') { |
---|
512 | | - value |= (*esc - '0') << shift; |
---|
513 | | - } else if (*esc >= 'A' && *esc <= 'F') { |
---|
514 | | - value |= (*esc - 'A' + 10) << shift; |
---|
515 | | - } else if (*esc >= 'a' && *esc <= 'f') { |
---|
516 | | - value |= (*esc - 'a' + 10) << shift; |
---|
517 | | - } else { |
---|
518 | | - esc++; |
---|
519 | | - continue; |
---|
520 | | - } |
---|
| 488 | + int half; |
---|
521 | 489 | |
---|
| 490 | + shift ^= 4; |
---|
| 491 | + |
---|
| 492 | + half = hex_to_bin(*esc++); |
---|
| 493 | + if (half < 0) |
---|
| 494 | + continue; |
---|
| 495 | + |
---|
| 496 | + value |= half << shift; |
---|
522 | 497 | if (shift == 0) { |
---|
523 | 498 | cgbytes[cgoffset++] = value; |
---|
524 | 499 | value = 0; |
---|
525 | 500 | } |
---|
526 | | - |
---|
527 | | - esc++; |
---|
528 | 501 | } |
---|
529 | 502 | |
---|
530 | 503 | lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); |
---|
.. | .. |
---|
580 | 553 | |
---|
581 | 554 | static void charlcd_write_char(struct charlcd *lcd, char c) |
---|
582 | 555 | { |
---|
583 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 556 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
584 | 557 | |
---|
585 | 558 | /* first, we'll test if we're in escape mode */ |
---|
586 | 559 | if ((c != '\n') && priv->esc_seq.len >= 0) { |
---|
.. | .. |
---|
705 | 678 | |
---|
706 | 679 | static int charlcd_open(struct inode *inode, struct file *file) |
---|
707 | 680 | { |
---|
708 | | - struct charlcd_priv *priv = to_priv(the_charlcd); |
---|
| 681 | + struct charlcd_priv *priv = charlcd_to_priv(the_charlcd); |
---|
709 | 682 | int ret; |
---|
710 | 683 | |
---|
711 | 684 | ret = -EBUSY; |
---|
.. | .. |
---|
763 | 736 | } |
---|
764 | 737 | } |
---|
765 | 738 | |
---|
| 739 | +#ifdef CONFIG_PANEL_BOOT_MESSAGE |
---|
| 740 | +#define LCD_INIT_TEXT CONFIG_PANEL_BOOT_MESSAGE |
---|
| 741 | +#else |
---|
| 742 | +#define LCD_INIT_TEXT "Linux-" UTS_RELEASE "\n" |
---|
| 743 | +#endif |
---|
| 744 | + |
---|
| 745 | +#ifdef CONFIG_CHARLCD_BL_ON |
---|
| 746 | +#define LCD_INIT_BL "\x1b[L+" |
---|
| 747 | +#elif defined(CONFIG_CHARLCD_BL_FLASH) |
---|
| 748 | +#define LCD_INIT_BL "\x1b[L*" |
---|
| 749 | +#else |
---|
| 750 | +#define LCD_INIT_BL "\x1b[L-" |
---|
| 751 | +#endif |
---|
| 752 | + |
---|
766 | 753 | /* initialize the LCD driver */ |
---|
767 | 754 | static int charlcd_init(struct charlcd *lcd) |
---|
768 | 755 | { |
---|
769 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 756 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
770 | 757 | int ret; |
---|
771 | 758 | |
---|
772 | 759 | if (lcd->ops->backlight) { |
---|
.. | .. |
---|
784 | 771 | return ret; |
---|
785 | 772 | |
---|
786 | 773 | /* display a short message */ |
---|
787 | | -#ifdef CONFIG_PANEL_CHANGE_MESSAGE |
---|
788 | | -#ifdef CONFIG_PANEL_BOOT_MESSAGE |
---|
789 | | - charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE); |
---|
790 | | -#endif |
---|
791 | | -#else |
---|
792 | | - charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\n"); |
---|
793 | | -#endif |
---|
| 774 | + charlcd_puts(lcd, "\x1b[Lc\x1b[Lb" LCD_INIT_BL LCD_INIT_TEXT); |
---|
| 775 | + |
---|
794 | 776 | /* clear the display on the next device opening */ |
---|
795 | 777 | priv->must_clear = true; |
---|
796 | 778 | charlcd_home(lcd); |
---|
.. | .. |
---|
817 | 799 | return lcd; |
---|
818 | 800 | } |
---|
819 | 801 | EXPORT_SYMBOL_GPL(charlcd_alloc); |
---|
| 802 | + |
---|
| 803 | +void charlcd_free(struct charlcd *lcd) |
---|
| 804 | +{ |
---|
| 805 | + kfree(charlcd_to_priv(lcd)); |
---|
| 806 | +} |
---|
| 807 | +EXPORT_SYMBOL_GPL(charlcd_free); |
---|
820 | 808 | |
---|
821 | 809 | static int panel_notify_sys(struct notifier_block *this, unsigned long code, |
---|
822 | 810 | void *unused) |
---|
.. | .. |
---|
866 | 854 | |
---|
867 | 855 | int charlcd_unregister(struct charlcd *lcd) |
---|
868 | 856 | { |
---|
869 | | - struct charlcd_priv *priv = to_priv(lcd); |
---|
| 857 | + struct charlcd_priv *priv = charlcd_to_priv(lcd); |
---|
870 | 858 | |
---|
871 | 859 | unregister_reboot_notifier(&panel_notifier); |
---|
872 | 860 | charlcd_puts(lcd, "\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-"); |
---|