blob: 4d000fa1bea5b41681b763b0dd318dd52d6f4afd [file] [log] [blame]
Simon Glass90b6fef2016-01-18 19:52:26 -07001/*
2 * Copyright (c) 2014 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <bzlib.h>
10#include <dm.h>
11#include <mapmem.h>
12#include <os.h>
13#include <video.h>
14#include <video_console.h>
15#include <dm/test.h>
16#include <dm/uclass-internal.h>
17#include <test/ut.h>
18
19/*
20 * These tests use the standard sandbox frame buffer, the resolution of which
21 * is defined in the device tree. This only supports 16bpp so the tests only
22 * test that code path. It would be possible to adjust this fairly easily,
23 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
24 * in sandbox_sdl_sync() would also need to change to handle the different
25 * surface depth.
26 */
27DECLARE_GLOBAL_DATA_PTR;
28
29/* Basic test of the video uclass */
30static int dm_test_video_base(struct unit_test_state *uts)
31{
32 struct video_priv *priv;
33 struct udevice *dev;
34
35 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
36 ut_asserteq(1366, video_get_xsize(dev));
37 ut_asserteq(768, video_get_ysize(dev));
38 priv = dev_get_uclass_priv(dev);
39 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
40
41 return 0;
42}
43DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
44
45/**
46 * compress_frame_buffer() - Compress the frame buffer and return its size
47 *
48 * We want to write tests which perform operations on the video console and
49 * check that the frame buffer ends up with the correct contents. But it is
50 * painful to store 'known good' images for comparison with the frame
51 * buffer. As an alternative, we can compress the frame buffer and check the
52 * size of the compressed data. This provides a pretty good level of
53 * certainty and the resulting tests need only check a single value.
54 *
55 * @dev: Video device
56 * @return compressed size of the frame buffer, or -ve on error
57 */
58static int compress_frame_buffer(struct udevice *dev)
59{
60 struct video_priv *priv = dev_get_uclass_priv(dev);
61 uint destlen;
62 void *dest;
63 int ret;
64
65 destlen = priv->fb_size;
66 dest = malloc(priv->fb_size);
67 if (!dest)
68 return -ENOMEM;
69 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
70 priv->fb, priv->fb_size,
71 3, 0, 0);
72 free(dest);
73 if (ret)
74 return ret;
75
76 return destlen;
77}
78
79/*
80 * Call this function at any point to halt and show the current display. Be
81 * sure to run the test with the -l flag.
82 */
83static void __maybe_unused see_output(void)
84{
85 video_sync_all();
86 while (1);
87}
88
Simon Glassdaac9c72016-01-14 18:10:50 -070089/* Select the video console driver to use for a video device */
90static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
91{
92 struct sandbox_sdl_plat *plat;
93 struct udevice *dev;
94
95 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
96 ut_assert(!device_active(dev));
97 plat = dev_get_platdata(dev);
98 plat->vidconsole_drv_name = "vidconsole0";
99
100 return 0;
101}
102
Simon Glass90b6fef2016-01-18 19:52:26 -0700103/* Test text output works on the video console */
104static int dm_test_video_text(struct unit_test_state *uts)
105{
106 struct udevice *dev, *con;
107 int i;
108
109#define WHITE 0xffff
110#define SCROLL_LINES 100
111
Simon Glassdaac9c72016-01-14 18:10:50 -0700112 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass90b6fef2016-01-18 19:52:26 -0700113 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
114 ut_asserteq(46, compress_frame_buffer(dev));
115
116 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
117 vidconsole_putc_xy(con, 0, 0, 'a');
118 ut_asserteq(79, compress_frame_buffer(dev));
119
120 vidconsole_putc_xy(con, 0, 0, ' ');
121 ut_asserteq(46, compress_frame_buffer(dev));
122
123 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700124 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass90b6fef2016-01-18 19:52:26 -0700125 ut_asserteq(273, compress_frame_buffer(dev));
126
127 vidconsole_set_row(con, 0, WHITE);
128 ut_asserteq(46, compress_frame_buffer(dev));
129
130 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700131 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass90b6fef2016-01-18 19:52:26 -0700132 ut_asserteq(273, compress_frame_buffer(dev));
133
134 return 0;
135}
136DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
137
138/* Test handling of special characters in the console */
139static int dm_test_video_chars(struct unit_test_state *uts)
140{
141 struct udevice *dev, *con;
Simon Glass37b80202016-01-14 18:10:38 -0700142 const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very \amodest \bman\n\t\tand Has much to\b\bto be modest about.";
Simon Glass90b6fef2016-01-18 19:52:26 -0700143 const char *s;
144
Simon Glassdaac9c72016-01-14 18:10:50 -0700145 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass90b6fef2016-01-18 19:52:26 -0700146 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
147 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
148 for (s = test_string; *s; s++)
149 vidconsole_put_char(con, *s);
150 ut_asserteq(466, compress_frame_buffer(dev));
151
152 return 0;
153}
154DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
155
156/**
157 * check_vidconsole_output() - Run a text console test
158 *
159 * @uts: Test state
160 * @rot: Console rotation (0, 90, 180, 270)
161 * @wrap_size: Expected size of compressed frame buffer for the wrap test
162 * @scroll_size: Same for the scroll test
163 * @return 0 on success
164 */
165static int check_vidconsole_output(struct unit_test_state *uts, int rot,
166 int wrap_size, int scroll_size)
167{
168 struct udevice *dev, *con;
169 struct sandbox_sdl_plat *plat;
170 int i;
171
172 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
173 ut_assert(!device_active(dev));
174 plat = dev_get_platdata(dev);
175 plat->rot = rot;
176
177 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
178 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
179 ut_asserteq(46, compress_frame_buffer(dev));
180
181 /* Check display wrap */
182 for (i = 0; i < 120; i++)
183 vidconsole_put_char(con, 'A' + i % 50);
184 ut_asserteq(wrap_size, compress_frame_buffer(dev));
185
186 /* Check display scrolling */
187 for (i = 0; i < SCROLL_LINES; i++) {
188 vidconsole_put_char(con, 'A' + i % 50);
189 vidconsole_put_char(con, '\n');
190 }
191 ut_asserteq(scroll_size, compress_frame_buffer(dev));
192
193 /* If we scroll enough, the screen becomes blank again */
194 for (i = 0; i < SCROLL_LINES; i++)
195 vidconsole_put_char(con, '\n');
196 ut_asserteq(46, compress_frame_buffer(dev));
197
198 return 0;
199}
200
201/* Test text output through the console uclass */
202static int dm_test_video_context(struct unit_test_state *uts)
203{
Simon Glassdaac9c72016-01-14 18:10:50 -0700204 ut_assertok(select_vidconsole(uts, "vidconsole0"));
205 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
206
207 return 0;
Simon Glass90b6fef2016-01-18 19:52:26 -0700208}
209DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700210
211/* Test rotated text output through the console uclass */
212static int dm_test_video_rotation1(struct unit_test_state *uts)
213{
214 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
215
216 return 0;
217}
218DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
219
220/* Test rotated text output through the console uclass */
221static int dm_test_video_rotation2(struct unit_test_state *uts)
222{
223 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
224
225 return 0;
226}
227DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
228
229/* Test rotated text output through the console uclass */
230static int dm_test_video_rotation3(struct unit_test_state *uts)
231{
232 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
233
234 return 0;
235}
236DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700237
238/* Read a file into memory and return a pointer to it */
239static int read_file(struct unit_test_state *uts, const char *fname,
240 ulong *addrp)
241{
242 int buf_size = 100000;
243 ulong addr = 0;
244 int size, fd;
245 char *buf;
246
247 buf = map_sysmem(addr, 0);
248 ut_assert(buf != NULL);
249 fd = os_open(fname, OS_O_RDONLY);
250 ut_assert(fd >= 0);
251 size = os_read(fd, buf, buf_size);
Simon Glass9050c5f2016-01-30 15:45:17 -0700252 os_close(fd);
Simon Glass7a1cb292016-01-18 19:52:28 -0700253 ut_assert(size >= 0);
254 ut_assert(size < buf_size);
Simon Glass7a1cb292016-01-18 19:52:28 -0700255 *addrp = addr;
256
257 return 0;
258}
259
260/* Test drawing a bitmap file */
261static int dm_test_video_bmp(struct unit_test_state *uts)
262{
263 struct udevice *dev;
264 ulong addr;
265
266 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
267 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
268
269 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
270 ut_asserteq(1368, compress_frame_buffer(dev));
271
272 return 0;
273}
274DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
275
276/* Test drawing a compressed bitmap file */
277static int dm_test_video_bmp_comp(struct unit_test_state *uts)
278{
279 struct udevice *dev;
280 ulong addr;
281
282 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
283 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
284
285 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
286 ut_asserteq(1368, compress_frame_buffer(dev));
287
288 return 0;
289}
290DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700291
292/* Test TrueType console */
293static int dm_test_video_truetype(struct unit_test_state *uts)
294{
295 struct udevice *dev, *con;
296 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
297 const char *s;
298
299 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
300 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
301 for (s = test_string; *s; s++)
302 vidconsole_put_char(con, *s);
303 ut_asserteq(12619, compress_frame_buffer(dev));
304
305 return 0;
306}
307DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
308
309/* Test scrolling TrueType console */
310static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
311{
312 struct sandbox_sdl_plat *plat;
313 struct udevice *dev, *con;
314 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
315 const char *s;
316
317 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
318 ut_assert(!device_active(dev));
319 plat = dev_get_platdata(dev);
320 plat->font_size = 100;
321
322 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
323 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
324 for (s = test_string; *s; s++)
325 vidconsole_put_char(con, *s);
326 ut_asserteq(33849, compress_frame_buffer(dev));
327
328 return 0;
329}
330DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
331
332/* Test TrueType backspace, within and across lines */
333static int dm_test_video_truetype_bs(struct unit_test_state *uts)
334{
335 struct sandbox_sdl_plat *plat;
336 struct udevice *dev, *con;
337 const char *test_string = "...Criticism may or may\b\b\b\b\b\bnot be agreeable, but seldom it is necessary\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bit is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things.";
338 const char *s;
339
340 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
341 ut_assert(!device_active(dev));
342 plat = dev_get_platdata(dev);
343 plat->font_size = 100;
344
345 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
346 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
347 for (s = test_string; *s; s++)
348 vidconsole_put_char(con, *s);
349 ut_asserteq(34871, compress_frame_buffer(dev));
350
351 return 0;
352}
353DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);