1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2015 Google, Inc
4 * (C) Copyright 2015
5 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
6 * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
7 */
8
9#include <common.h>
10#include <charset.h>
11#include <dm.h>
12#include <video.h>
13#include <video_console.h>
14#include <video_font.h>		/* Get font data, width and height */
15#include "vidconsole_internal.h"
16
17static int console_set_row(struct udevice *dev, uint row, int clr)
18{
19	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
20	struct console_simple_priv *priv = dev_get_priv(dev);
21	struct video_fontdata *fontdata = priv->fontdata;
22	void *line, *dst, *end;
23	int pixels = fontdata->height * vid_priv->xsize;
24	int ret;
25	int i;
26	int pbytes;
27
28	ret = check_bpix_support(vid_priv->bpix);
29	if (ret)
30		return ret;
31
32	line = vid_priv->fb + row * fontdata->height * vid_priv->line_length;
33	dst = line;
34	pbytes = VNBYTES(vid_priv->bpix);
35	for (i = 0; i < pixels; i++)
36		fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
37	end = dst;
38
39	ret = vidconsole_sync_copy(dev, line, end);
40	if (ret)
41		return ret;
42
43	return 0;
44}
45
46static int console_move_rows(struct udevice *dev, uint rowdst,
47			     uint rowsrc, uint count)
48{
49	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
50	struct console_simple_priv *priv = dev_get_priv(dev);
51	struct video_fontdata *fontdata = priv->fontdata;
52	void *dst;
53	void *src;
54	int size;
55	int ret;
56
57	dst = vid_priv->fb + rowdst * fontdata->height * vid_priv->line_length;
58	src = vid_priv->fb + rowsrc * fontdata->height * vid_priv->line_length;
59	size = fontdata->height * vid_priv->line_length * count;
60	ret = vidconsole_memmove(dev, dst, src, size);
61	if (ret)
62		return ret;
63
64	return 0;
65}
66
67static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp)
68{
69	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
70	struct udevice *vid = dev->parent;
71	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
72	struct console_simple_priv *priv = dev_get_priv(dev);
73	struct video_fontdata *fontdata = priv->fontdata;
74	int pbytes = VNBYTES(vid_priv->bpix);
75	int x, linenum, ret;
76	void *start, *line;
77	u8 ch = console_utf_to_cp437(cp);
78	uchar *pfont = fontdata->video_fontdata +
79			ch * fontdata->char_pixel_bytes;
80
81	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
82		return -EAGAIN;
83	linenum = y;
84	x = VID_TO_PIXEL(x_frac);
85	start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
86	line = start;
87
88	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
89		return -EAGAIN;
90
91	ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
92	if (ret)
93		return ret;
94
95	ret = vidconsole_sync_copy(dev, start, line);
96	if (ret)
97		return ret;
98
99	return VID_TO_POS(fontdata->width);
100}
101
102static int console_set_cursor_visible(struct udevice *dev, bool visible,
103				      uint x, uint y, uint index)
104{
105	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
106	struct udevice *vid = dev->parent;
107	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
108	struct console_simple_priv *priv = dev_get_priv(dev);
109	struct video_fontdata *fontdata = priv->fontdata;
110	int pbytes = VNBYTES(vid_priv->bpix);
111	void *start, *line;
112
113	/* for now, this is not used outside expo */
114	if (!IS_ENABLED(CONFIG_EXPO))
115		return -ENOSYS;
116
117	x += index * fontdata->width;
118	start = vid_priv->fb + y * vid_priv->line_length + x * pbytes;
119
120	/* place the cursor 1 pixel before the start of the next char */
121	x -= 1;
122
123	line = start;
124	draw_cursor_vertically(&line, vid_priv, vc_priv->y_charsize,
125			       NORMAL_DIRECTION);
126
127	return 0;
128}
129
130struct vidconsole_ops console_ops = {
131	.putc_xy	= console_putc_xy,
132	.move_rows	= console_move_rows,
133	.set_row	= console_set_row,
134	.get_font_size	= console_simple_get_font_size,
135	.get_font	= console_simple_get_font,
136	.select_font	= console_simple_select_font,
137	.set_cursor_visible	= console_set_cursor_visible,
138};
139
140U_BOOT_DRIVER(vidconsole_normal) = {
141	.name		= "vidconsole0",
142	.id		= UCLASS_VIDEO_CONSOLE,
143	.ops		= &console_ops,
144	.probe		= console_probe,
145	.priv_auto	= sizeof(struct console_simple_priv),
146};
147