console_core.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
  7. */
  8. #include <video.h>
  9. #include <video_console.h>
  10. #include <dm.h>
  11. #include <video_font.h>
  12. #include "vidconsole_internal.h"
  13. /**
  14. * console_set_font() - prepare vidconsole for chosen font.
  15. *
  16. * @dev vidconsole device
  17. * @fontdata pointer to font data struct
  18. */
  19. static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata)
  20. {
  21. struct console_simple_priv *priv = dev_get_priv(dev);
  22. struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  23. struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  24. debug("console_simple: setting %s font\n", fontdata->name);
  25. debug("width: %d\n", fontdata->width);
  26. debug("byte width: %d\n", fontdata->byte_width);
  27. debug("height: %d\n", fontdata->height);
  28. priv->fontdata = fontdata;
  29. vc_priv->x_charsize = fontdata->width;
  30. vc_priv->y_charsize = fontdata->height;
  31. if (vid_priv->rot % 2) {
  32. vc_priv->cols = vid_priv->ysize / fontdata->width;
  33. vc_priv->rows = vid_priv->xsize / fontdata->height;
  34. vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
  35. } else {
  36. vc_priv->cols = vid_priv->xsize / fontdata->width;
  37. vc_priv->rows = vid_priv->ysize / fontdata->height;
  38. }
  39. return 0;
  40. }
  41. int check_bpix_support(int bpix)
  42. {
  43. if (bpix == VIDEO_BPP8 && CONFIG_IS_ENABLED(VIDEO_BPP8))
  44. return 0;
  45. else if (bpix == VIDEO_BPP16 && CONFIG_IS_ENABLED(VIDEO_BPP16))
  46. return 0;
  47. else if (bpix == VIDEO_BPP32 && CONFIG_IS_ENABLED(VIDEO_BPP32))
  48. return 0;
  49. else
  50. return -ENOSYS;
  51. }
  52. inline void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step)
  53. {
  54. u8 *dst_byte = *dstp;
  55. if (pbytes == 4) {
  56. u32 *dst = *dstp;
  57. *dst = value;
  58. }
  59. if (pbytes == 2) {
  60. u16 *dst = *dstp;
  61. *dst = value;
  62. }
  63. if (pbytes == 1) {
  64. u8 *dst = *dstp;
  65. *dst = value;
  66. }
  67. *dstp = dst_byte + step;
  68. }
  69. int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv,
  70. struct video_fontdata *fontdata, bool direction)
  71. {
  72. int step, line_step, pbytes, bitcount, width_remainder, ret;
  73. void *dst;
  74. ret = check_bpix_support(vid_priv->bpix);
  75. if (ret)
  76. return ret;
  77. pbytes = VNBYTES(vid_priv->bpix);
  78. if (direction) {
  79. step = -pbytes;
  80. line_step = -vid_priv->line_length;
  81. } else {
  82. step = pbytes;
  83. line_step = vid_priv->line_length;
  84. }
  85. width_remainder = fontdata->width % 8;
  86. for (int row = 0; row < fontdata->height; row++) {
  87. uchar bits;
  88. bitcount = 8;
  89. dst = *line;
  90. for (int col = 0; col < fontdata->byte_width; col++) {
  91. if (width_remainder) {
  92. bool is_last_col = (fontdata->byte_width - col == 1);
  93. if (is_last_col)
  94. bitcount = width_remainder;
  95. }
  96. bits = pfont[col];
  97. for (int bit = 0; bit < bitcount; bit++) {
  98. u32 value = (bits & 0x80) ?
  99. vid_priv->colour_fg :
  100. vid_priv->colour_bg;
  101. fill_pixel_and_goto_next(&dst,
  102. value,
  103. pbytes,
  104. step
  105. );
  106. bits <<= 1;
  107. }
  108. }
  109. *line += line_step;
  110. pfont += fontdata->byte_width;
  111. }
  112. return ret;
  113. }
  114. int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
  115. struct video_fontdata *fontdata, bool direction)
  116. {
  117. int step, line_step, pbytes, bitcount = 8, width_remainder, ret;
  118. void *dst;
  119. u8 mask;
  120. ret = check_bpix_support(vid_priv->bpix);
  121. if (ret)
  122. return ret;
  123. pbytes = VNBYTES(vid_priv->bpix);
  124. if (direction) {
  125. step = -pbytes;
  126. line_step = vid_priv->line_length;
  127. } else {
  128. step = pbytes;
  129. line_step = -vid_priv->line_length;
  130. }
  131. width_remainder = fontdata->width % 8;
  132. for (int col = 0; col < fontdata->byte_width; col++) {
  133. mask = 0x80;
  134. if (width_remainder) {
  135. bool is_last_col = (fontdata->byte_width - col == 1);
  136. if (is_last_col)
  137. bitcount = width_remainder;
  138. }
  139. for (int bit = 0; bit < bitcount; bit++) {
  140. dst = *line;
  141. for (int row = 0; row < fontdata->height; row++) {
  142. u32 value = (pfont[row * fontdata->byte_width + col]
  143. & mask) ? vid_priv->colour_fg : vid_priv->colour_bg;
  144. fill_pixel_and_goto_next(&dst,
  145. value,
  146. pbytes,
  147. step
  148. );
  149. }
  150. *line += line_step;
  151. mask >>= 1;
  152. }
  153. }
  154. return ret;
  155. }
  156. int console_probe(struct udevice *dev)
  157. {
  158. return console_set_font(dev, fonts);
  159. }
  160. const char *console_simple_get_font_size(struct udevice *dev, uint *sizep)
  161. {
  162. struct console_simple_priv *priv = dev_get_priv(dev);
  163. *sizep = priv->fontdata->width;
  164. return priv->fontdata->name;
  165. }
  166. int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info)
  167. {
  168. info->name = fonts[seq].name;
  169. return 0;
  170. }
  171. int console_simple_select_font(struct udevice *dev, const char *name, uint size)
  172. {
  173. struct video_fontdata *font;
  174. if (!name) {
  175. if (fonts->name)
  176. console_set_font(dev, fonts);
  177. return 0;
  178. }
  179. for (font = fonts; font->name; font++) {
  180. if (!strcmp(name, font->name)) {
  181. console_set_font(dev, font);
  182. return 0;
  183. }
  184. };
  185. printf("no such font: %s, make sure it's name has <width>x<height> format\n", name);
  186. return -ENOENT;
  187. }