charlcd.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Character LCD driver for Linux
  4. *
  5. * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
  6. * Copyright (C) 2016-2017 Glider bvba
  7. */
  8. #include <linux/atomic.h>
  9. #include <linux/ctype.h>
  10. #include <linux/delay.h>
  11. #include <linux/fs.h>
  12. #include <linux/miscdevice.h>
  13. #include <linux/module.h>
  14. #include <linux/notifier.h>
  15. #include <linux/reboot.h>
  16. #include <linux/slab.h>
  17. #include <linux/uaccess.h>
  18. #include <linux/workqueue.h>
  19. #include <generated/utsrelease.h>
  20. #include "charlcd.h"
  21. #define DEFAULT_LCD_BWIDTH 40
  22. #define DEFAULT_LCD_HWIDTH 64
  23. /* Keep the backlight on this many seconds for each flash */
  24. #define LCD_BL_TEMPO_PERIOD 4
  25. #define LCD_FLAG_B 0x0004 /* Blink on */
  26. #define LCD_FLAG_C 0x0008 /* Cursor on */
  27. #define LCD_FLAG_D 0x0010 /* Display on */
  28. #define LCD_FLAG_F 0x0020 /* Large font mode */
  29. #define LCD_FLAG_N 0x0040 /* 2-rows mode */
  30. #define LCD_FLAG_L 0x0080 /* Backlight enabled */
  31. /* LCD commands */
  32. #define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */
  33. #define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */
  34. #define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */
  35. #define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */
  36. #define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */
  37. #define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */
  38. #define LCD_CMD_BLINK_ON 0x01 /* Set blink on */
  39. #define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */
  40. #define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */
  41. #define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */
  42. #define LCD_CMD_FUNCTION_SET 0x20 /* Set function */
  43. #define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */
  44. #define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */
  45. #define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */
  46. #define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */
  47. #define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */
  48. #define LCD_ESCAPE_LEN 24 /* Max chars for LCD escape command */
  49. #define LCD_ESCAPE_CHAR 27 /* Use char 27 for escape command */
  50. struct charlcd_priv {
  51. struct charlcd lcd;
  52. struct delayed_work bl_work;
  53. struct mutex bl_tempo_lock; /* Protects access to bl_tempo */
  54. bool bl_tempo;
  55. bool must_clear;
  56. /* contains the LCD config state */
  57. unsigned long int flags;
  58. /* Contains the LCD X and Y offset */
  59. struct {
  60. unsigned long int x;
  61. unsigned long int y;
  62. } addr;
  63. /* Current escape sequence and it's length or -1 if outside */
  64. struct {
  65. char buf[LCD_ESCAPE_LEN + 1];
  66. int len;
  67. } esc_seq;
  68. unsigned long long drvdata[];
  69. };
  70. #define charlcd_to_priv(p) container_of(p, struct charlcd_priv, lcd)
  71. /* Device single-open policy control */
  72. static atomic_t charlcd_available = ATOMIC_INIT(1);
  73. /* sleeps that many milliseconds with a reschedule */
  74. static void long_sleep(int ms)
  75. {
  76. schedule_timeout_interruptible(msecs_to_jiffies(ms));
  77. }
  78. /* turn the backlight on or off */
  79. static void charlcd_backlight(struct charlcd *lcd, int on)
  80. {
  81. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  82. if (!lcd->ops->backlight)
  83. return;
  84. mutex_lock(&priv->bl_tempo_lock);
  85. if (!priv->bl_tempo)
  86. lcd->ops->backlight(lcd, on);
  87. mutex_unlock(&priv->bl_tempo_lock);
  88. }
  89. static void charlcd_bl_off(struct work_struct *work)
  90. {
  91. struct delayed_work *dwork = to_delayed_work(work);
  92. struct charlcd_priv *priv =
  93. container_of(dwork, struct charlcd_priv, bl_work);
  94. mutex_lock(&priv->bl_tempo_lock);
  95. if (priv->bl_tempo) {
  96. priv->bl_tempo = false;
  97. if (!(priv->flags & LCD_FLAG_L))
  98. priv->lcd.ops->backlight(&priv->lcd, 0);
  99. }
  100. mutex_unlock(&priv->bl_tempo_lock);
  101. }
  102. /* turn the backlight on for a little while */
  103. void charlcd_poke(struct charlcd *lcd)
  104. {
  105. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  106. if (!lcd->ops->backlight)
  107. return;
  108. cancel_delayed_work_sync(&priv->bl_work);
  109. mutex_lock(&priv->bl_tempo_lock);
  110. if (!priv->bl_tempo && !(priv->flags & LCD_FLAG_L))
  111. lcd->ops->backlight(lcd, 1);
  112. priv->bl_tempo = true;
  113. schedule_delayed_work(&priv->bl_work, LCD_BL_TEMPO_PERIOD * HZ);
  114. mutex_unlock(&priv->bl_tempo_lock);
  115. }
  116. EXPORT_SYMBOL_GPL(charlcd_poke);
  117. static void charlcd_gotoxy(struct charlcd *lcd)
  118. {
  119. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  120. unsigned int addr;
  121. /*
  122. * we force the cursor to stay at the end of the
  123. * line if it wants to go farther
  124. */
  125. addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
  126. : lcd->bwidth - 1;
  127. if (priv->addr.y & 1)
  128. addr += lcd->hwidth;
  129. if (priv->addr.y & 2)
  130. addr += lcd->bwidth;
  131. lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
  132. }
  133. static void charlcd_home(struct charlcd *lcd)
  134. {
  135. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  136. priv->addr.x = 0;
  137. priv->addr.y = 0;
  138. charlcd_gotoxy(lcd);
  139. }
  140. static void charlcd_print(struct charlcd *lcd, char c)
  141. {
  142. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  143. if (priv->addr.x < lcd->bwidth) {
  144. if (lcd->char_conv)
  145. c = lcd->char_conv[(unsigned char)c];
  146. lcd->ops->write_data(lcd, c);
  147. priv->addr.x++;
  148. /* prevents the cursor from wrapping onto the next line */
  149. if (priv->addr.x == lcd->bwidth)
  150. charlcd_gotoxy(lcd);
  151. }
  152. }
  153. static void charlcd_clear_fast(struct charlcd *lcd)
  154. {
  155. int pos;
  156. charlcd_home(lcd);
  157. if (lcd->ops->clear_fast)
  158. lcd->ops->clear_fast(lcd);
  159. else
  160. for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
  161. lcd->ops->write_data(lcd, ' ');
  162. charlcd_home(lcd);
  163. }
  164. /* clears the display and resets X/Y */
  165. static void charlcd_clear_display(struct charlcd *lcd)
  166. {
  167. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  168. lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
  169. priv->addr.x = 0;
  170. priv->addr.y = 0;
  171. /* we must wait a few milliseconds (15) */
  172. long_sleep(15);
  173. }
  174. static int charlcd_init_display(struct charlcd *lcd)
  175. {
  176. void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
  177. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  178. u8 init;
  179. if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
  180. return -EINVAL;
  181. priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
  182. LCD_FLAG_C | LCD_FLAG_B;
  183. long_sleep(20); /* wait 20 ms after power-up for the paranoid */
  184. /*
  185. * 8-bit mode, 1 line, small fonts; let's do it 3 times, to make sure
  186. * the LCD is in 8-bit mode afterwards
  187. */
  188. init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
  189. if (lcd->ifwidth == 4) {
  190. init >>= 4;
  191. write_cmd_raw = lcd->ops->write_cmd_raw4;
  192. } else {
  193. write_cmd_raw = lcd->ops->write_cmd;
  194. }
  195. write_cmd_raw(lcd, init);
  196. long_sleep(10);
  197. write_cmd_raw(lcd, init);
  198. long_sleep(10);
  199. write_cmd_raw(lcd, init);
  200. long_sleep(10);
  201. if (lcd->ifwidth == 4) {
  202. /* Switch to 4-bit mode, 1 line, small fonts */
  203. lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
  204. long_sleep(10);
  205. }
  206. /* set font height and lines number */
  207. lcd->ops->write_cmd(lcd,
  208. LCD_CMD_FUNCTION_SET |
  209. ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
  210. ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
  211. ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
  212. long_sleep(10);
  213. /* display off, cursor off, blink off */
  214. lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CTRL);
  215. long_sleep(10);
  216. lcd->ops->write_cmd(lcd,
  217. LCD_CMD_DISPLAY_CTRL | /* set display mode */
  218. ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
  219. ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
  220. ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
  221. charlcd_backlight(lcd, (priv->flags & LCD_FLAG_L) ? 1 : 0);
  222. long_sleep(10);
  223. /* entry mode set : increment, cursor shifting */
  224. lcd->ops->write_cmd(lcd, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
  225. charlcd_clear_display(lcd);
  226. return 0;
  227. }
  228. /*
  229. * Parses a movement command of the form "(.*);", where the group can be
  230. * any number of subcommands of the form "(x|y)[0-9]+".
  231. *
  232. * Returns whether the command is valid. The position arguments are
  233. * only written if the parsing was successful.
  234. *
  235. * For instance:
  236. * - ";" returns (<original x>, <original y>).
  237. * - "x1;" returns (1, <original y>).
  238. * - "y2x1;" returns (1, 2).
  239. * - "x12y34x56;" returns (56, 34).
  240. * - "" fails.
  241. * - "x" fails.
  242. * - "x;" fails.
  243. * - "x1" fails.
  244. * - "xy12;" fails.
  245. * - "x12yy12;" fails.
  246. * - "xx" fails.
  247. */
  248. static bool parse_xy(const char *s, unsigned long *x, unsigned long *y)
  249. {
  250. unsigned long new_x = *x;
  251. unsigned long new_y = *y;
  252. char *p;
  253. for (;;) {
  254. if (!*s)
  255. return false;
  256. if (*s == ';')
  257. break;
  258. if (*s == 'x') {
  259. new_x = simple_strtoul(s + 1, &p, 10);
  260. if (p == s + 1)
  261. return false;
  262. s = p;
  263. } else if (*s == 'y') {
  264. new_y = simple_strtoul(s + 1, &p, 10);
  265. if (p == s + 1)
  266. return false;
  267. s = p;
  268. } else {
  269. return false;
  270. }
  271. }
  272. *x = new_x;
  273. *y = new_y;
  274. return true;
  275. }
  276. /*
  277. * These are the file operation function for user access to /dev/lcd
  278. * This function can also be called from inside the kernel, by
  279. * setting file and ppos to NULL.
  280. *
  281. */
  282. static inline int handle_lcd_special_code(struct charlcd *lcd)
  283. {
  284. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  285. /* LCD special codes */
  286. int processed = 0;
  287. char *esc = priv->esc_seq.buf + 2;
  288. int oldflags = priv->flags;
  289. /* check for display mode flags */
  290. switch (*esc) {
  291. case 'D': /* Display ON */
  292. priv->flags |= LCD_FLAG_D;
  293. processed = 1;
  294. break;
  295. case 'd': /* Display OFF */
  296. priv->flags &= ~LCD_FLAG_D;
  297. processed = 1;
  298. break;
  299. case 'C': /* Cursor ON */
  300. priv->flags |= LCD_FLAG_C;
  301. processed = 1;
  302. break;
  303. case 'c': /* Cursor OFF */
  304. priv->flags &= ~LCD_FLAG_C;
  305. processed = 1;
  306. break;
  307. case 'B': /* Blink ON */
  308. priv->flags |= LCD_FLAG_B;
  309. processed = 1;
  310. break;
  311. case 'b': /* Blink OFF */
  312. priv->flags &= ~LCD_FLAG_B;
  313. processed = 1;
  314. break;
  315. case '+': /* Back light ON */
  316. priv->flags |= LCD_FLAG_L;
  317. processed = 1;
  318. break;
  319. case '-': /* Back light OFF */
  320. priv->flags &= ~LCD_FLAG_L;
  321. processed = 1;
  322. break;
  323. case '*': /* Flash back light */
  324. charlcd_poke(lcd);
  325. processed = 1;
  326. break;
  327. case 'f': /* Small Font */
  328. priv->flags &= ~LCD_FLAG_F;
  329. processed = 1;
  330. break;
  331. case 'F': /* Large Font */
  332. priv->flags |= LCD_FLAG_F;
  333. processed = 1;
  334. break;
  335. case 'n': /* One Line */
  336. priv->flags &= ~LCD_FLAG_N;
  337. processed = 1;
  338. break;
  339. case 'N': /* Two Lines */
  340. priv->flags |= LCD_FLAG_N;
  341. processed = 1;
  342. break;
  343. case 'l': /* Shift Cursor Left */
  344. if (priv->addr.x > 0) {
  345. /* back one char if not at end of line */
  346. if (priv->addr.x < lcd->bwidth)
  347. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  348. priv->addr.x--;
  349. }
  350. processed = 1;
  351. break;
  352. case 'r': /* shift cursor right */
  353. if (priv->addr.x < lcd->width) {
  354. /* allow the cursor to pass the end of the line */
  355. if (priv->addr.x < (lcd->bwidth - 1))
  356. lcd->ops->write_cmd(lcd,
  357. LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
  358. priv->addr.x++;
  359. }
  360. processed = 1;
  361. break;
  362. case 'L': /* shift display left */
  363. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
  364. processed = 1;
  365. break;
  366. case 'R': /* shift display right */
  367. lcd->ops->write_cmd(lcd,
  368. LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT |
  369. LCD_CMD_SHIFT_RIGHT);
  370. processed = 1;
  371. break;
  372. case 'k': { /* kill end of line */
  373. int x;
  374. for (x = priv->addr.x; x < lcd->bwidth; x++)
  375. lcd->ops->write_data(lcd, ' ');
  376. /* restore cursor position */
  377. charlcd_gotoxy(lcd);
  378. processed = 1;
  379. break;
  380. }
  381. case 'I': /* reinitialize display */
  382. charlcd_init_display(lcd);
  383. processed = 1;
  384. break;
  385. case 'G': {
  386. /* Generator : LGcxxxxx...xx; must have <c> between '0'
  387. * and '7', representing the numerical ASCII code of the
  388. * redefined character, and <xx...xx> a sequence of 16
  389. * hex digits representing 8 bytes for each character.
  390. * Most LCDs will only use 5 lower bits of the 7 first
  391. * bytes.
  392. */
  393. unsigned char cgbytes[8];
  394. unsigned char cgaddr;
  395. int cgoffset;
  396. int shift;
  397. char value;
  398. int addr;
  399. if (!strchr(esc, ';'))
  400. break;
  401. esc++;
  402. cgaddr = *(esc++) - '0';
  403. if (cgaddr > 7) {
  404. processed = 1;
  405. break;
  406. }
  407. cgoffset = 0;
  408. shift = 0;
  409. value = 0;
  410. while (*esc && cgoffset < 8) {
  411. int half;
  412. shift ^= 4;
  413. half = hex_to_bin(*esc++);
  414. if (half < 0)
  415. continue;
  416. value |= half << shift;
  417. if (shift == 0) {
  418. cgbytes[cgoffset++] = value;
  419. value = 0;
  420. }
  421. }
  422. lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
  423. for (addr = 0; addr < cgoffset; addr++)
  424. lcd->ops->write_data(lcd, cgbytes[addr]);
  425. /* ensures that we stop writing to CGRAM */
  426. charlcd_gotoxy(lcd);
  427. processed = 1;
  428. break;
  429. }
  430. case 'x': /* gotoxy : LxXXX[yYYY]; */
  431. case 'y': /* gotoxy : LyYYY[xXXX]; */
  432. if (priv->esc_seq.buf[priv->esc_seq.len - 1] != ';')
  433. break;
  434. /* If the command is valid, move to the new address */
  435. if (parse_xy(esc, &priv->addr.x, &priv->addr.y))
  436. charlcd_gotoxy(lcd);
  437. /* Regardless of its validity, mark as processed */
  438. processed = 1;
  439. break;
  440. }
  441. /* TODO: This indent party here got ugly, clean it! */
  442. /* Check whether one flag was changed */
  443. if (oldflags == priv->flags)
  444. return processed;
  445. /* check whether one of B,C,D flags were changed */
  446. if ((oldflags ^ priv->flags) &
  447. (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
  448. /* set display mode */
  449. lcd->ops->write_cmd(lcd,
  450. LCD_CMD_DISPLAY_CTRL |
  451. ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
  452. ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
  453. ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
  454. /* check whether one of F,N flags was changed */
  455. else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
  456. lcd->ops->write_cmd(lcd,
  457. LCD_CMD_FUNCTION_SET |
  458. ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
  459. ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
  460. ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
  461. /* check whether L flag was changed */
  462. else if ((oldflags ^ priv->flags) & LCD_FLAG_L)
  463. charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
  464. return processed;
  465. }
  466. static void charlcd_write_char(struct charlcd *lcd, char c)
  467. {
  468. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  469. /* first, we'll test if we're in escape mode */
  470. if ((c != '\n') && priv->esc_seq.len >= 0) {
  471. /* yes, let's add this char to the buffer */
  472. priv->esc_seq.buf[priv->esc_seq.len++] = c;
  473. priv->esc_seq.buf[priv->esc_seq.len] = '\0';
  474. } else {
  475. /* aborts any previous escape sequence */
  476. priv->esc_seq.len = -1;
  477. switch (c) {
  478. case LCD_ESCAPE_CHAR:
  479. /* start of an escape sequence */
  480. priv->esc_seq.len = 0;
  481. priv->esc_seq.buf[priv->esc_seq.len] = '\0';
  482. break;
  483. case '\b':
  484. /* go back one char and clear it */
  485. if (priv->addr.x > 0) {
  486. /*
  487. * check if we're not at the
  488. * end of the line
  489. */
  490. if (priv->addr.x < lcd->bwidth)
  491. /* back one char */
  492. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  493. priv->addr.x--;
  494. }
  495. /* replace with a space */
  496. lcd->ops->write_data(lcd, ' ');
  497. /* back one char again */
  498. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  499. break;
  500. case '\f':
  501. /* quickly clear the display */
  502. charlcd_clear_fast(lcd);
  503. break;
  504. case '\n':
  505. /*
  506. * flush the remainder of the current line and
  507. * go to the beginning of the next line
  508. */
  509. for (; priv->addr.x < lcd->bwidth; priv->addr.x++)
  510. lcd->ops->write_data(lcd, ' ');
  511. priv->addr.x = 0;
  512. priv->addr.y = (priv->addr.y + 1) % lcd->height;
  513. charlcd_gotoxy(lcd);
  514. break;
  515. case '\r':
  516. /* go to the beginning of the same line */
  517. priv->addr.x = 0;
  518. charlcd_gotoxy(lcd);
  519. break;
  520. case '\t':
  521. /* print a space instead of the tab */
  522. charlcd_print(lcd, ' ');
  523. break;
  524. default:
  525. /* simply print this char */
  526. charlcd_print(lcd, c);
  527. break;
  528. }
  529. }
  530. /*
  531. * now we'll see if we're in an escape mode and if the current
  532. * escape sequence can be understood.
  533. */
  534. if (priv->esc_seq.len >= 2) {
  535. int processed = 0;
  536. if (!strcmp(priv->esc_seq.buf, "[2J")) {
  537. /* clear the display */
  538. charlcd_clear_fast(lcd);
  539. processed = 1;
  540. } else if (!strcmp(priv->esc_seq.buf, "[H")) {
  541. /* cursor to home */
  542. charlcd_home(lcd);
  543. processed = 1;
  544. }
  545. /* codes starting with ^[[L */
  546. else if ((priv->esc_seq.len >= 3) &&
  547. (priv->esc_seq.buf[0] == '[') &&
  548. (priv->esc_seq.buf[1] == 'L')) {
  549. processed = handle_lcd_special_code(lcd);
  550. }
  551. /* LCD special escape codes */
  552. /*
  553. * flush the escape sequence if it's been processed
  554. * or if it is getting too long.
  555. */
  556. if (processed || (priv->esc_seq.len >= LCD_ESCAPE_LEN))
  557. priv->esc_seq.len = -1;
  558. } /* escape codes */
  559. }
  560. static struct charlcd *the_charlcd;
  561. static ssize_t charlcd_write(struct file *file, const char __user *buf,
  562. size_t count, loff_t *ppos)
  563. {
  564. const char __user *tmp = buf;
  565. char c;
  566. for (; count-- > 0; (*ppos)++, tmp++) {
  567. if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
  568. /*
  569. * let's be a little nice with other processes
  570. * that need some CPU
  571. */
  572. schedule();
  573. if (get_user(c, tmp))
  574. return -EFAULT;
  575. charlcd_write_char(the_charlcd, c);
  576. }
  577. return tmp - buf;
  578. }
  579. static int charlcd_open(struct inode *inode, struct file *file)
  580. {
  581. struct charlcd_priv *priv = charlcd_to_priv(the_charlcd);
  582. int ret;
  583. ret = -EBUSY;
  584. if (!atomic_dec_and_test(&charlcd_available))
  585. goto fail; /* open only once at a time */
  586. ret = -EPERM;
  587. if (file->f_mode & FMODE_READ) /* device is write-only */
  588. goto fail;
  589. if (priv->must_clear) {
  590. charlcd_clear_display(&priv->lcd);
  591. priv->must_clear = false;
  592. }
  593. return nonseekable_open(inode, file);
  594. fail:
  595. atomic_inc(&charlcd_available);
  596. return ret;
  597. }
  598. static int charlcd_release(struct inode *inode, struct file *file)
  599. {
  600. atomic_inc(&charlcd_available);
  601. return 0;
  602. }
  603. static const struct file_operations charlcd_fops = {
  604. .write = charlcd_write,
  605. .open = charlcd_open,
  606. .release = charlcd_release,
  607. .llseek = no_llseek,
  608. };
  609. static struct miscdevice charlcd_dev = {
  610. .minor = LCD_MINOR,
  611. .name = "lcd",
  612. .fops = &charlcd_fops,
  613. };
  614. static void charlcd_puts(struct charlcd *lcd, const char *s)
  615. {
  616. const char *tmp = s;
  617. int count = strlen(s);
  618. for (; count-- > 0; tmp++) {
  619. if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
  620. /*
  621. * let's be a little nice with other processes
  622. * that need some CPU
  623. */
  624. schedule();
  625. charlcd_write_char(lcd, *tmp);
  626. }
  627. }
  628. #ifdef CONFIG_PANEL_BOOT_MESSAGE
  629. #define LCD_INIT_TEXT CONFIG_PANEL_BOOT_MESSAGE
  630. #else
  631. #define LCD_INIT_TEXT "Linux-" UTS_RELEASE "\n"
  632. #endif
  633. #ifdef CONFIG_CHARLCD_BL_ON
  634. #define LCD_INIT_BL "\x1b[L+"
  635. #elif defined(CONFIG_CHARLCD_BL_FLASH)
  636. #define LCD_INIT_BL "\x1b[L*"
  637. #else
  638. #define LCD_INIT_BL "\x1b[L-"
  639. #endif
  640. /* initialize the LCD driver */
  641. static int charlcd_init(struct charlcd *lcd)
  642. {
  643. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  644. int ret;
  645. if (lcd->ops->backlight) {
  646. mutex_init(&priv->bl_tempo_lock);
  647. INIT_DELAYED_WORK(&priv->bl_work, charlcd_bl_off);
  648. }
  649. /*
  650. * before this line, we must NOT send anything to the display.
  651. * Since charlcd_init_display() needs to write data, we have to
  652. * enable mark the LCD initialized just before.
  653. */
  654. ret = charlcd_init_display(lcd);
  655. if (ret)
  656. return ret;
  657. /* display a short message */
  658. charlcd_puts(lcd, "\x1b[Lc\x1b[Lb" LCD_INIT_BL LCD_INIT_TEXT);
  659. /* clear the display on the next device opening */
  660. priv->must_clear = true;
  661. charlcd_home(lcd);
  662. return 0;
  663. }
  664. struct charlcd *charlcd_alloc(unsigned int drvdata_size)
  665. {
  666. struct charlcd_priv *priv;
  667. struct charlcd *lcd;
  668. priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL);
  669. if (!priv)
  670. return NULL;
  671. priv->esc_seq.len = -1;
  672. lcd = &priv->lcd;
  673. lcd->ifwidth = 8;
  674. lcd->bwidth = DEFAULT_LCD_BWIDTH;
  675. lcd->hwidth = DEFAULT_LCD_HWIDTH;
  676. lcd->drvdata = priv->drvdata;
  677. return lcd;
  678. }
  679. EXPORT_SYMBOL_GPL(charlcd_alloc);
  680. void charlcd_free(struct charlcd *lcd)
  681. {
  682. kfree(charlcd_to_priv(lcd));
  683. }
  684. EXPORT_SYMBOL_GPL(charlcd_free);
  685. static int panel_notify_sys(struct notifier_block *this, unsigned long code,
  686. void *unused)
  687. {
  688. struct charlcd *lcd = the_charlcd;
  689. switch (code) {
  690. case SYS_DOWN:
  691. charlcd_puts(lcd,
  692. "\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
  693. break;
  694. case SYS_HALT:
  695. charlcd_puts(lcd, "\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
  696. break;
  697. case SYS_POWER_OFF:
  698. charlcd_puts(lcd, "\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
  699. break;
  700. default:
  701. break;
  702. }
  703. return NOTIFY_DONE;
  704. }
  705. static struct notifier_block panel_notifier = {
  706. panel_notify_sys,
  707. NULL,
  708. 0
  709. };
  710. int charlcd_register(struct charlcd *lcd)
  711. {
  712. int ret;
  713. ret = charlcd_init(lcd);
  714. if (ret)
  715. return ret;
  716. ret = misc_register(&charlcd_dev);
  717. if (ret)
  718. return ret;
  719. the_charlcd = lcd;
  720. register_reboot_notifier(&panel_notifier);
  721. return 0;
  722. }
  723. EXPORT_SYMBOL_GPL(charlcd_register);
  724. int charlcd_unregister(struct charlcd *lcd)
  725. {
  726. struct charlcd_priv *priv = charlcd_to_priv(lcd);
  727. unregister_reboot_notifier(&panel_notifier);
  728. charlcd_puts(lcd, "\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-");
  729. misc_deregister(&charlcd_dev);
  730. the_charlcd = NULL;
  731. if (lcd->ops->backlight) {
  732. cancel_delayed_work_sync(&priv->bl_work);
  733. priv->lcd.ops->backlight(&priv->lcd, 0);
  734. }
  735. return 0;
  736. }
  737. EXPORT_SYMBOL_GPL(charlcd_unregister);
  738. MODULE_LICENSE("GPL");