]>
Commit | Line | Data |
---|---|---|
31547259 DS |
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 <[email protected]> | |
7 | */ | |
8 | ||
9 | #include <video.h> | |
10 | #include <video_console.h> | |
11 | #include <dm.h> | |
39c1fa2c | 12 | #include <video_font.h> |
31547259 DS |
13 | #include "vidconsole_internal.h" |
14 | ||
39c1fa2c DS |
15 | /** |
16 | * console_set_font() - prepare vidconsole for chosen font. | |
17 | * | |
18 | * @dev vidconsole device | |
19 | * @fontdata pointer to font data struct | |
20 | */ | |
21 | static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata) | |
22 | { | |
23 | struct console_simple_priv *priv = dev_get_priv(dev); | |
24 | struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); | |
25 | struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); | |
26 | ||
27 | debug("console_simple: setting %s font\n", fontdata->name); | |
28 | debug("width: %d\n", fontdata->width); | |
29 | debug("byte width: %d\n", fontdata->byte_width); | |
30 | debug("height: %d\n", fontdata->height); | |
31 | ||
32 | priv->fontdata = fontdata; | |
33 | vc_priv->x_charsize = fontdata->width; | |
34 | vc_priv->y_charsize = fontdata->height; | |
35 | if (vid_priv->rot % 2) { | |
36 | vc_priv->cols = vid_priv->ysize / fontdata->width; | |
37 | vc_priv->rows = vid_priv->xsize / fontdata->height; | |
38 | vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize); | |
39 | } else { | |
40 | vc_priv->cols = vid_priv->xsize / fontdata->width; | |
41 | vc_priv->rows = vid_priv->ysize / fontdata->height; | |
42 | } | |
43 | ||
44 | return 0; | |
45 | } | |
46 | ||
31547259 DS |
47 | int check_bpix_support(int bpix) |
48 | { | |
86fbee60 | 49 | if (bpix == VIDEO_BPP8 && CONFIG_IS_ENABLED(VIDEO_BPP8)) |
31547259 | 50 | return 0; |
86fbee60 | 51 | else if (bpix == VIDEO_BPP16 && CONFIG_IS_ENABLED(VIDEO_BPP16)) |
31547259 | 52 | return 0; |
86fbee60 | 53 | else if (bpix == VIDEO_BPP32 && CONFIG_IS_ENABLED(VIDEO_BPP32)) |
31547259 DS |
54 | return 0; |
55 | else | |
56 | return -ENOSYS; | |
57 | } | |
58 | ||
59 | inline void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step) | |
60 | { | |
61 | u8 *dst_byte = *dstp; | |
62 | ||
63 | if (pbytes == 4) { | |
64 | u32 *dst = *dstp; | |
65 | *dst = value; | |
66 | } | |
67 | if (pbytes == 2) { | |
68 | u16 *dst = *dstp; | |
69 | *dst = value; | |
70 | } | |
71 | if (pbytes == 1) { | |
72 | u8 *dst = *dstp; | |
73 | *dst = value; | |
74 | } | |
75 | *dstp = dst_byte + step; | |
76 | } | |
77 | ||
78 | int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv, | |
39c1fa2c | 79 | struct video_fontdata *fontdata, bool direction) |
31547259 | 80 | { |
02db4ec9 | 81 | int step, line_step, pbytes, bitcount, width_remainder, ret; |
31547259 DS |
82 | void *dst; |
83 | ||
84 | ret = check_bpix_support(vid_priv->bpix); | |
85 | if (ret) | |
86 | return ret; | |
87 | ||
88 | pbytes = VNBYTES(vid_priv->bpix); | |
89 | if (direction) { | |
90 | step = -pbytes; | |
91 | line_step = -vid_priv->line_length; | |
92 | } else { | |
93 | step = pbytes; | |
94 | line_step = vid_priv->line_length; | |
95 | } | |
96 | ||
39c1fa2c DS |
97 | width_remainder = fontdata->width % 8; |
98 | for (int row = 0; row < fontdata->height; row++) { | |
02db4ec9 DS |
99 | uchar bits; |
100 | ||
101 | bitcount = 8; | |
31547259 | 102 | dst = *line; |
39c1fa2c | 103 | for (int col = 0; col < fontdata->byte_width; col++) { |
02db4ec9 | 104 | if (width_remainder) { |
39c1fa2c | 105 | bool is_last_col = (fontdata->byte_width - col == 1); |
02db4ec9 | 106 | |
39c1fa2c | 107 | if (is_last_col) |
02db4ec9 DS |
108 | bitcount = width_remainder; |
109 | } | |
110 | bits = pfont[col]; | |
111 | ||
112 | for (int bit = 0; bit < bitcount; bit++) { | |
113 | u32 value = (bits & 0x80) ? | |
114 | vid_priv->colour_fg : | |
115 | vid_priv->colour_bg; | |
116 | ||
117 | fill_pixel_and_goto_next(&dst, | |
118 | value, | |
119 | pbytes, | |
120 | step | |
121 | ); | |
122 | bits <<= 1; | |
123 | } | |
31547259 DS |
124 | } |
125 | *line += line_step; | |
39c1fa2c | 126 | pfont += fontdata->byte_width; |
31547259 DS |
127 | } |
128 | return ret; | |
129 | } | |
130 | ||
131 | int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv, | |
39c1fa2c | 132 | struct video_fontdata *fontdata, bool direction) |
31547259 | 133 | { |
02db4ec9 | 134 | int step, line_step, pbytes, bitcount = 8, width_remainder, ret; |
31547259 | 135 | void *dst; |
02db4ec9 | 136 | u8 mask; |
31547259 DS |
137 | |
138 | ret = check_bpix_support(vid_priv->bpix); | |
139 | if (ret) | |
140 | return ret; | |
141 | ||
142 | pbytes = VNBYTES(vid_priv->bpix); | |
143 | if (direction) { | |
144 | step = -pbytes; | |
145 | line_step = vid_priv->line_length; | |
146 | } else { | |
147 | step = pbytes; | |
148 | line_step = -vid_priv->line_length; | |
149 | } | |
02db4ec9 | 150 | |
39c1fa2c DS |
151 | width_remainder = fontdata->width % 8; |
152 | for (int col = 0; col < fontdata->byte_width; col++) { | |
02db4ec9 DS |
153 | mask = 0x80; |
154 | if (width_remainder) { | |
39c1fa2c | 155 | bool is_last_col = (fontdata->byte_width - col == 1); |
02db4ec9 | 156 | |
39c1fa2c | 157 | if (is_last_col) |
02db4ec9 DS |
158 | bitcount = width_remainder; |
159 | } | |
160 | for (int bit = 0; bit < bitcount; bit++) { | |
161 | dst = *line; | |
39c1fa2c DS |
162 | for (int row = 0; row < fontdata->height; row++) { |
163 | u32 value = (pfont[row * fontdata->byte_width + col] | |
164 | & mask) ? vid_priv->colour_fg : vid_priv->colour_bg; | |
02db4ec9 DS |
165 | |
166 | fill_pixel_and_goto_next(&dst, | |
167 | value, | |
168 | pbytes, | |
169 | step | |
170 | ); | |
171 | } | |
172 | *line += line_step; | |
173 | mask >>= 1; | |
31547259 | 174 | } |
31547259 DS |
175 | } |
176 | return ret; | |
177 | } | |
178 | ||
37db20d0 SG |
179 | int draw_cursor_vertically(void **line, struct video_priv *vid_priv, |
180 | uint height, bool direction) | |
181 | { | |
182 | int step, line_step, pbytes, ret; | |
183 | uint value; | |
184 | void *dst; | |
185 | ||
186 | ret = check_bpix_support(vid_priv->bpix); | |
187 | if (ret) | |
188 | return ret; | |
189 | ||
190 | pbytes = VNBYTES(vid_priv->bpix); | |
191 | if (direction) { | |
192 | step = -pbytes; | |
193 | line_step = -vid_priv->line_length; | |
194 | } else { | |
195 | step = pbytes; | |
196 | line_step = vid_priv->line_length; | |
197 | } | |
198 | ||
199 | value = vid_priv->colour_fg; | |
200 | ||
201 | for (int row = 0; row < height; row++) { | |
202 | dst = *line; | |
203 | for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++) | |
204 | fill_pixel_and_goto_next(&dst, value, pbytes, step); | |
205 | *line += line_step; | |
206 | } | |
207 | return ret; | |
208 | } | |
209 | ||
31547259 DS |
210 | int console_probe(struct udevice *dev) |
211 | { | |
39c1fa2c | 212 | return console_set_font(dev, fonts); |
31547259 | 213 | } |
e7ee1fd5 DS |
214 | |
215 | const char *console_simple_get_font_size(struct udevice *dev, uint *sizep) | |
216 | { | |
217 | struct console_simple_priv *priv = dev_get_priv(dev); | |
218 | ||
219 | *sizep = priv->fontdata->width; | |
220 | ||
221 | return priv->fontdata->name; | |
222 | } | |
223 | ||
224 | int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info) | |
225 | { | |
226 | info->name = fonts[seq].name; | |
227 | ||
24adbee3 | 228 | return info->name ? 0 : -ENOENT; |
e7ee1fd5 DS |
229 | } |
230 | ||
231 | int console_simple_select_font(struct udevice *dev, const char *name, uint size) | |
232 | { | |
233 | struct video_fontdata *font; | |
234 | ||
7a2fee8d OJ |
235 | if (!name) { |
236 | if (fonts->name) | |
237 | console_set_font(dev, fonts); | |
238 | return 0; | |
239 | } | |
240 | ||
e7ee1fd5 DS |
241 | for (font = fonts; font->name; font++) { |
242 | if (!strcmp(name, font->name)) { | |
243 | console_set_font(dev, font); | |
244 | return 0; | |
245 | } | |
246 | }; | |
247 | printf("no such font: %s, make sure it's name has <width>x<height> format\n", name); | |
248 | return -ENOENT; | |
249 | } |