blob: 70cc62d1781ab58126682ee7d36c773101dc3f17 [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>
10#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);
19 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030020 void *start, *dst, *line;
Simon Glass87aae882016-01-18 19:52:19 -070021 int i, j;
Simon Glass42301da2020-07-02 21:12:26 -060022 int ret;
Simon Glass87aae882016-01-18 19:52:19 -070023
Simon Glass42301da2020-07-02 21:12:26 -060024 start = vid_priv->fb + vid_priv->line_length -
Simon Glass87aae882016-01-18 19:52:19 -070025 (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -060026 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070027 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030028 dst = line;
29 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
30 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -070031 line += vid_priv->line_length;
32 }
Simon Glass42301da2020-07-02 21:12:26 -060033 ret = vidconsole_sync_copy(dev, start, line);
34 if (ret)
35 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070036
37 return 0;
38}
39
40static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030041 uint count)
Simon Glass87aae882016-01-18 19:52:19 -070042{
43 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Simon Glass80daa3f2020-07-02 21:12:16 -060044 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -070045 void *dst;
46 void *src;
Simon Glass42301da2020-07-02 21:12:26 -060047 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -070048
49 dst = vid_priv->fb + vid_priv->line_length -
50 (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
51 src = vid_priv->fb + vid_priv->line_length -
52 (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
53
54 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -060055 ret = vidconsole_memmove(dev, dst, src,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030056 VIDEO_FONT_HEIGHT * pbytes * count);
Simon Glass42301da2020-07-02 21:12:26 -060057 if (ret)
58 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070059 src += vid_priv->line_length;
60 dst += vid_priv->line_length;
61 }
62
63 return 0;
64}
65
Simon Glass52c10c52016-01-14 18:10:37 -070066static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
Simon Glass87aae882016-01-18 19:52:19 -070067{
Simon Glass52c10c52016-01-14 18:10:37 -070068 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -070069 struct udevice *vid = dev->parent;
70 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
71 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030072 int x, linenum, ret;
Simon Glass42301da2020-07-02 21:12:26 -060073 void *start, *line;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030074 uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
Simon Glass87aae882016-01-18 19:52:19 -070075
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030076 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
77 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -060078 linenum = VID_TO_PIXEL(x_frac) + 1;
79 x = y + 1;
Simon Glass42301da2020-07-02 21:12:26 -060080 start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
81 line = start;
Simon Glass87aae882016-01-18 19:52:19 -070082
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030083 ret = fill_char_horizontally(pfont, &line, vid_priv, FLIPPED_DIRECTION);
84 if (ret)
85 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070086
Simon Glass42301da2020-07-02 21:12:26 -060087 /* We draw backwards from 'start, so account for the first line */
88 ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
89 if (ret)
90 return ret;
Simon Glass87aae882016-01-18 19:52:19 -070091
Simon Glass52c10c52016-01-14 18:10:37 -070092 return VID_TO_POS(VIDEO_FONT_WIDTH);
Simon Glass87aae882016-01-18 19:52:19 -070093}
94
95
96static int console_set_row_2(struct udevice *dev, uint row, int clr)
97{
98 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030099 void *start, *line, *dst, *end;
Simon Glass87aae882016-01-18 19:52:19 -0700100 int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
Simon Glass42301da2020-07-02 21:12:26 -0600101 int i, ret;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300102 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700103
Simon Glass42301da2020-07-02 21:12:26 -0600104 start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
Simon Glass87aae882016-01-18 19:52:19 -0700105 (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600106 line = start;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300107 dst = line;
108 for (i = 0; i < pixels; i++)
109 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
110 end = dst;
Simon Glass42301da2020-07-02 21:12:26 -0600111 ret = vidconsole_sync_copy(dev, start, end);
112 if (ret)
113 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700114
115 return 0;
116}
117
118static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
119 uint count)
120{
121 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
122 void *dst;
123 void *src;
124 void *end;
125
126 end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
127 dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
128 vid_priv->line_length;
129 src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
130 vid_priv->line_length;
Simon Glass42301da2020-07-02 21:12:26 -0600131 vidconsole_memmove(dev, dst, src,
132 VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
Simon Glass87aae882016-01-18 19:52:19 -0700133
134 return 0;
135}
136
Simon Glass52c10c52016-01-14 18:10:37 -0700137static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
Simon Glass87aae882016-01-18 19:52:19 -0700138{
Simon Glass52c10c52016-01-14 18:10:37 -0700139 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700140 struct udevice *vid = dev->parent;
141 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Simon Glass80daa3f2020-07-02 21:12:16 -0600142 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300143 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600144 void *start, *line;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300145 uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
Simon Glass87aae882016-01-18 19:52:19 -0700146
Simon Glass52c10c52016-01-14 18:10:37 -0700147 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
148 return -EAGAIN;
Simon Glass80daa3f2020-07-02 21:12:16 -0600149 linenum = vid_priv->ysize - y - 1;
Simon Glassf50a6b92020-07-02 21:12:17 -0600150 x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
Simon Glass42301da2020-07-02 21:12:26 -0600151 start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
152 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700153
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300154 ret = fill_char_vertically(pfont, &line, vid_priv, FLIPPED_DIRECTION);
155 if (ret)
156 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700157
Simon Glass42301da2020-07-02 21:12:26 -0600158 /* Add 4 bytes to allow for the first pixel writen */
159 ret = vidconsole_sync_copy(dev, start + 4, line);
160 if (ret)
161 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700162
Simon Glass52c10c52016-01-14 18:10:37 -0700163 return VID_TO_POS(VIDEO_FONT_WIDTH);
Simon Glass87aae882016-01-18 19:52:19 -0700164}
165
166static int console_set_row_3(struct udevice *dev, uint row, int clr)
167{
168 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
169 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300170 void *start, *dst, *line;
Simon Glass42301da2020-07-02 21:12:26 -0600171 int i, j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700172
Simon Glass42301da2020-07-02 21:12:26 -0600173 start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
174 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700175 for (j = 0; j < vid_priv->ysize; j++) {
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300176 dst = line;
177 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
178 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
Simon Glass87aae882016-01-18 19:52:19 -0700179 line += vid_priv->line_length;
180 }
Simon Glass42301da2020-07-02 21:12:26 -0600181 ret = vidconsole_sync_copy(dev, start, line);
182 if (ret)
183 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700184
185 return 0;
186}
187
188static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
189 uint count)
190{
191 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Simon Glass80daa3f2020-07-02 21:12:16 -0600192 int pbytes = VNBYTES(vid_priv->bpix);
Simon Glass87aae882016-01-18 19:52:19 -0700193 void *dst;
194 void *src;
Simon Glass42301da2020-07-02 21:12:26 -0600195 int j, ret;
Simon Glass87aae882016-01-18 19:52:19 -0700196
197 dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
198 src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
199
200 for (j = 0; j < vid_priv->ysize; j++) {
Simon Glass42301da2020-07-02 21:12:26 -0600201 ret = vidconsole_memmove(dev, dst, src,
202 VIDEO_FONT_HEIGHT * pbytes * count);
203 if (ret)
204 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700205 src += vid_priv->line_length;
206 dst += vid_priv->line_length;
207 }
208
209 return 0;
210}
211
Simon Glass52c10c52016-01-14 18:10:37 -0700212static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
Simon Glass87aae882016-01-18 19:52:19 -0700213{
Simon Glass52c10c52016-01-14 18:10:37 -0700214 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass87aae882016-01-18 19:52:19 -0700215 struct udevice *vid = dev->parent;
216 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
217 int pbytes = VNBYTES(vid_priv->bpix);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300218 int linenum, x, ret;
Simon Glass42301da2020-07-02 21:12:26 -0600219 void *start, *line;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300220 uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
Simon Glass87aae882016-01-18 19:52:19 -0700221
Simon Glass52c10c52016-01-14 18:10:37 -0700222 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
223 return -EAGAIN;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300224 x = y;
225 linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
226 start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
Simon Glass42301da2020-07-02 21:12:26 -0600227 line = start;
Simon Glass87aae882016-01-18 19:52:19 -0700228
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300229 ret = fill_char_horizontally(pfont, &line, vid_priv, NORMAL_DIRECTION);
230 if (ret)
231 return ret;
Simon Glass42301da2020-07-02 21:12:26 -0600232 /* Add a line to allow for the first pixels writen */
233 ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
234 if (ret)
235 return ret;
Simon Glass87aae882016-01-18 19:52:19 -0700236
Simon Glass52c10c52016-01-14 18:10:37 -0700237 return VID_TO_POS(VIDEO_FONT_WIDTH);
Simon Glass87aae882016-01-18 19:52:19 -0700238}
239
Simon Glass87aae882016-01-18 19:52:19 -0700240struct vidconsole_ops console_ops_1 = {
241 .putc_xy = console_putc_xy_1,
242 .move_rows = console_move_rows_1,
243 .set_row = console_set_row_1,
244};
245
246struct vidconsole_ops console_ops_2 = {
247 .putc_xy = console_putc_xy_2,
248 .move_rows = console_move_rows_2,
249 .set_row = console_set_row_2,
250};
251
252struct vidconsole_ops console_ops_3 = {
253 .putc_xy = console_putc_xy_3,
254 .move_rows = console_move_rows_3,
255 .set_row = console_set_row_3,
256};
257
258U_BOOT_DRIVER(vidconsole_1) = {
259 .name = "vidconsole1",
260 .id = UCLASS_VIDEO_CONSOLE,
261 .ops = &console_ops_1,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300262 .probe = console_probe,
Simon Glass87aae882016-01-18 19:52:19 -0700263};
264
265U_BOOT_DRIVER(vidconsole_2) = {
266 .name = "vidconsole2",
267 .id = UCLASS_VIDEO_CONSOLE,
268 .ops = &console_ops_2,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300269 .probe = console_probe,
Simon Glass87aae882016-01-18 19:52:19 -0700270};
271
272U_BOOT_DRIVER(vidconsole_3) = {
273 .name = "vidconsole3",
274 .id = UCLASS_VIDEO_CONSOLE,
275 .ops = &console_ops_3,
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300276 .probe = console_probe,
Simon Glass87aae882016-01-18 19:52:19 -0700277};