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 <charset.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 */
14 #include "vidconsole_internal.h"
15 
console_set_row(struct udevice * dev,uint row,int clr)16 static int console_set_row(struct udevice *dev, uint row, int clr)
17 {
18 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
19 	struct console_simple_priv *priv = dev_get_priv(dev);
20 	struct video_fontdata *fontdata = priv->fontdata;
21 	void *line, *dst, *end;
22 	int pixels = fontdata->height * vid_priv->xsize;
23 	int ret;
24 	int i;
25 	int pbytes;
26 
27 	ret = check_bpix_support(vid_priv->bpix);
28 	if (ret)
29 		return ret;
30 
31 	line = vid_priv->fb + row * fontdata->height * vid_priv->line_length;
32 	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;
37 
38 	video_damage(dev->parent,
39 		     0,
40 		     fontdata->height * row,
41 		     vid_priv->xsize,
42 		     fontdata->height);
43 
44 	return 0;
45 }
46 
console_move_rows(struct udevice * dev,uint rowdst,uint rowsrc,uint count)47 static int console_move_rows(struct udevice *dev, uint rowdst,
48 			     uint rowsrc, uint count)
49 {
50 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
51 	struct console_simple_priv *priv = dev_get_priv(dev);
52 	struct video_fontdata *fontdata = priv->fontdata;
53 	void *dst;
54 	void *src;
55 	int size;
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 	memmove(dst, src, size);
61 
62 	video_damage(dev->parent,
63 		     0,
64 		     fontdata->height * rowdst,
65 		     vid_priv->xsize,
66 		     fontdata->height * count);
67 
68 	return 0;
69 }
70 
console_putc_xy(struct udevice * dev,uint x_frac,uint y,int cp)71 static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp)
72 {
73 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
74 	struct udevice *vid = dev->parent;
75 	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
76 	struct console_simple_priv *priv = dev_get_priv(dev);
77 	struct video_fontdata *fontdata = priv->fontdata;
78 	int pbytes = VNBYTES(vid_priv->bpix);
79 	int x, linenum, ret;
80 	void *start, *line;
81 	u8 ch = console_utf_to_cp437(cp);
82 	uchar *pfont = fontdata->video_fontdata +
83 			ch * fontdata->char_pixel_bytes;
84 
85 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
86 		return -EAGAIN;
87 	linenum = y;
88 	x = VID_TO_PIXEL(x_frac);
89 	start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
90 	line = start;
91 
92 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
93 		return -EAGAIN;
94 
95 	ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
96 	if (ret)
97 		return ret;
98 
99 	video_damage(dev->parent,
100 		     x,
101 		     y,
102 		     fontdata->width,
103 		     fontdata->height);
104 
105 	return VID_TO_POS(fontdata->width);
106 }
107 
console_set_cursor_visible(struct udevice * dev,bool visible,uint x,uint y,uint index)108 static int console_set_cursor_visible(struct udevice *dev, bool visible,
109 				      uint x, uint y, uint index)
110 {
111 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
112 	struct udevice *vid = dev->parent;
113 	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
114 	struct console_simple_priv *priv = dev_get_priv(dev);
115 	struct video_fontdata *fontdata = priv->fontdata;
116 	int pbytes = VNBYTES(vid_priv->bpix);
117 	void *start, *line;
118 
119 	/* for now, this is not used outside expo */
120 	if (!IS_ENABLED(CONFIG_EXPO))
121 		return -ENOSYS;
122 
123 	x += index * fontdata->width;
124 	start = vid_priv->fb + y * vid_priv->line_length + x * pbytes;
125 
126 	/* place the cursor 1 pixel before the start of the next char */
127 	x -= 1;
128 
129 	line = start;
130 	draw_cursor_vertically(&line, vid_priv, vc_priv->y_charsize,
131 			       NORMAL_DIRECTION);
132 
133 	return 0;
134 }
135 
136 struct vidconsole_ops console_ops = {
137 	.putc_xy	= console_putc_xy,
138 	.move_rows	= console_move_rows,
139 	.set_row	= console_set_row,
140 	.get_font_size	= console_simple_get_font_size,
141 	.get_font	= console_simple_get_font,
142 	.select_font	= console_simple_select_font,
143 	.set_cursor_visible	= console_set_cursor_visible,
144 };
145 
146 U_BOOT_DRIVER(vidconsole_normal) = {
147 	.name		= "vidconsole0",
148 	.id		= UCLASS_VIDEO_CONSOLE,
149 	.ops		= &console_ops,
150 	.probe		= console_probe,
151 	.priv_auto	= sizeof(struct console_simple_priv),
152 };
153