console_rotate.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2015 Google, Inc
  4. * (C) Copyright 2015
  5. * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <video.h>
  10. #include <video_console.h>
  11. #include <video_font.h> /* Get font data, width and height */
  12. static int console_set_row_1(struct udevice *dev, uint row, int clr)
  13. {
  14. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  15. int pbytes = VNBYTES(vid_priv->bpix);
  16. void *start, *line;
  17. int i, j;
  18. int ret;
  19. start = vid_priv->fb + vid_priv->line_length -
  20. (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
  21. line = start;
  22. for (j = 0; j < vid_priv->ysize; j++) {
  23. switch (vid_priv->bpix) {
  24. case VIDEO_BPP8:
  25. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  26. uint8_t *dst = line;
  27. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  28. *dst++ = clr;
  29. break;
  30. }
  31. case VIDEO_BPP16:
  32. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  33. uint16_t *dst = line;
  34. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  35. *dst++ = clr;
  36. break;
  37. }
  38. case VIDEO_BPP32:
  39. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  40. uint32_t *dst = line;
  41. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  42. *dst++ = clr;
  43. break;
  44. }
  45. default:
  46. return -ENOSYS;
  47. }
  48. line += vid_priv->line_length;
  49. }
  50. ret = vidconsole_sync_copy(dev, start, line);
  51. if (ret)
  52. return ret;
  53. return 0;
  54. }
  55. static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
  56. uint count)
  57. {
  58. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  59. int pbytes = VNBYTES(vid_priv->bpix);
  60. void *dst;
  61. void *src;
  62. int j, ret;
  63. dst = vid_priv->fb + vid_priv->line_length -
  64. (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
  65. src = vid_priv->fb + vid_priv->line_length -
  66. (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
  67. for (j = 0; j < vid_priv->ysize; j++) {
  68. ret = vidconsole_memmove(dev, dst, src,
  69. VIDEO_FONT_HEIGHT * pbytes * count);
  70. if (ret)
  71. return ret;
  72. src += vid_priv->line_length;
  73. dst += vid_priv->line_length;
  74. }
  75. return 0;
  76. }
  77. static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
  78. {
  79. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  80. struct udevice *vid = dev->parent;
  81. struct video_priv *vid_priv = dev_get_uclass_priv(vid);
  82. uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
  83. int pbytes = VNBYTES(vid_priv->bpix);
  84. int i, col, x, linenum, ret;
  85. int mask = 0x80;
  86. void *start, *line;
  87. linenum = VID_TO_PIXEL(x_frac) + 1;
  88. x = y + 1;
  89. start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
  90. line = start;
  91. if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
  92. return -EAGAIN;
  93. for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
  94. switch (vid_priv->bpix) {
  95. case VIDEO_BPP8:
  96. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  97. uint8_t *dst = line;
  98. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  99. *dst-- = (pfont[i] & mask) ?
  100. vid_priv->colour_fg :
  101. vid_priv->colour_bg;
  102. }
  103. break;
  104. }
  105. case VIDEO_BPP16:
  106. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  107. uint16_t *dst = line;
  108. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  109. *dst-- = (pfont[i] & mask) ?
  110. vid_priv->colour_fg :
  111. vid_priv->colour_bg;
  112. }
  113. break;
  114. }
  115. case VIDEO_BPP32:
  116. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  117. uint32_t *dst = line;
  118. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  119. *dst-- = (pfont[i] & mask) ?
  120. vid_priv->colour_fg :
  121. vid_priv->colour_bg;
  122. }
  123. break;
  124. }
  125. default:
  126. return -ENOSYS;
  127. }
  128. line += vid_priv->line_length;
  129. mask >>= 1;
  130. }
  131. /* We draw backwards from 'start, so account for the first line */
  132. ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
  133. if (ret)
  134. return ret;
  135. return VID_TO_POS(VIDEO_FONT_WIDTH);
  136. }
  137. static int console_set_row_2(struct udevice *dev, uint row, int clr)
  138. {
  139. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  140. void *start, *line, *end;
  141. int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
  142. int i, ret;
  143. start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
  144. (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
  145. line = start;
  146. switch (vid_priv->bpix) {
  147. case VIDEO_BPP8:
  148. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  149. uint8_t *dst = line;
  150. for (i = 0; i < pixels; i++)
  151. *dst++ = clr;
  152. end = dst;
  153. break;
  154. }
  155. case VIDEO_BPP16:
  156. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  157. uint16_t *dst = line;
  158. for (i = 0; i < pixels; i++)
  159. *dst++ = clr;
  160. end = dst;
  161. break;
  162. }
  163. case VIDEO_BPP32:
  164. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  165. uint32_t *dst = line;
  166. for (i = 0; i < pixels; i++)
  167. *dst++ = clr;
  168. end = dst;
  169. break;
  170. }
  171. default:
  172. return -ENOSYS;
  173. }
  174. ret = vidconsole_sync_copy(dev, start, end);
  175. if (ret)
  176. return ret;
  177. return 0;
  178. }
  179. static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
  180. uint count)
  181. {
  182. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  183. void *dst;
  184. void *src;
  185. void *end;
  186. end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
  187. dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
  188. vid_priv->line_length;
  189. src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
  190. vid_priv->line_length;
  191. vidconsole_memmove(dev, dst, src,
  192. VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
  193. return 0;
  194. }
  195. static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
  196. {
  197. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  198. struct udevice *vid = dev->parent;
  199. struct video_priv *vid_priv = dev_get_uclass_priv(vid);
  200. int pbytes = VNBYTES(vid_priv->bpix);
  201. int i, row, x, linenum, ret;
  202. void *start, *line;
  203. if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
  204. return -EAGAIN;
  205. linenum = vid_priv->ysize - y - 1;
  206. x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
  207. start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
  208. line = start;
  209. for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
  210. unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
  211. uchar bits = video_fontdata[idx];
  212. switch (vid_priv->bpix) {
  213. case VIDEO_BPP8:
  214. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  215. uint8_t *dst = line;
  216. for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
  217. *dst-- = (bits & 0x80) ?
  218. vid_priv->colour_fg :
  219. vid_priv->colour_bg;
  220. bits <<= 1;
  221. }
  222. break;
  223. }
  224. case VIDEO_BPP16:
  225. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  226. uint16_t *dst = line;
  227. for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
  228. *dst-- = (bits & 0x80) ?
  229. vid_priv->colour_fg :
  230. vid_priv->colour_bg;
  231. bits <<= 1;
  232. }
  233. break;
  234. }
  235. case VIDEO_BPP32:
  236. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  237. uint32_t *dst = line;
  238. for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
  239. *dst-- = (bits & 0x80) ?
  240. vid_priv->colour_fg :
  241. vid_priv->colour_bg;
  242. bits <<= 1;
  243. }
  244. break;
  245. }
  246. default:
  247. return -ENOSYS;
  248. }
  249. line -= vid_priv->line_length;
  250. }
  251. /* Add 4 bytes to allow for the first pixel writen */
  252. ret = vidconsole_sync_copy(dev, start + 4, line);
  253. if (ret)
  254. return ret;
  255. return VID_TO_POS(VIDEO_FONT_WIDTH);
  256. }
  257. static int console_set_row_3(struct udevice *dev, uint row, int clr)
  258. {
  259. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  260. int pbytes = VNBYTES(vid_priv->bpix);
  261. void *start, *line;
  262. int i, j, ret;
  263. start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
  264. line = start;
  265. for (j = 0; j < vid_priv->ysize; j++) {
  266. switch (vid_priv->bpix) {
  267. case VIDEO_BPP8:
  268. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  269. uint8_t *dst = line;
  270. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  271. *dst++ = clr;
  272. break;
  273. }
  274. case VIDEO_BPP16:
  275. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  276. uint16_t *dst = line;
  277. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  278. *dst++ = clr;
  279. break;
  280. }
  281. case VIDEO_BPP32:
  282. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  283. uint32_t *dst = line;
  284. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  285. *dst++ = clr;
  286. break;
  287. }
  288. default:
  289. return -ENOSYS;
  290. }
  291. line += vid_priv->line_length;
  292. }
  293. ret = vidconsole_sync_copy(dev, start, line);
  294. if (ret)
  295. return ret;
  296. return 0;
  297. }
  298. static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
  299. uint count)
  300. {
  301. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  302. int pbytes = VNBYTES(vid_priv->bpix);
  303. void *dst;
  304. void *src;
  305. int j, ret;
  306. dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
  307. src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
  308. for (j = 0; j < vid_priv->ysize; j++) {
  309. ret = vidconsole_memmove(dev, dst, src,
  310. VIDEO_FONT_HEIGHT * pbytes * count);
  311. if (ret)
  312. return ret;
  313. src += vid_priv->line_length;
  314. dst += vid_priv->line_length;
  315. }
  316. return 0;
  317. }
  318. static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
  319. {
  320. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  321. struct udevice *vid = dev->parent;
  322. struct video_priv *vid_priv = dev_get_uclass_priv(vid);
  323. uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
  324. int pbytes = VNBYTES(vid_priv->bpix);
  325. int i, col, x, ret;
  326. int mask = 0x80;
  327. void *start, *line;
  328. if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
  329. return -EAGAIN;
  330. x = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
  331. start = vid_priv->fb + x * vid_priv->line_length + y * pbytes;
  332. line = start;
  333. for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
  334. switch (vid_priv->bpix) {
  335. case VIDEO_BPP8:
  336. if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  337. uint8_t *dst = line;
  338. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  339. *dst++ = (pfont[i] & mask) ?
  340. vid_priv->colour_fg :
  341. vid_priv->colour_bg;
  342. }
  343. break;
  344. }
  345. case VIDEO_BPP16:
  346. if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  347. uint16_t *dst = line;
  348. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  349. *dst++ = (pfont[i] & mask) ?
  350. vid_priv->colour_fg :
  351. vid_priv->colour_bg;
  352. }
  353. break;
  354. }
  355. case VIDEO_BPP32:
  356. if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  357. uint32_t *dst = line;
  358. for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
  359. *dst++ = (pfont[i] & mask) ?
  360. vid_priv->colour_fg :
  361. vid_priv->colour_bg;
  362. }
  363. break;
  364. }
  365. default:
  366. return -ENOSYS;
  367. }
  368. line -= vid_priv->line_length;
  369. mask >>= 1;
  370. }
  371. /* Add a line to allow for the first pixels writen */
  372. ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
  373. if (ret)
  374. return ret;
  375. return VID_TO_POS(VIDEO_FONT_WIDTH);
  376. }
  377. static int console_probe_2(struct udevice *dev)
  378. {
  379. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  380. struct udevice *vid_dev = dev->parent;
  381. struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
  382. vc_priv->x_charsize = VIDEO_FONT_WIDTH;
  383. vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
  384. vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
  385. vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
  386. return 0;
  387. }
  388. static int console_probe_1_3(struct udevice *dev)
  389. {
  390. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  391. struct udevice *vid_dev = dev->parent;
  392. struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
  393. vc_priv->x_charsize = VIDEO_FONT_WIDTH;
  394. vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
  395. vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
  396. vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
  397. vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
  398. return 0;
  399. }
  400. struct vidconsole_ops console_ops_1 = {
  401. .putc_xy = console_putc_xy_1,
  402. .move_rows = console_move_rows_1,
  403. .set_row = console_set_row_1,
  404. };
  405. struct vidconsole_ops console_ops_2 = {
  406. .putc_xy = console_putc_xy_2,
  407. .move_rows = console_move_rows_2,
  408. .set_row = console_set_row_2,
  409. };
  410. struct vidconsole_ops console_ops_3 = {
  411. .putc_xy = console_putc_xy_3,
  412. .move_rows = console_move_rows_3,
  413. .set_row = console_set_row_3,
  414. };
  415. U_BOOT_DRIVER(vidconsole_1) = {
  416. .name = "vidconsole1",
  417. .id = UCLASS_VIDEO_CONSOLE,
  418. .ops = &console_ops_1,
  419. .probe = console_probe_1_3,
  420. };
  421. U_BOOT_DRIVER(vidconsole_2) = {
  422. .name = "vidconsole2",
  423. .id = UCLASS_VIDEO_CONSOLE,
  424. .ops = &console_ops_2,
  425. .probe = console_probe_2,
  426. };
  427. U_BOOT_DRIVER(vidconsole_3) = {
  428. .name = "vidconsole3",
  429. .id = UCLASS_VIDEO_CONSOLE,
  430. .ops = &console_ops_3,
  431. .probe = console_probe_1_3,
  432. };