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