xref: /openbmc/u-boot/test/dm/video.c (revision 7e8702a0)
1 /*
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  */
27 DECLARE_GLOBAL_DATA_PTR;
28 
29 /* Basic test of the video uclass */
30 static 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 }
43 DM_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  */
58 static 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  */
83 static void __maybe_unused see_output(void)
84 {
85 	video_sync_all();
86 	while (1);
87 }
88 
89 /* Test text output works on the video console */
90 static int dm_test_video_text(struct unit_test_state *uts)
91 {
92 	struct udevice *dev, *con;
93 	int i;
94 
95 #define WHITE		0xffff
96 #define SCROLL_LINES	100
97 
98 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
99 	ut_asserteq(46, compress_frame_buffer(dev));
100 
101 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
102 	vidconsole_putc_xy(con, 0, 0, 'a');
103 	ut_asserteq(79, compress_frame_buffer(dev));
104 
105 	vidconsole_putc_xy(con, 0, 0, ' ');
106 	ut_asserteq(46, compress_frame_buffer(dev));
107 
108 	for (i = 0; i < 20; i++)
109 		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
110 	ut_asserteq(273, compress_frame_buffer(dev));
111 
112 	vidconsole_set_row(con, 0, WHITE);
113 	ut_asserteq(46, compress_frame_buffer(dev));
114 
115 	for (i = 0; i < 20; i++)
116 		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
117 	ut_asserteq(273, compress_frame_buffer(dev));
118 
119 	return 0;
120 }
121 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
122 
123 /* Test handling of special characters in the console */
124 static int dm_test_video_chars(struct unit_test_state *uts)
125 {
126 	struct udevice *dev, *con;
127 	const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very modest  \bman\n\t\tand Has much to\b\bto be modest about.";
128 	const char *s;
129 
130 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
131 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
132 	for (s = test_string; *s; s++)
133 		vidconsole_put_char(con, *s);
134 	ut_asserteq(466, compress_frame_buffer(dev));
135 
136 	return 0;
137 }
138 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
139 
140 /**
141  * check_vidconsole_output() - Run a text console test
142  *
143  * @uts:	Test state
144  * @rot:	Console rotation (0, 90, 180, 270)
145  * @wrap_size:	Expected size of compressed frame buffer for the wrap test
146  * @scroll_size: Same for the scroll test
147  * @return 0 on success
148  */
149 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
150 				   int wrap_size, int scroll_size)
151 {
152 	struct udevice *dev, *con;
153 	struct sandbox_sdl_plat *plat;
154 	int i;
155 
156 	ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
157 	ut_assert(!device_active(dev));
158 	plat = dev_get_platdata(dev);
159 	plat->rot = rot;
160 
161 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
162 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
163 	ut_asserteq(46, compress_frame_buffer(dev));
164 
165 	/* Check display wrap */
166 	for (i = 0; i < 120; i++)
167 		vidconsole_put_char(con, 'A' + i % 50);
168 	ut_asserteq(wrap_size, compress_frame_buffer(dev));
169 
170 	/* Check display scrolling */
171 	for (i = 0; i < SCROLL_LINES; i++) {
172 		vidconsole_put_char(con, 'A' + i % 50);
173 		vidconsole_put_char(con, '\n');
174 	}
175 	ut_asserteq(scroll_size, compress_frame_buffer(dev));
176 
177 	/* If we scroll enough, the screen becomes blank again */
178 	for (i = 0; i < SCROLL_LINES; i++)
179 		vidconsole_put_char(con, '\n');
180 	ut_asserteq(46, compress_frame_buffer(dev));
181 
182 	return 0;
183 }
184 
185 /* Test text output through the console uclass */
186 static int dm_test_video_context(struct unit_test_state *uts)
187 {
188 	return check_vidconsole_output(uts, 0, 788, 453);
189 }
190 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
191 
192 /* Test rotated text output through the console uclass */
193 static int dm_test_video_rotation1(struct unit_test_state *uts)
194 {
195 	ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
196 
197 	return 0;
198 }
199 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
200 
201 /* Test rotated text output through the console uclass */
202 static int dm_test_video_rotation2(struct unit_test_state *uts)
203 {
204 	ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
205 
206 	return 0;
207 }
208 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
209 
210 /* Test rotated text output through the console uclass */
211 static int dm_test_video_rotation3(struct unit_test_state *uts)
212 {
213 	ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
214 
215 	return 0;
216 }
217 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
218 
219 /* Read a file into memory and return a pointer to it */
220 static int read_file(struct unit_test_state *uts, const char *fname,
221 		     ulong *addrp)
222 {
223 	int buf_size = 100000;
224 	ulong addr = 0;
225 	int size, fd;
226 	char *buf;
227 
228 	buf = map_sysmem(addr, 0);
229 	ut_assert(buf != NULL);
230 	fd = os_open(fname, OS_O_RDONLY);
231 	ut_assert(fd >= 0);
232 	size = os_read(fd, buf, buf_size);
233 	ut_assert(size >= 0);
234 	ut_assert(size < buf_size);
235 	os_close(fd);
236 	*addrp = addr;
237 
238 	return 0;
239 }
240 
241 /* Test drawing a bitmap file */
242 static int dm_test_video_bmp(struct unit_test_state *uts)
243 {
244 	struct udevice *dev;
245 	ulong addr;
246 
247 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
248 	ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
249 
250 	ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
251 	ut_asserteq(1368, compress_frame_buffer(dev));
252 
253 	return 0;
254 }
255 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
256 
257 /* Test drawing a compressed bitmap file */
258 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
259 {
260 	struct udevice *dev;
261 	ulong addr;
262 
263 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
264 	ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
265 
266 	ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
267 	ut_asserteq(1368, compress_frame_buffer(dev));
268 
269 	return 0;
270 }
271 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
272