blob: 51ac8cc78e9daa56cb363f9f66f168bd81c55dbd [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass23825a92016-01-18 19:52:18 -07002/*
3 * Copyright (c) 2015 Google, Inc
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +03004 * (C) Copyright 2015
Simon Glass23825a92016-01-18 19:52:18 -07005 * 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 Glass23825a92016-01-18 19:52:18 -07007 */
8
Janne Grunau5548c362024-03-16 22:50:19 +01009#include <charset.h>
Simon Glass23825a92016-01-18 19:52:18 -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 Glass23825a92016-01-18 19:52:18 -070015
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030016static int console_set_row(struct udevice *dev, uint row, int clr)
Simon Glass23825a92016-01-18 19:52:18 -070017{
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;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030021 void *line, *dst, *end;
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030022 int pixels = fontdata->height * vid_priv->xsize;
Simon Glass03a96ae2020-07-02 21:12:24 -060023 int ret;
Simon Glass6c1ca6b2019-12-20 18:10:34 -070024 int i;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030025 int pbytes;
Simon Glass23825a92016-01-18 19:52:18 -070026
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030027 ret = check_bpix_support(vid_priv->bpix);
28 if (ret)
29 return ret;
Simon Glass23825a92016-01-18 19:52:18 -070030
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030031 line = vid_priv->fb + row * fontdata->height * vid_priv->line_length;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030032 dst = line;
33 pbytes = VNBYTES(vid_priv->bpix);
34 for (i = 0; i < pixels; i++)
35 fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
36 end = dst;
Simon Glass23825a92016-01-18 19:52:18 -070037
Simon Glass03a96ae2020-07-02 21:12:24 -060038 ret = vidconsole_sync_copy(dev, line, end);
39 if (ret)
40 return ret;
Simon Glass23825a92016-01-18 19:52:18 -070041
Alexander Graf1b47cf22022-06-10 00:59:17 +020042 video_damage(dev->parent,
43 0,
44 fontdata->height * row,
45 vid_priv->xsize,
46 fontdata->height);
47
Simon Glass23825a92016-01-18 19:52:18 -070048 return 0;
49}
50
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030051static int console_move_rows(struct udevice *dev, uint rowdst,
52 uint rowsrc, uint count)
Simon Glass23825a92016-01-18 19:52:18 -070053{
54 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030055 struct console_simple_priv *priv = dev_get_priv(dev);
56 struct video_fontdata *fontdata = priv->fontdata;
Simon Glass23825a92016-01-18 19:52:18 -070057 void *dst;
58 void *src;
Simon Glass03a96ae2020-07-02 21:12:24 -060059 int size;
60 int ret;
Simon Glass23825a92016-01-18 19:52:18 -070061
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030062 dst = vid_priv->fb + rowdst * fontdata->height * vid_priv->line_length;
63 src = vid_priv->fb + rowsrc * fontdata->height * vid_priv->line_length;
64 size = fontdata->height * vid_priv->line_length * count;
Simon Glass03a96ae2020-07-02 21:12:24 -060065 ret = vidconsole_memmove(dev, dst, src, size);
66 if (ret)
67 return ret;
Simon Glass23825a92016-01-18 19:52:18 -070068
Alexander Graf1b47cf22022-06-10 00:59:17 +020069 video_damage(dev->parent,
70 0,
71 fontdata->height * rowdst,
72 vid_priv->xsize,
73 fontdata->height * count);
74
Simon Glass23825a92016-01-18 19:52:18 -070075 return 0;
76}
77
Janne Grunau5548c362024-03-16 22:50:19 +010078static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp)
Simon Glass23825a92016-01-18 19:52:18 -070079{
Simon Glass52c10c52016-01-14 18:10:37 -070080 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
Simon Glass23825a92016-01-18 19:52:18 -070081 struct udevice *vid = dev->parent;
82 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030083 struct console_simple_priv *priv = dev_get_priv(dev);
84 struct video_fontdata *fontdata = priv->fontdata;
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030085 int pbytes = VNBYTES(vid_priv->bpix);
86 int x, linenum, ret;
87 void *start, *line;
Janne Grunau5548c362024-03-16 22:50:19 +010088 u8 ch = console_utf_to_cp437(cp);
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +030089 uchar *pfont = fontdata->video_fontdata +
Janne Grunau5548c362024-03-16 22:50:19 +010090 ch * fontdata->char_pixel_bytes;
Simon Glass03a96ae2020-07-02 21:12:24 -060091
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +030092 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
93 return -EAGAIN;
94 linenum = y;
95 x = VID_TO_PIXEL(x_frac);
96 start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
Simon Glass03a96ae2020-07-02 21:12:24 -060097 line = start;
Simon Glass52c10c52016-01-14 18:10:37 -070098
99 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
100 return -EAGAIN;
Simon Glass23825a92016-01-18 19:52:18 -0700101
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300102 ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300103 if (ret)
104 return ret;
Simon Glass23825a92016-01-18 19:52:18 -0700105
Alexander Graf1b47cf22022-06-10 00:59:17 +0200106 video_damage(dev->parent,
107 x,
108 y,
109 fontdata->width,
110 fontdata->height);
111
Simon Glass03a96ae2020-07-02 21:12:24 -0600112 ret = vidconsole_sync_copy(dev, start, line);
113 if (ret)
114 return ret;
Simon Glass23825a92016-01-18 19:52:18 -0700115
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300116 return VID_TO_POS(fontdata->width);
Simon Glass52c10c52016-01-14 18:10:37 -0700117}
118
Simon Glass377f79aa2023-10-01 19:13:21 -0600119static int console_set_cursor_visible(struct udevice *dev, bool visible,
120 uint x, uint y, uint index)
121{
122 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
123 struct udevice *vid = dev->parent;
124 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
125 struct console_simple_priv *priv = dev_get_priv(dev);
126 struct video_fontdata *fontdata = priv->fontdata;
127 int pbytes = VNBYTES(vid_priv->bpix);
128 void *start, *line;
129
130 /* for now, this is not used outside expo */
131 if (!IS_ENABLED(CONFIG_EXPO))
132 return -ENOSYS;
133
134 x += index * fontdata->width;
135 start = vid_priv->fb + y * vid_priv->line_length + x * pbytes;
136
137 /* place the cursor 1 pixel before the start of the next char */
138 x -= 1;
139
140 line = start;
141 draw_cursor_vertically(&line, vid_priv, vc_priv->y_charsize,
142 NORMAL_DIRECTION);
143
144 return 0;
145}
146
Dzmitry Sankouskiaea2d2d2023-03-07 13:21:11 +0300147struct vidconsole_ops console_ops = {
148 .putc_xy = console_putc_xy,
149 .move_rows = console_move_rows,
150 .set_row = console_set_row,
Dzmitry Sankouskibb165e42023-03-07 13:21:16 +0300151 .get_font_size = console_simple_get_font_size,
152 .get_font = console_simple_get_font,
153 .select_font = console_simple_select_font,
Simon Glass377f79aa2023-10-01 19:13:21 -0600154 .set_cursor_visible = console_set_cursor_visible,
Simon Glass23825a92016-01-18 19:52:18 -0700155};
156
157U_BOOT_DRIVER(vidconsole_normal) = {
Dzmitry Sankouski7fa964a2023-03-07 13:21:14 +0300158 .name = "vidconsole0",
159 .id = UCLASS_VIDEO_CONSOLE,
160 .ops = &console_ops,
161 .probe = console_probe,
162 .priv_auto = sizeof(struct console_simple_priv),
Simon Glass23825a92016-01-18 19:52:18 -0700163};