blob: e4303dfb364c48152206f60b52d40a5e856d8aea [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass87aae882016-01-18 19:52:19 -07002/*
3 * Copyright (c) 2015 Google, Inc
4 * (C) Copyright 2015
5 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +03006 * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
Simon Glass87aae882016-01-18 19:52:19 -07007 */
8
9#include <common.h>
Janne Grunau5548c362024-03-16 22:50:19 +010010#include <charset.h>
Simon Glass87aae882016-01-18 19:52:19 -070011#include <dm.h>
12#include <video.h>
13#include <video_console.h>
14#include <video_font.h> /* Get font data, width and height */
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030015#include "vidconsole_internal.h"
Simon Glass87aae882016-01-18 19:52:19 -070016
17static int console_set_row_1(struct udevice *dev, uint row, int clr)
18{
19 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030020 struct console_simple_priv *priv = dev_get_priv(dev);
21 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -070022 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030023 void *start, *dst, *line;
Simon Glass87aae882016-01-18 19:52:19 -070024 int i, j;
Simon Glass42301da2020-07-02 21:12:26 -060025 int ret;
Simon Glass87aae882016-01-18 19:52:19 -070026
Simon Glass42301da2020-07-02 21:12:26 -060027 start = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030028 (row + 1) * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -060029 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070030 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030031 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030032 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030033 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -070034 line += vid_priv->line_length;
35 }
Simon Glass42301da2020-07-02 21:12:26 -060036 ret = vidconsole_sync_copy(dev, start, line);
37 if (ret)
38 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070039
40 return 0;
41}
42
43static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030044 uint count)
Simon Glass87aae882016-01-18 19:52:19 -070045{
46 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030047 struct console_simple_priv *priv = dev_get_priv(dev);
48 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -060049 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -070050 void *dst;
51 void *src;
Simon Glass42301da2020-07-02 21:12:26 -060052 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -070053
54 dst = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030055 (rowdst + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070056 src = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030057 (rowsrc + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070058
59 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -060060 ret = vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030061 fontdata->height * pbytes * count);
Simon Glass42301da2020-07-02 21:12:26 -060062 if (ret)
63 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070064 src += vid_priv->line_length;
65 dst += vid_priv->line_length;
66 }
67
68 return 0;
69}
70
Janne Grunau5548c362024-03-16 22:50:19 +010071static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -070072{
Simon Glass52c10c52016-01-14 18:10:37 -070073 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -070074 struct udevice *vid = dev->parent;
75 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030076 struct console_simple_priv *priv = dev_get_priv(dev);
77 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -070078 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030079 int x, linenum, ret;
Simon Glass42301da2020-07-02 21:12:26 -060080 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +010081 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030082 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +010083 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -070084
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030085 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
86 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -060087 linenum = VID_TO_PIXEL(x_frac) + 1;
88 x = y + 1;
Simon Glass42301da2020-07-02 21:12:26 -060089 start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
90 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070091
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030092 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030093 if (ret)
94 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070095
Simon Glass42301da2020-07-02 21:12:26 -060096 /* We draw backwards from 'start, so account for the first line */
97 ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
98 if (ret)
99 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700100
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300101 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700102}
103
104
105static int console_set_row_2(struct udevice *dev, uint row, int clr)
106{
107 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300108 struct console_simple_priv *priv = dev_get_priv(dev);
109 struct video_fontdata *fontdata = priv->fontdata;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300110 void *start, *line, *dst, *end;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300111 int pixels = fontdata->height * vid_priv->xsize;
Simon Glass42301da2020-07-02 21:12:26 -0600112 int i, ret;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300113 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700114
Simon Glass42301da2020-07-02 21:12:26 -0600115 start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300116 (row + 1) * fontdata->height * vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600117 line = start;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300118 dst = line;
119 for (i = 0; i < pixels; i++)
120 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
121 end = dst;
Simon Glass42301da2020-07-02 21:12:26 -0600122 ret = vidconsole_sync_copy(dev, start, end);
123 if (ret)
124 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700125
126 return 0;
127}
128
129static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
130 uint count)
131{
132 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300133 struct console_simple_priv *priv = dev_get_priv(dev);
134 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700135 void *dst;
136 void *src;
137 void *end;
138
139 end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300140 dst = end - (rowdst + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700141 vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300142 src = end - (rowsrc + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700143 vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600144 vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300145 fontdata->height * vid_priv->line_length * count);
Simon Glass87aae882016-01-18 19:52:19 -0700146
147 return 0;
148}
149
Janne Grunau5548c362024-03-16 22:50:19 +0100150static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700151{
Simon Glass52c10c52016-01-14 18:10:37 -0700152 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700153 struct udevice *vid = dev->parent;
154 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300155 struct console_simple_priv *priv = dev_get_priv(dev);
156 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600157 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300158 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600159 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100160 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300161 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100162 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700163
Simon Glass52c10c52016-01-14 18:10:37 -0700164 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
165 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -0600166 linenum = vid_priv->ysize - y - 1;
Simon Glassf50a6b92020-07-02 21:12:17 -0600167 x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
Simon Glass42301da2020-07-02 21:12:26 -0600168 start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
169 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700170
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300171 ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300172 if (ret)
173 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700174
Simon Glass42301da2020-07-02 21:12:26 -0600175 /* Add 4 bytes to allow for the first pixel writen */
176 ret = vidconsole_sync_copy(dev, start + 4, line);
177 if (ret)
178 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700179
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300180 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700181}
182
183static int console_set_row_3(struct udevice *dev, uint row, int clr)
184{
185 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300186 struct console_simple_priv *priv = dev_get_priv(dev);
187 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700188 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300189 void *start, *dst, *line;
Simon Glass42301da2020-07-02 21:12:26 -0600190 int i, j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700191
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300192 start = vid_priv->fb + row * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600193 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700194 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300195 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300196 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300197 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -0700198 line += vid_priv->line_length;
199 }
Simon Glass42301da2020-07-02 21:12:26 -0600200 ret = vidconsole_sync_copy(dev, start, line);
201 if (ret)
202 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700203
204 return 0;
205}
206
207static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
208 uint count)
209{
210 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300211 struct console_simple_priv *priv = dev_get_priv(dev);
212 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600213 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700214 void *dst;
215 void *src;
Simon Glass42301da2020-07-02 21:12:26 -0600216 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700217
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300218 dst = vid_priv->fb + rowdst * fontdata->height * pbytes;
219 src = vid_priv->fb + rowsrc * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -0700220
221 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -0600222 ret = vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300223 fontdata->height * pbytes * count);
Simon Glass42301da2020-07-02 21:12:26 -0600224 if (ret)
225 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700226 src += vid_priv->line_length;
227 dst += vid_priv->line_length;
228 }
229
230 return 0;
231}
232
Janne Grunau5548c362024-03-16 22:50:19 +0100233static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700234{
Simon Glass52c10c52016-01-14 18:10:37 -0700235 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700236 struct udevice *vid = dev->parent;
237 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300238 struct console_simple_priv *priv = dev_get_priv(dev);
239 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700240 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300241 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600242 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100243 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300244 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100245 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700246
Simon Glass52c10c52016-01-14 18:10:37 -0700247 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
248 return -EAGAIN;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300249 x = y;
250 linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
251 start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600252 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700253
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300254 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300255 if (ret)
256 return ret;
Simon Glass42301da2020-07-02 21:12:26 -0600257 /* Add a line to allow for the first pixels writen */
258 ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
259 if (ret)
260 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700261
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300262 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700263}
264
Simon Glass87aae882016-01-18 19:52:19 -0700265struct vidconsole_ops console_ops_1 = {
266 .putc_xy = console_putc_xy_1,
267 .move_rows = console_move_rows_1,
268 .set_row = console_set_row_1,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300269 .get_font_size = console_simple_get_font_size,
270 .get_font = console_simple_get_font,
271 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700272};
273
274struct vidconsole_ops console_ops_2 = {
275 .putc_xy = console_putc_xy_2,
276 .move_rows = console_move_rows_2,
277 .set_row = console_set_row_2,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300278 .get_font_size = console_simple_get_font_size,
279 .get_font = console_simple_get_font,
280 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700281};
282
283struct vidconsole_ops console_ops_3 = {
284 .putc_xy = console_putc_xy_3,
285 .move_rows = console_move_rows_3,
286 .set_row = console_set_row_3,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300287 .get_font_size = console_simple_get_font_size,
288 .get_font = console_simple_get_font,
289 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700290};
291
292U_BOOT_DRIVER(vidconsole_1) = {
293 .name = "vidconsole1",
294 .id = UCLASS_VIDEO_CONSOLE,
295 .ops = &console_ops_1,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300296 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300297 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700298};
299
300U_BOOT_DRIVER(vidconsole_2) = {
301 .name = "vidconsole2",
302 .id = UCLASS_VIDEO_CONSOLE,
303 .ops = &console_ops_2,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300304 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300305 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700306};
307
308U_BOOT_DRIVER(vidconsole_3) = {
309 .name = "vidconsole3",
310 .id = UCLASS_VIDEO_CONSOLE,
311 .ops = &console_ops_3,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300312 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300313 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700314};