xref: /rk3399_rockchip-uboot/test/dm/video.c (revision 3c97c4fb52af9d4da4546cbb8a52bdb6f0d4b57f)
1*3c97c4fbSSimon Glass /*
2*3c97c4fbSSimon Glass  * Copyright (c) 2014 Google, Inc
3*3c97c4fbSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4*3c97c4fbSSimon Glass  *
5*3c97c4fbSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6*3c97c4fbSSimon Glass  */
7*3c97c4fbSSimon Glass 
8*3c97c4fbSSimon Glass #include <common.h>
9*3c97c4fbSSimon Glass #include <bzlib.h>
10*3c97c4fbSSimon Glass #include <dm.h>
11*3c97c4fbSSimon Glass #include <mapmem.h>
12*3c97c4fbSSimon Glass #include <os.h>
13*3c97c4fbSSimon Glass #include <video.h>
14*3c97c4fbSSimon Glass #include <video_console.h>
15*3c97c4fbSSimon Glass #include <dm/test.h>
16*3c97c4fbSSimon Glass #include <dm/uclass-internal.h>
17*3c97c4fbSSimon Glass #include <test/ut.h>
18*3c97c4fbSSimon Glass 
19*3c97c4fbSSimon Glass /*
20*3c97c4fbSSimon Glass  * These tests use the standard sandbox frame buffer, the resolution of which
21*3c97c4fbSSimon Glass  * is defined in the device tree. This only supports 16bpp so the tests only
22*3c97c4fbSSimon Glass  * test that code path. It would be possible to adjust this fairly easily,
23*3c97c4fbSSimon Glass  * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
24*3c97c4fbSSimon Glass  * in sandbox_sdl_sync() would also need to change to handle the different
25*3c97c4fbSSimon Glass  * surface depth.
26*3c97c4fbSSimon Glass  */
27*3c97c4fbSSimon Glass DECLARE_GLOBAL_DATA_PTR;
28*3c97c4fbSSimon Glass 
29*3c97c4fbSSimon Glass /* Basic test of the video uclass */
30*3c97c4fbSSimon Glass static int dm_test_video_base(struct unit_test_state *uts)
31*3c97c4fbSSimon Glass {
32*3c97c4fbSSimon Glass 	struct video_priv *priv;
33*3c97c4fbSSimon Glass 	struct udevice *dev;
34*3c97c4fbSSimon Glass 
35*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
36*3c97c4fbSSimon Glass 	ut_asserteq(1366, video_get_xsize(dev));
37*3c97c4fbSSimon Glass 	ut_asserteq(768, video_get_ysize(dev));
38*3c97c4fbSSimon Glass 	priv = dev_get_uclass_priv(dev);
39*3c97c4fbSSimon Glass 	ut_asserteq(priv->fb_size, 1366 * 768 * 2);
40*3c97c4fbSSimon Glass 
41*3c97c4fbSSimon Glass 	return 0;
42*3c97c4fbSSimon Glass }
43*3c97c4fbSSimon Glass DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
44*3c97c4fbSSimon Glass 
45*3c97c4fbSSimon Glass /**
46*3c97c4fbSSimon Glass  * compress_frame_buffer() - Compress the frame buffer and return its size
47*3c97c4fbSSimon Glass  *
48*3c97c4fbSSimon Glass  * We want to write tests which perform operations on the video console and
49*3c97c4fbSSimon Glass  * check that the frame buffer ends up with the correct contents. But it is
50*3c97c4fbSSimon Glass  * painful to store 'known good' images for comparison with the frame
51*3c97c4fbSSimon Glass  * buffer. As an alternative, we can compress the frame buffer and check the
52*3c97c4fbSSimon Glass  * size of the compressed data. This provides a pretty good level of
53*3c97c4fbSSimon Glass  * certainty and the resulting tests need only check a single value.
54*3c97c4fbSSimon Glass  *
55*3c97c4fbSSimon Glass  * @dev:	Video device
56*3c97c4fbSSimon Glass  * @return compressed size of the frame buffer, or -ve on error
57*3c97c4fbSSimon Glass  */
58*3c97c4fbSSimon Glass static int compress_frame_buffer(struct udevice *dev)
59*3c97c4fbSSimon Glass {
60*3c97c4fbSSimon Glass 	struct video_priv *priv = dev_get_uclass_priv(dev);
61*3c97c4fbSSimon Glass 	uint destlen;
62*3c97c4fbSSimon Glass 	void *dest;
63*3c97c4fbSSimon Glass 	int ret;
64*3c97c4fbSSimon Glass 
65*3c97c4fbSSimon Glass 	destlen = priv->fb_size;
66*3c97c4fbSSimon Glass 	dest = malloc(priv->fb_size);
67*3c97c4fbSSimon Glass 	if (!dest)
68*3c97c4fbSSimon Glass 		return -ENOMEM;
69*3c97c4fbSSimon Glass 	ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
70*3c97c4fbSSimon Glass 				       priv->fb, priv->fb_size,
71*3c97c4fbSSimon Glass 				       3, 0, 0);
72*3c97c4fbSSimon Glass 	free(dest);
73*3c97c4fbSSimon Glass 	if (ret)
74*3c97c4fbSSimon Glass 		return ret;
75*3c97c4fbSSimon Glass 
76*3c97c4fbSSimon Glass 	return destlen;
77*3c97c4fbSSimon Glass }
78*3c97c4fbSSimon Glass 
79*3c97c4fbSSimon Glass /*
80*3c97c4fbSSimon Glass  * Call this function at any point to halt and show the current display. Be
81*3c97c4fbSSimon Glass  * sure to run the test with the -l flag.
82*3c97c4fbSSimon Glass  */
83*3c97c4fbSSimon Glass static void __maybe_unused see_output(void)
84*3c97c4fbSSimon Glass {
85*3c97c4fbSSimon Glass 	video_sync_all();
86*3c97c4fbSSimon Glass 	while (1);
87*3c97c4fbSSimon Glass }
88*3c97c4fbSSimon Glass 
89*3c97c4fbSSimon Glass /* Test text output works on the video console */
90*3c97c4fbSSimon Glass static int dm_test_video_text(struct unit_test_state *uts)
91*3c97c4fbSSimon Glass {
92*3c97c4fbSSimon Glass 	struct udevice *dev, *con;
93*3c97c4fbSSimon Glass 	int i;
94*3c97c4fbSSimon Glass 
95*3c97c4fbSSimon Glass #define WHITE		0xffff
96*3c97c4fbSSimon Glass #define SCROLL_LINES	100
97*3c97c4fbSSimon Glass 
98*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
99*3c97c4fbSSimon Glass 	ut_asserteq(46, compress_frame_buffer(dev));
100*3c97c4fbSSimon Glass 
101*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
102*3c97c4fbSSimon Glass 	vidconsole_putc_xy(con, 0, 0, 'a');
103*3c97c4fbSSimon Glass 	ut_asserteq(79, compress_frame_buffer(dev));
104*3c97c4fbSSimon Glass 
105*3c97c4fbSSimon Glass 	vidconsole_putc_xy(con, 0, 0, ' ');
106*3c97c4fbSSimon Glass 	ut_asserteq(46, compress_frame_buffer(dev));
107*3c97c4fbSSimon Glass 
108*3c97c4fbSSimon Glass 	for (i = 0; i < 20; i++)
109*3c97c4fbSSimon Glass 		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
110*3c97c4fbSSimon Glass 	ut_asserteq(273, compress_frame_buffer(dev));
111*3c97c4fbSSimon Glass 
112*3c97c4fbSSimon Glass 	vidconsole_set_row(con, 0, WHITE);
113*3c97c4fbSSimon Glass 	ut_asserteq(46, compress_frame_buffer(dev));
114*3c97c4fbSSimon Glass 
115*3c97c4fbSSimon Glass 	for (i = 0; i < 20; i++)
116*3c97c4fbSSimon Glass 		vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
117*3c97c4fbSSimon Glass 	ut_asserteq(273, compress_frame_buffer(dev));
118*3c97c4fbSSimon Glass 
119*3c97c4fbSSimon Glass 	return 0;
120*3c97c4fbSSimon Glass }
121*3c97c4fbSSimon Glass DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
122*3c97c4fbSSimon Glass 
123*3c97c4fbSSimon Glass /* Test handling of special characters in the console */
124*3c97c4fbSSimon Glass static int dm_test_video_chars(struct unit_test_state *uts)
125*3c97c4fbSSimon Glass {
126*3c97c4fbSSimon Glass 	struct udevice *dev, *con;
127*3c97c4fbSSimon Glass 	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*3c97c4fbSSimon Glass 	const char *s;
129*3c97c4fbSSimon Glass 
130*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
131*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
132*3c97c4fbSSimon Glass 	for (s = test_string; *s; s++)
133*3c97c4fbSSimon Glass 		vidconsole_put_char(con, *s);
134*3c97c4fbSSimon Glass 	ut_asserteq(466, compress_frame_buffer(dev));
135*3c97c4fbSSimon Glass 
136*3c97c4fbSSimon Glass 	return 0;
137*3c97c4fbSSimon Glass }
138*3c97c4fbSSimon Glass DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
139*3c97c4fbSSimon Glass 
140*3c97c4fbSSimon Glass /**
141*3c97c4fbSSimon Glass  * check_vidconsole_output() - Run a text console test
142*3c97c4fbSSimon Glass  *
143*3c97c4fbSSimon Glass  * @uts:	Test state
144*3c97c4fbSSimon Glass  * @rot:	Console rotation (0, 90, 180, 270)
145*3c97c4fbSSimon Glass  * @wrap_size:	Expected size of compressed frame buffer for the wrap test
146*3c97c4fbSSimon Glass  * @scroll_size: Same for the scroll test
147*3c97c4fbSSimon Glass  * @return 0 on success
148*3c97c4fbSSimon Glass  */
149*3c97c4fbSSimon Glass static int check_vidconsole_output(struct unit_test_state *uts, int rot,
150*3c97c4fbSSimon Glass 				   int wrap_size, int scroll_size)
151*3c97c4fbSSimon Glass {
152*3c97c4fbSSimon Glass 	struct udevice *dev, *con;
153*3c97c4fbSSimon Glass 	struct sandbox_sdl_plat *plat;
154*3c97c4fbSSimon Glass 	int i;
155*3c97c4fbSSimon Glass 
156*3c97c4fbSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
157*3c97c4fbSSimon Glass 	ut_assert(!device_active(dev));
158*3c97c4fbSSimon Glass 	plat = dev_get_platdata(dev);
159*3c97c4fbSSimon Glass 	plat->rot = rot;
160*3c97c4fbSSimon Glass 
161*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
162*3c97c4fbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
163*3c97c4fbSSimon Glass 	ut_asserteq(46, compress_frame_buffer(dev));
164*3c97c4fbSSimon Glass 
165*3c97c4fbSSimon Glass 	/* Check display wrap */
166*3c97c4fbSSimon Glass 	for (i = 0; i < 120; i++)
167*3c97c4fbSSimon Glass 		vidconsole_put_char(con, 'A' + i % 50);
168*3c97c4fbSSimon Glass 	ut_asserteq(wrap_size, compress_frame_buffer(dev));
169*3c97c4fbSSimon Glass 
170*3c97c4fbSSimon Glass 	/* Check display scrolling */
171*3c97c4fbSSimon Glass 	for (i = 0; i < SCROLL_LINES; i++) {
172*3c97c4fbSSimon Glass 		vidconsole_put_char(con, 'A' + i % 50);
173*3c97c4fbSSimon Glass 		vidconsole_put_char(con, '\n');
174*3c97c4fbSSimon Glass 	}
175*3c97c4fbSSimon Glass 	ut_asserteq(scroll_size, compress_frame_buffer(dev));
176*3c97c4fbSSimon Glass 
177*3c97c4fbSSimon Glass 	/* If we scroll enough, the screen becomes blank again */
178*3c97c4fbSSimon Glass 	for (i = 0; i < SCROLL_LINES; i++)
179*3c97c4fbSSimon Glass 		vidconsole_put_char(con, '\n');
180*3c97c4fbSSimon Glass 	ut_asserteq(46, compress_frame_buffer(dev));
181*3c97c4fbSSimon Glass 
182*3c97c4fbSSimon Glass 	return 0;
183*3c97c4fbSSimon Glass }
184*3c97c4fbSSimon Glass 
185*3c97c4fbSSimon Glass /* Test text output through the console uclass */
186*3c97c4fbSSimon Glass static int dm_test_video_context(struct unit_test_state *uts)
187*3c97c4fbSSimon Glass {
188*3c97c4fbSSimon Glass 	return check_vidconsole_output(uts, 0, 788, 453);
189*3c97c4fbSSimon Glass }
190*3c97c4fbSSimon Glass DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
191