blob: dc969836274108c9e1665f4d1154d6ec604358c3 [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
Janne Grunau5548c362024-03-16 22:50:19 +01009#include <charset.h>
Simon Glass87aae882016-01-18 19:52:19 -070010#include <dm.h>
11#include <video.h>
12#include <video_console.h>
13#include <video_font.h> /* Get font data, width and height */
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030014#include "vidconsole_internal.h"
Simon Glass87aae882016-01-18 19:52:19 -070015
16static int console_set_row_1(struct udevice *dev, uint row, int clr)
17{
18 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030019 struct console_simple_priv *priv = dev_get_priv(dev);
20 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -070021 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030022 void *start, *dst, *line;
Simon Glass87aae882016-01-18 19:52:19 -070023 int i, j;
Simon Glass42301da2020-07-02 21:12:26 -060024 int ret;
Simon Glass87aae882016-01-18 19:52:19 -070025
Simon Glass42301da2020-07-02 21:12:26 -060026 start = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030027 (row + 1) * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -060028 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070029 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030030 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030031 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030032 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -070033 line += vid_priv->line_length;
34 }
Simon Glass42301da2020-07-02 21:12:26 -060035 ret = vidconsole_sync_copy(dev, start, line);
36 if (ret)
37 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070038
39 return 0;
40}
41
42static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030043 uint count)
Simon Glass87aae882016-01-18 19:52:19 -070044{
45 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030046 struct console_simple_priv *priv = dev_get_priv(dev);
47 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -060048 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -070049 void *dst;
50 void *src;
Simon Glass42301da2020-07-02 21:12:26 -060051 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -070052
53 dst = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030054 (rowdst + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070055 src = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030056 (rowsrc + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070057
58 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -060059 ret = vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030060 fontdata->height * pbytes * count);
Simon Glass42301da2020-07-02 21:12:26 -060061 if (ret)
62 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070063 src += vid_priv->line_length;
64 dst += vid_priv->line_length;
65 }
66
67 return 0;
68}
69
Janne Grunau5548c362024-03-16 22:50:19 +010070static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -070071{
Simon Glass52c10c52016-01-14 18:10:37 -070072 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -070073 struct udevice *vid = dev->parent;
74 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030075 struct console_simple_priv *priv = dev_get_priv(dev);
76 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -070077 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030078 int x, linenum, ret;
Simon Glass42301da2020-07-02 21:12:26 -060079 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +010080 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030081 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +010082 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -070083
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030084 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
85 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -060086 linenum = VID_TO_PIXEL(x_frac) + 1;
87 x = y + 1;
Simon Glass42301da2020-07-02 21:12:26 -060088 start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
89 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070090
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030091 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030092 if (ret)
93 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070094
Simon Glass42301da2020-07-02 21:12:26 -060095 /* We draw backwards from 'start, so account for the first line */
96 ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
97 if (ret)
98 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070099
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300100 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700101}
102
103
104static int console_set_row_2(struct udevice *dev, uint row, int clr)
105{
106 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300107 struct console_simple_priv *priv = dev_get_priv(dev);
108 struct video_fontdata *fontdata = priv->fontdata;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300109 void *start, *line, *dst, *end;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300110 int pixels = fontdata->height * vid_priv->xsize;
Simon Glass42301da2020-07-02 21:12:26 -0600111 int i, ret;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300112 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700113
Simon Glass42301da2020-07-02 21:12:26 -0600114 start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300115 (row + 1) * fontdata->height * vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600116 line = start;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300117 dst = line;
118 for (i = 0; i < pixels; i++)
119 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
120 end = dst;
Simon Glass42301da2020-07-02 21:12:26 -0600121 ret = vidconsole_sync_copy(dev, start, end);
122 if (ret)
123 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700124
125 return 0;
126}
127
128static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
129 uint count)
130{
131 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300132 struct console_simple_priv *priv = dev_get_priv(dev);
133 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700134 void *dst;
135 void *src;
136 void *end;
137
138 end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300139 dst = end - (rowdst + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700140 vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300141 src = end - (rowsrc + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700142 vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600143 vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300144 fontdata->height * vid_priv->line_length * count);
Simon Glass87aae882016-01-18 19:52:19 -0700145
146 return 0;
147}
148
Janne Grunau5548c362024-03-16 22:50:19 +0100149static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700150{
Simon Glass52c10c52016-01-14 18:10:37 -0700151 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700152 struct udevice *vid = dev->parent;
153 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300154 struct console_simple_priv *priv = dev_get_priv(dev);
155 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600156 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300157 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600158 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100159 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300160 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100161 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700162
Simon Glass52c10c52016-01-14 18:10:37 -0700163 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
164 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -0600165 linenum = vid_priv->ysize - y - 1;
Simon Glassf50a6b92020-07-02 21:12:17 -0600166 x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
Simon Glass42301da2020-07-02 21:12:26 -0600167 start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
168 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700169
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300170 ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300171 if (ret)
172 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700173
Simon Glass42301da2020-07-02 21:12:26 -0600174 /* Add 4 bytes to allow for the first pixel writen */
175 ret = vidconsole_sync_copy(dev, start + 4, line);
176 if (ret)
177 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700178
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300179 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700180}
181
182static int console_set_row_3(struct udevice *dev, uint row, int clr)
183{
184 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300185 struct console_simple_priv *priv = dev_get_priv(dev);
186 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700187 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300188 void *start, *dst, *line;
Simon Glass42301da2020-07-02 21:12:26 -0600189 int i, j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700190
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300191 start = vid_priv->fb + row * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600192 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700193 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300194 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300195 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300196 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -0700197 line += vid_priv->line_length;
198 }
Simon Glass42301da2020-07-02 21:12:26 -0600199 ret = vidconsole_sync_copy(dev, start, line);
200 if (ret)
201 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700202
203 return 0;
204}
205
206static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
207 uint count)
208{
209 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300210 struct console_simple_priv *priv = dev_get_priv(dev);
211 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600212 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700213 void *dst;
214 void *src;
Simon Glass42301da2020-07-02 21:12:26 -0600215 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700216
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300217 dst = vid_priv->fb + rowdst * fontdata->height * pbytes;
218 src = vid_priv->fb + rowsrc * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -0700219
220 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -0600221 ret = vidconsole_memmove(dev, dst, src,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300222 fontdata->height * pbytes * count);
Simon Glass42301da2020-07-02 21:12:26 -0600223 if (ret)
224 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700225 src += vid_priv->line_length;
226 dst += vid_priv->line_length;
227 }
228
229 return 0;
230}
231
Janne Grunau5548c362024-03-16 22:50:19 +0100232static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700233{
Simon Glass52c10c52016-01-14 18:10:37 -0700234 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700235 struct udevice *vid = dev->parent;
236 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300237 struct console_simple_priv *priv = dev_get_priv(dev);
238 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700239 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300240 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600241 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100242 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300243 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100244 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700245
Simon Glass52c10c52016-01-14 18:10:37 -0700246 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
247 return -EAGAIN;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300248 x = y;
249 linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
250 start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600251 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700252
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300253 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300254 if (ret)
255 return ret;
Simon Glass42301da2020-07-02 21:12:26 -0600256 /* Add a line to allow for the first pixels writen */
257 ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
258 if (ret)
259 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700260
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300261 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700262}
263
Simon Glass87aae882016-01-18 19:52:19 -0700264struct vidconsole_ops console_ops_1 = {
265 .putc_xy = console_putc_xy_1,
266 .move_rows = console_move_rows_1,
267 .set_row = console_set_row_1,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300268 .get_font_size = console_simple_get_font_size,
269 .get_font = console_simple_get_font,
270 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700271};
272
273struct vidconsole_ops console_ops_2 = {
274 .putc_xy = console_putc_xy_2,
275 .move_rows = console_move_rows_2,
276 .set_row = console_set_row_2,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300277 .get_font_size = console_simple_get_font_size,
278 .get_font = console_simple_get_font,
279 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700280};
281
282struct vidconsole_ops console_ops_3 = {
283 .putc_xy = console_putc_xy_3,
284 .move_rows = console_move_rows_3,
285 .set_row = console_set_row_3,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300286 .get_font_size = console_simple_get_font_size,
287 .get_font = console_simple_get_font,
288 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700289};
290
291U_BOOT_DRIVER(vidconsole_1) = {
292 .name = "vidconsole1",
293 .id = UCLASS_VIDEO_CONSOLE,
294 .ops = &console_ops_1,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300295 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300296 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700297};
298
299U_BOOT_DRIVER(vidconsole_2) = {
300 .name = "vidconsole2",
301 .id = UCLASS_VIDEO_CONSOLE,
302 .ops = &console_ops_2,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300303 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300304 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700305};
306
307U_BOOT_DRIVER(vidconsole_3) = {
308 .name = "vidconsole3",
309 .id = UCLASS_VIDEO_CONSOLE,
310 .ops = &console_ops_3,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300311 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300312 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700313};