]> Git Repo - u-boot.git/blob - test/dm/video.c
imx8m: fix reading of DDR4 MR registers
[u-boot.git] / test / dm / video.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  * Written by Simon Glass <[email protected]>
5  */
6
7 #include <common.h>
8 #include <bzlib.h>
9 #include <dm.h>
10 #include <gzip.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <os.h>
15 #include <video.h>
16 #include <video_console.h>
17 #include <asm/test.h>
18 #include <dm/test.h>
19 #include <dm/uclass-internal.h>
20 #include <test/test.h>
21 #include <test/ut.h>
22
23 /*
24  * These tests use the standard sandbox frame buffer, the resolution of which
25  * is defined in the device tree. This only supports 16bpp so the tests only
26  * test that code path. It would be possible to adjust this fairly easily,
27  * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
28  * in sandbox_sdl_sync() would also need to change to handle the different
29  * surface depth.
30  */
31 /* Basic test of the video uclass */
32 static int dm_test_video_base(struct unit_test_state *uts)
33 {
34         struct video_priv *priv;
35         struct udevice *dev;
36
37         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
38         ut_asserteq(1366, video_get_xsize(dev));
39         ut_asserteq(768, video_get_ysize(dev));
40         priv = dev_get_uclass_priv(dev);
41         ut_asserteq(priv->fb_size, 1366 * 768 * 2);
42
43         return 0;
44 }
45 DM_TEST(dm_test_video_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
46
47 /**
48  * compress_frame_buffer() - Compress the frame buffer and return its size
49  *
50  * We want to write tests which perform operations on the video console and
51  * check that the frame buffer ends up with the correct contents. But it is
52  * painful to store 'known good' images for comparison with the frame
53  * buffer. As an alternative, we can compress the frame buffer and check the
54  * size of the compressed data. This provides a pretty good level of
55  * certainty and the resulting tests need only check a single value.
56  *
57  * If the copy framebuffer is enabled, this compares it to the main framebuffer
58  * too.
59  *
60  * @uts:        Test state
61  * @dev:        Video device
62  * Return: compressed size of the frame buffer, or -ve on error
63  */
64 static int compress_frame_buffer(struct unit_test_state *uts,
65                                  struct udevice *dev)
66 {
67         struct video_priv *priv = dev_get_uclass_priv(dev);
68         struct video_priv *uc_priv = dev_get_uclass_priv(dev);
69         uint destlen;
70         void *dest;
71         int ret;
72
73         destlen = priv->fb_size;
74         dest = malloc(priv->fb_size);
75         if (!dest)
76                 return -ENOMEM;
77         ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
78                                        priv->fb, priv->fb_size,
79                                        3, 0, 0);
80         free(dest);
81         if (ret)
82                 return ret;
83
84         /* Check here that the copy frame buffer is working correctly */
85         if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
86                 ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb,
87                                    uc_priv->fb_size),
88                                    "Copy framebuffer does not match fb");
89         }
90
91         return destlen;
92 }
93
94 /*
95  * Call this function at any point to halt and show the current display. Be
96  * sure to run the test with the -l flag.
97  */
98 static void __maybe_unused see_output(void)
99 {
100         video_sync_all();
101         while (1);
102 }
103
104 /* Select the video console driver to use for a video device */
105 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
106 {
107         struct sandbox_sdl_plat *plat;
108         struct udevice *dev;
109
110         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
111         ut_assert(!device_active(dev));
112         plat = dev_get_plat(dev);
113         plat->vidconsole_drv_name = "vidconsole0";
114
115         return 0;
116 }
117
118 /**
119  * video_get_nologo() - Disable the logo on the video device and return it
120  *
121  * @uts: Test state
122  * @devp: Returns video device
123  * Return: 0 if OK, -ve on error
124  */
125 static int video_get_nologo(struct unit_test_state *uts, struct udevice **devp)
126 {
127         struct video_uc_plat *uc_plat;
128         struct udevice *dev;
129
130         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
131         ut_assertnonnull(dev);
132         uc_plat = dev_get_uclass_plat(dev);
133         uc_plat->hide_logo = true;
134
135         /* now probe it */
136         ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
137         ut_assertnonnull(dev);
138         *devp = dev;
139
140         return 0;
141 }
142
143 /* Test text output works on the video console */
144 static int dm_test_video_text(struct unit_test_state *uts)
145 {
146         struct udevice *dev, *con;
147         int i;
148
149 #define WHITE           0xffff
150 #define SCROLL_LINES    100
151
152         ut_assertok(select_vidconsole(uts, "vidconsole0"));
153         ut_assertok(video_get_nologo(uts, &dev));
154         ut_asserteq(46, compress_frame_buffer(uts, dev));
155
156         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
157         vidconsole_putc_xy(con, 0, 0, 'a');
158         ut_asserteq(79, compress_frame_buffer(uts, dev));
159
160         vidconsole_putc_xy(con, 0, 0, ' ');
161         ut_asserteq(46, compress_frame_buffer(uts, dev));
162
163         for (i = 0; i < 20; i++)
164                 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
165         ut_asserteq(273, compress_frame_buffer(uts, dev));
166
167         vidconsole_set_row(con, 0, WHITE);
168         ut_asserteq(46, compress_frame_buffer(uts, dev));
169
170         for (i = 0; i < 20; i++)
171                 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
172         ut_asserteq(273, compress_frame_buffer(uts, dev));
173
174         return 0;
175 }
176 DM_TEST(dm_test_video_text, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
177
178 /* Test handling of special characters in the console */
179 static int dm_test_video_chars(struct unit_test_state *uts)
180 {
181         struct udevice *dev, *con;
182         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.";
183
184         ut_assertok(select_vidconsole(uts, "vidconsole0"));
185         ut_assertok(video_get_nologo(uts, &dev));
186         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
187         vidconsole_put_string(con, test_string);
188         ut_asserteq(466, compress_frame_buffer(uts, dev));
189
190         return 0;
191 }
192 DM_TEST(dm_test_video_chars, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
193
194 #ifdef CONFIG_VIDEO_ANSI
195 #define ANSI_ESC "\x1b"
196 /* Test handling of ANSI escape sequences */
197 static int dm_test_video_ansi(struct unit_test_state *uts)
198 {
199         struct udevice *dev, *con;
200
201         ut_assertok(select_vidconsole(uts, "vidconsole0"));
202         ut_assertok(video_get_nologo(uts, &dev));
203         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
204
205         /* reference clear: */
206         video_clear(con->parent);
207         video_sync(con->parent, false);
208         ut_asserteq(46, compress_frame_buffer(uts, dev));
209
210         /* test clear escape sequence: [2J */
211         vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
212         ut_asserteq(46, compress_frame_buffer(uts, dev));
213
214         /* test set-cursor: [%d;%df */
215         vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
216         ut_asserteq(143, compress_frame_buffer(uts, dev));
217
218         /* test colors (30-37 fg color, 40-47 bg color) */
219         vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
220         vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
221         ut_asserteq(272, compress_frame_buffer(uts, dev));
222
223         return 0;
224 }
225 DM_TEST(dm_test_video_ansi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
226 #endif
227
228 /**
229  * check_vidconsole_output() - Run a text console test
230  *
231  * @uts:        Test state
232  * @rot:        Console rotation (0=normal orientation, 1=90 degrees clockwise,
233  *              2=upside down, 3=90 degree counterclockwise)
234  * @wrap_size:  Expected size of compressed frame buffer for the wrap test
235  * @scroll_size: Same for the scroll test
236  * Return: 0 on success
237  */
238 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
239                                    int wrap_size, int scroll_size)
240 {
241         struct udevice *dev, *con;
242         struct sandbox_sdl_plat *plat;
243         int i;
244
245         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
246         ut_assert(!device_active(dev));
247         plat = dev_get_plat(dev);
248         plat->rot = rot;
249
250         ut_assertok(video_get_nologo(uts, &dev));
251         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
252         ut_asserteq(46, compress_frame_buffer(uts, dev));
253
254         /* Check display wrap */
255         for (i = 0; i < 120; i++)
256                 vidconsole_put_char(con, 'A' + i % 50);
257         ut_asserteq(wrap_size, compress_frame_buffer(uts, dev));
258
259         /* Check display scrolling */
260         for (i = 0; i < SCROLL_LINES; i++) {
261                 vidconsole_put_char(con, 'A' + i % 50);
262                 vidconsole_put_char(con, '\n');
263         }
264         ut_asserteq(scroll_size, compress_frame_buffer(uts, dev));
265
266         /* If we scroll enough, the screen becomes blank again */
267         for (i = 0; i < SCROLL_LINES; i++)
268                 vidconsole_put_char(con, '\n');
269         ut_asserteq(46, compress_frame_buffer(uts, dev));
270
271         return 0;
272 }
273
274 /* Test text output through the console uclass */
275 static int dm_test_video_context(struct unit_test_state *uts)
276 {
277         ut_assertok(select_vidconsole(uts, "vidconsole0"));
278         ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
279
280         return 0;
281 }
282 DM_TEST(dm_test_video_context, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
283
284 /* Test rotated text output through the console uclass */
285 static int dm_test_video_rotation1(struct unit_test_state *uts)
286 {
287         ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
288
289         return 0;
290 }
291 DM_TEST(dm_test_video_rotation1, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
292
293 /* Test rotated text output through the console uclass */
294 static int dm_test_video_rotation2(struct unit_test_state *uts)
295 {
296         ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
297
298         return 0;
299 }
300 DM_TEST(dm_test_video_rotation2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
301
302 /* Test rotated text output through the console uclass */
303 static int dm_test_video_rotation3(struct unit_test_state *uts)
304 {
305         ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
306
307         return 0;
308 }
309 DM_TEST(dm_test_video_rotation3, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
310
311 /* Read a file into memory and return a pointer to it */
312 static int read_file(struct unit_test_state *uts, const char *fname,
313                      ulong *addrp)
314 {
315         int buf_size = 100000;
316         ulong addr = 0;
317         int size, fd;
318         char *buf;
319
320         buf = map_sysmem(addr, 0);
321         ut_assert(buf != NULL);
322         fd = os_open(fname, OS_O_RDONLY);
323         ut_assert(fd >= 0);
324         size = os_read(fd, buf, buf_size);
325         os_close(fd);
326         ut_assert(size >= 0);
327         ut_assert(size < buf_size);
328         *addrp = addr;
329
330         return 0;
331 }
332
333 /* Test drawing a bitmap file */
334 static int dm_test_video_bmp(struct unit_test_state *uts)
335 {
336         struct udevice *dev;
337         ulong addr;
338
339         ut_assertok(video_get_nologo(uts, &dev));
340         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
341
342         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
343         ut_asserteq(1368, compress_frame_buffer(uts, dev));
344
345         return 0;
346 }
347 DM_TEST(dm_test_video_bmp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
348
349 /* Test drawing a bitmap file on a 8bpp display */
350 static int dm_test_video_bmp8(struct unit_test_state *uts)
351 {
352         struct udevice *dev;
353         ulong addr;
354
355         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
356         ut_assertnonnull(dev);
357         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
358
359         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
360
361         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
362         ut_asserteq(1247, compress_frame_buffer(uts, dev));
363
364         return 0;
365 }
366 DM_TEST(dm_test_video_bmp8, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
367
368 /* Test drawing a bitmap file on a 16bpp display */
369 static int dm_test_video_bmp16(struct unit_test_state *uts)
370 {
371         ulong src, src_len = ~0UL;
372         uint dst_len = ~0U;
373         struct udevice *dev;
374         ulong dst = 0x10000;
375
376         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
377         ut_assertnonnull(dev);
378         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
379
380         ut_assertok(read_file(uts, "tools/logos/denx-16bpp.bmp.gz", &src));
381         ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
382                            &src_len));
383
384         ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
385         ut_asserteq(3700, compress_frame_buffer(uts, dev));
386
387         return 0;
388 }
389 DM_TEST(dm_test_video_bmp16, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
390
391 /* Test drawing a 24bpp bitmap file on a 16bpp display */
392 static int dm_test_video_bmp24(struct unit_test_state *uts)
393 {
394         ulong src, src_len = ~0UL;
395         uint dst_len = ~0U;
396         struct udevice *dev;
397         ulong dst = 0x10000;
398
399         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
400         ut_assertnonnull(dev);
401         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
402
403         ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
404         ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
405                            &src_len));
406
407         ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
408         ut_asserteq(3656, compress_frame_buffer(uts, dev));
409
410         return 0;
411 }
412 DM_TEST(dm_test_video_bmp24, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
413
414 /* Test drawing a 24bpp bitmap file on a 32bpp display */
415 static int dm_test_video_bmp24_32(struct unit_test_state *uts)
416 {
417         ulong src, src_len = ~0UL;
418         uint dst_len = ~0U;
419         struct udevice *dev;
420         ulong dst = 0x10000;
421
422         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
423         ut_assertnonnull(dev);
424         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
425
426         ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
427         ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
428                            &src_len));
429
430         ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
431         ut_asserteq(6827, compress_frame_buffer(uts, dev));
432
433         return 0;
434 }
435 DM_TEST(dm_test_video_bmp24_32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
436
437 /* Test drawing a bitmap file on a 32bpp display */
438 static int dm_test_video_bmp32(struct unit_test_state *uts)
439 {
440         struct udevice *dev;
441         ulong addr;
442
443         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
444         ut_assertnonnull(dev);
445         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
446         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
447
448         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
449         ut_asserteq(2024, compress_frame_buffer(uts, dev));
450
451         return 0;
452 }
453 DM_TEST(dm_test_video_bmp32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
454
455 /* Test drawing a compressed bitmap file */
456 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
457 {
458         struct udevice *dev;
459         ulong addr;
460
461         ut_assertok(video_get_nologo(uts, &dev));
462         ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
463
464         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
465         ut_asserteq(1368, compress_frame_buffer(uts, dev));
466
467         return 0;
468 }
469 DM_TEST(dm_test_video_bmp_comp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
470
471 /* Test drawing a bitmap file on a 32bpp display */
472 static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
473 {
474         struct udevice *dev;
475         ulong addr;
476
477         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
478         ut_assertnonnull(dev);
479         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
480
481         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
482
483         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
484         ut_asserteq(2024, compress_frame_buffer(uts, dev));
485
486         return 0;
487 }
488 DM_TEST(dm_test_video_comp_bmp32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
489
490 /* Test drawing a bitmap file on a 8bpp display */
491 static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
492 {
493         struct udevice *dev;
494         ulong addr;
495
496         ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
497         ut_assertnonnull(dev);
498         ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
499
500         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
501
502         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
503         ut_asserteq(1247, compress_frame_buffer(uts, dev));
504
505         return 0;
506 }
507 DM_TEST(dm_test_video_comp_bmp8, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
508
509 /* Test TrueType console */
510 static int dm_test_video_truetype(struct unit_test_state *uts)
511 {
512         struct udevice *dev, *con;
513         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";
514
515         ut_assertok(video_get_nologo(uts, &dev));
516         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
517         vidconsole_put_string(con, test_string);
518         ut_asserteq(12237, compress_frame_buffer(uts, dev));
519
520         return 0;
521 }
522 DM_TEST(dm_test_video_truetype, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
523
524 /* Test scrolling TrueType console */
525 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
526 {
527         struct sandbox_sdl_plat *plat;
528         struct udevice *dev, *con;
529         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";
530
531         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
532         ut_assert(!device_active(dev));
533         plat = dev_get_plat(dev);
534         plat->font_size = 100;
535
536         ut_assertok(video_get_nologo(uts, &dev));
537         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
538         vidconsole_put_string(con, test_string);
539         ut_asserteq(35030, compress_frame_buffer(uts, dev));
540
541         return 0;
542 }
543 DM_TEST(dm_test_video_truetype_scroll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
544
545 /* Test TrueType backspace, within and across lines */
546 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
547 {
548         struct sandbox_sdl_plat *plat;
549         struct udevice *dev, *con;
550         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.";
551
552         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
553         ut_assert(!device_active(dev));
554         plat = dev_get_plat(dev);
555         plat->font_size = 100;
556
557         ut_assertok(video_get_nologo(uts, &dev));
558         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
559         vidconsole_put_string(con, test_string);
560         ut_asserteq(29018, compress_frame_buffer(uts, dev));
561
562         return 0;
563 }
564 DM_TEST(dm_test_video_truetype_bs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
This page took 0.067323 seconds and 4 git commands to generate.