blob: a7e44e06ebf86c5a05b8309ab25fdebfbb4f6884 [file] [log] [blame]
Simon Glass3c97c4f2016-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 Glass8df8dad2016-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 Glass3c97c4f2016-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 Glass8df8dad2016-01-14 18:10:50 -0700112 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass3c97c4f2016-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 Glassf2661782016-01-14 18:10:37 -0700124 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass3c97c4f2016-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 Glassf2661782016-01-14 18:10:37 -0700131 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass3c97c4f2016-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 Glass5508f102016-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 Glass3c97c4f2016-01-18 19:52:26 -0700143 const char *s;
144
Simon Glass8df8dad2016-01-14 18:10:50 -0700145 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass3c97c4f2016-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 Glass8df8dad2016-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 Glass3c97c4f2016-01-18 19:52:26 -0700208}
209DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass85e08db2016-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 Glass747440d2016-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);
252 ut_assert(size >= 0);
253 ut_assert(size < buf_size);
254 os_close(fd);
255 *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);