blob: 886b25dcfafccba22074f4761cf582ec4b906c66 [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;
24
Simon Glass42301da2020-07-02 21:12:26 -060025 start = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030026 (row + 1) * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -060027 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070028 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030029 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030030 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030031 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -070032 line += vid_priv->line_length;
33 }
34
Alexander Graf1b47cf22022-06-10 00:59:17 +020035 video_damage(dev->parent,
36 vid_priv->xsize - ((row + 1) * fontdata->height),
37 0,
38 fontdata->height,
39 vid_priv->ysize);
40
Simon Glass87aae882016-01-18 19:52:19 -070041 return 0;
42}
43
44static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030045 uint count)
Simon Glass87aae882016-01-18 19:52:19 -070046{
47 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030048 struct console_simple_priv *priv = dev_get_priv(dev);
49 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -060050 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -070051 void *dst;
52 void *src;
Alexander Graff88b6a22022-06-10 00:59:21 +020053 int j;
Simon Glass87aae882016-01-18 19:52:19 -070054
55 dst = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030056 (rowdst + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070057 src = vid_priv->fb + vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030058 (rowsrc + count) * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -070059
60 for (j = 0; j < vid_priv->ysize; j++) {
Alexander Graff88b6a22022-06-10 00:59:21 +020061 memmove(dst, src, fontdata->height * pbytes * count);
Simon Glass87aae882016-01-18 19:52:19 -070062 src += vid_priv->line_length;
63 dst += vid_priv->line_length;
64 }
65
Alexander Graf1b47cf22022-06-10 00:59:17 +020066 video_damage(dev->parent,
67 vid_priv->xsize - ((rowdst + count) * fontdata->height),
68 0,
69 count * fontdata->height,
70 vid_priv->ysize);
71
Simon Glass87aae882016-01-18 19:52:19 -070072 return 0;
73}
74
Janne Grunau5548c362024-03-16 22:50:19 +010075static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -070076{
Simon Glass52c10c52016-01-14 18:10:37 -070077 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -070078 struct udevice *vid = dev->parent;
79 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030080 struct console_simple_priv *priv = dev_get_priv(dev);
81 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -070082 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030083 int x, linenum, ret;
Simon Glass42301da2020-07-02 21:12:26 -060084 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +010085 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030086 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +010087 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -070088
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030089 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
90 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -060091 linenum = VID_TO_PIXEL(x_frac) + 1;
92 x = y + 1;
Simon Glass42301da2020-07-02 21:12:26 -060093 start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
94 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070095
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030096 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030097 if (ret)
98 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070099
Simon Glass42301da2020-07-02 21:12:26 -0600100 /* We draw backwards from 'start, so account for the first line */
Alexander Graf1b47cf22022-06-10 00:59:17 +0200101 video_damage(dev->parent,
102 vid_priv->xsize - y - fontdata->height,
103 linenum - 1,
104 fontdata->height,
105 fontdata->width);
106
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300107 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700108}
109
Simon Glass87aae882016-01-18 19:52:19 -0700110static int console_set_row_2(struct udevice *dev, uint row, int clr)
111{
112 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300113 struct console_simple_priv *priv = dev_get_priv(dev);
114 struct video_fontdata *fontdata = priv->fontdata;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300115 void *start, *line, *dst, *end;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300116 int pixels = fontdata->height * vid_priv->xsize;
Alexander Graff88b6a22022-06-10 00:59:21 +0200117 int i;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300118 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700119
Simon Glass42301da2020-07-02 21:12:26 -0600120 start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300121 (row + 1) * fontdata->height * vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600122 line = start;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300123 dst = line;
124 for (i = 0; i < pixels; i++)
125 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
126 end = dst;
Simon Glass87aae882016-01-18 19:52:19 -0700127
Alexander Graf1b47cf22022-06-10 00:59:17 +0200128 video_damage(dev->parent,
129 0,
130 vid_priv->ysize - (row + 1) * fontdata->height,
131 vid_priv->xsize,
132 fontdata->height);
133
Simon Glass87aae882016-01-18 19:52:19 -0700134 return 0;
135}
136
137static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
138 uint count)
139{
140 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300141 struct console_simple_priv *priv = dev_get_priv(dev);
142 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700143 void *dst;
144 void *src;
145 void *end;
146
147 end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300148 dst = end - (rowdst + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700149 vid_priv->line_length;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300150 src = end - (rowsrc + count) * fontdata->height *
Simon Glass87aae882016-01-18 19:52:19 -0700151 vid_priv->line_length;
Alexander Graff88b6a22022-06-10 00:59:21 +0200152 memmove(dst, src, fontdata->height * vid_priv->line_length * count);
Simon Glass87aae882016-01-18 19:52:19 -0700153
Alexander Graf1b47cf22022-06-10 00:59:17 +0200154 video_damage(dev->parent,
155 0,
156 vid_priv->ysize - (rowdst + count) * fontdata->height,
157 vid_priv->xsize,
158 count * fontdata->height);
159
Simon Glass87aae882016-01-18 19:52:19 -0700160 return 0;
161}
162
Janne Grunau5548c362024-03-16 22:50:19 +0100163static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700164{
Simon Glass52c10c52016-01-14 18:10:37 -0700165 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700166 struct udevice *vid = dev->parent;
167 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300168 struct console_simple_priv *priv = dev_get_priv(dev);
169 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600170 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300171 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600172 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100173 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300174 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100175 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700176
Simon Glass52c10c52016-01-14 18:10:37 -0700177 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
178 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -0600179 linenum = vid_priv->ysize - y - 1;
Simon Glassf50a6b92020-07-02 21:12:17 -0600180 x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
Simon Glass42301da2020-07-02 21:12:26 -0600181 start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
182 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700183
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300184 ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300185 if (ret)
186 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700187
Alexander Graf1b47cf22022-06-10 00:59:17 +0200188 video_damage(dev->parent,
189 x - fontdata->width + 1,
190 linenum - fontdata->height + 1,
191 fontdata->width,
192 fontdata->height);
193
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300194 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700195}
196
197static int console_set_row_3(struct udevice *dev, uint row, int clr)
198{
199 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300200 struct console_simple_priv *priv = dev_get_priv(dev);
201 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700202 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300203 void *start, *dst, *line;
Alexander Graff88b6a22022-06-10 00:59:21 +0200204 int i, j;
Simon Glass87aae882016-01-18 19:52:19 -0700205
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300206 start = vid_priv->fb + row * fontdata->height * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600207 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700208 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300209 dst = line;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300210 for (i = 0; i < fontdata->height; i++)
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300211 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -0700212 line += vid_priv->line_length;
213 }
214
Alexander Graf1b47cf22022-06-10 00:59:17 +0200215 video_damage(dev->parent,
216 row * fontdata->height,
217 0,
218 fontdata->height,
219 vid_priv->ysize);
220
Simon Glass87aae882016-01-18 19:52:19 -0700221 return 0;
222}
223
224static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
225 uint count)
226{
227 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300228 struct console_simple_priv *priv = dev_get_priv(dev);
229 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass80daa3f2020-07-02 21:12:16 -0600230 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700231 void *dst;
232 void *src;
Alexander Graff88b6a22022-06-10 00:59:21 +0200233 int j;
Simon Glass87aae882016-01-18 19:52:19 -0700234
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300235 dst = vid_priv->fb + rowdst * fontdata->height * pbytes;
236 src = vid_priv->fb + rowsrc * fontdata->height * pbytes;
Simon Glass87aae882016-01-18 19:52:19 -0700237
238 for (j = 0; j < vid_priv->ysize; j++) {
Alexander Graff88b6a22022-06-10 00:59:21 +0200239 memmove(dst, src, fontdata->height * pbytes * count);
Simon Glass87aae882016-01-18 19:52:19 -0700240 src += vid_priv->line_length;
241 dst += vid_priv->line_length;
242 }
243
Alexander Graf1b47cf22022-06-10 00:59:17 +0200244 video_damage(dev->parent,
245 rowdst * fontdata->height,
246 0,
247 count * fontdata->height,
248 vid_priv->ysize);
249
Simon Glass87aae882016-01-18 19:52:19 -0700250 return 0;
251}
252
Janne Grunau5548c362024-03-16 22:50:19 +0100253static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass87aae882016-01-18 19:52:19 -0700254{
Simon Glass52c10c52016-01-14 18:10:37 -0700255 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700256 struct udevice *vid = dev->parent;
257 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300258 struct console_simple_priv *priv = dev_get_priv(dev);
259 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass87aae882016-01-18 19:52:19 -0700260 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300261 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600262 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +0100263 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300264 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +0100265 ch * fontdata->char_pixel_bytes;
Simon Glass87aae882016-01-18 19:52:19 -0700266
Simon Glass52c10c52016-01-14 18:10:37 -0700267 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
268 return -EAGAIN;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300269 x = y;
270 linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
271 start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600272 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700273
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300274 ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300275 if (ret)
276 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700277
Alexander Graf1b47cf22022-06-10 00:59:17 +0200278 video_damage(dev->parent,
279 y,
280 linenum - fontdata->width + 1,
281 fontdata->height,
282 fontdata->width);
283
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300284 return VID_TO_POS(fontdata->width);
Simon Glass87aae882016-01-18 19:52:19 -0700285}
286
Simon Glass87aae882016-01-18 19:52:19 -0700287struct vidconsole_ops console_ops_1 = {
288 .putc_xy = console_putc_xy_1,
289 .move_rows = console_move_rows_1,
290 .set_row = console_set_row_1,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300291 .get_font_size = console_simple_get_font_size,
292 .get_font = console_simple_get_font,
293 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700294};
295
296struct vidconsole_ops console_ops_2 = {
297 .putc_xy = console_putc_xy_2,
298 .move_rows = console_move_rows_2,
299 .set_row = console_set_row_2,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300300 .get_font_size = console_simple_get_font_size,
301 .get_font = console_simple_get_font,
302 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700303};
304
305struct vidconsole_ops console_ops_3 = {
306 .putc_xy = console_putc_xy_3,
307 .move_rows = console_move_rows_3,
308 .set_row = console_set_row_3,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300309 .get_font_size = console_simple_get_font_size,
310 .get_font = console_simple_get_font,
311 .select_font = console_simple_select_font,
Simon Glass87aae882016-01-18 19:52:19 -0700312};
313
314U_BOOT_DRIVER(vidconsole_1) = {
315 .name = "vidconsole1",
316 .id = UCLASS_VIDEO_CONSOLE,
317 .ops = &console_ops_1,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300318 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300319 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700320};
321
322U_BOOT_DRIVER(vidconsole_2) = {
323 .name = "vidconsole2",
324 .id = UCLASS_VIDEO_CONSOLE,
325 .ops = &console_ops_2,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300326 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300327 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700328};
329
330U_BOOT_DRIVER(vidconsole_3) = {
331 .name = "vidconsole3",
332 .id = UCLASS_VIDEO_CONSOLE,
333 .ops = &console_ops_3,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300334 .probe = console_probe,
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300335 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass87aae882016-01-18 19:52:19 -0700336};