|
@@ -0,0 +1,190 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2014 Google, Inc
|
|
|
|
+ * Written by Simon Glass <sjg@chromium.org>
|
|
|
|
+ *
|
|
|
|
+ * SPDX-License-Identifier: GPL-2.0+
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include <common.h>
|
|
|
|
+#include <bzlib.h>
|
|
|
|
+#include <dm.h>
|
|
|
|
+#include <mapmem.h>
|
|
|
|
+#include <os.h>
|
|
|
|
+#include <video.h>
|
|
|
|
+#include <video_console.h>
|
|
|
|
+#include <dm/test.h>
|
|
|
|
+#include <dm/uclass-internal.h>
|
|
|
|
+#include <test/ut.h>
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * These tests use the standard sandbox frame buffer, the resolution of which
|
|
|
|
+ * is defined in the device tree. This only supports 16bpp so the tests only
|
|
|
|
+ * test that code path. It would be possible to adjust this fairly easily,
|
|
|
|
+ * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
|
|
|
|
+ * in sandbox_sdl_sync() would also need to change to handle the different
|
|
|
|
+ * surface depth.
|
|
|
|
+ */
|
|
|
|
+DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
+
|
|
|
|
+/* Basic test of the video uclass */
|
|
|
|
+static int dm_test_video_base(struct unit_test_state *uts)
|
|
|
|
+{
|
|
|
|
+ struct video_priv *priv;
|
|
|
|
+ struct udevice *dev;
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
|
|
|
|
+ ut_asserteq(1366, video_get_xsize(dev));
|
|
|
|
+ ut_asserteq(768, video_get_ysize(dev));
|
|
|
|
+ priv = dev_get_uclass_priv(dev);
|
|
|
|
+ ut_asserteq(priv->fb_size, 1366 * 768 * 2);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * compress_frame_buffer() - Compress the frame buffer and return its size
|
|
|
|
+ *
|
|
|
|
+ * We want to write tests which perform operations on the video console and
|
|
|
|
+ * check that the frame buffer ends up with the correct contents. But it is
|
|
|
|
+ * painful to store 'known good' images for comparison with the frame
|
|
|
|
+ * buffer. As an alternative, we can compress the frame buffer and check the
|
|
|
|
+ * size of the compressed data. This provides a pretty good level of
|
|
|
|
+ * certainty and the resulting tests need only check a single value.
|
|
|
|
+ *
|
|
|
|
+ * @dev: Video device
|
|
|
|
+ * @return compressed size of the frame buffer, or -ve on error
|
|
|
|
+ */
|
|
|
|
+static int compress_frame_buffer(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct video_priv *priv = dev_get_uclass_priv(dev);
|
|
|
|
+ uint destlen;
|
|
|
|
+ void *dest;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ destlen = priv->fb_size;
|
|
|
|
+ dest = malloc(priv->fb_size);
|
|
|
|
+ if (!dest)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
|
|
|
|
+ priv->fb, priv->fb_size,
|
|
|
|
+ 3, 0, 0);
|
|
|
|
+ free(dest);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ return destlen;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Call this function at any point to halt and show the current display. Be
|
|
|
|
+ * sure to run the test with the -l flag.
|
|
|
|
+ */
|
|
|
|
+static void __maybe_unused see_output(void)
|
|
|
|
+{
|
|
|
|
+ video_sync_all();
|
|
|
|
+ while (1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Test text output works on the video console */
|
|
|
|
+static int dm_test_video_text(struct unit_test_state *uts)
|
|
|
|
+{
|
|
|
|
+ struct udevice *dev, *con;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+#define WHITE 0xffff
|
|
|
|
+#define SCROLL_LINES 100
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
|
|
|
|
+ ut_asserteq(46, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
|
|
|
|
+ vidconsole_putc_xy(con, 0, 0, 'a');
|
|
|
|
+ ut_asserteq(79, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ vidconsole_putc_xy(con, 0, 0, ' ');
|
|
|
|
+ ut_asserteq(46, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 20; i++)
|
|
|
|
+ vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
|
|
|
|
+ ut_asserteq(273, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ vidconsole_set_row(con, 0, WHITE);
|
|
|
|
+ ut_asserteq(46, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 20; i++)
|
|
|
|
+ vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
|
|
|
|
+ ut_asserteq(273, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
|
|
+
|
|
|
|
+/* Test handling of special characters in the console */
|
|
|
|
+static int dm_test_video_chars(struct unit_test_state *uts)
|
|
|
|
+{
|
|
|
|
+ struct udevice *dev, *con;
|
|
|
|
+ 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.";
|
|
|
|
+ const char *s;
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
|
|
|
|
+ for (s = test_string; *s; s++)
|
|
|
|
+ vidconsole_put_char(con, *s);
|
|
|
|
+ ut_asserteq(466, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * check_vidconsole_output() - Run a text console test
|
|
|
|
+ *
|
|
|
|
+ * @uts: Test state
|
|
|
|
+ * @rot: Console rotation (0, 90, 180, 270)
|
|
|
|
+ * @wrap_size: Expected size of compressed frame buffer for the wrap test
|
|
|
|
+ * @scroll_size: Same for the scroll test
|
|
|
|
+ * @return 0 on success
|
|
|
|
+ */
|
|
|
|
+static int check_vidconsole_output(struct unit_test_state *uts, int rot,
|
|
|
|
+ int wrap_size, int scroll_size)
|
|
|
|
+{
|
|
|
|
+ struct udevice *dev, *con;
|
|
|
|
+ struct sandbox_sdl_plat *plat;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
|
|
|
|
+ ut_assert(!device_active(dev));
|
|
|
|
+ plat = dev_get_platdata(dev);
|
|
|
|
+ plat->rot = rot;
|
|
|
|
+
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
|
|
|
|
+ ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
|
|
|
|
+ ut_asserteq(46, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ /* Check display wrap */
|
|
|
|
+ for (i = 0; i < 120; i++)
|
|
|
|
+ vidconsole_put_char(con, 'A' + i % 50);
|
|
|
|
+ ut_asserteq(wrap_size, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ /* Check display scrolling */
|
|
|
|
+ for (i = 0; i < SCROLL_LINES; i++) {
|
|
|
|
+ vidconsole_put_char(con, 'A' + i % 50);
|
|
|
|
+ vidconsole_put_char(con, '\n');
|
|
|
|
+ }
|
|
|
|
+ ut_asserteq(scroll_size, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ /* If we scroll enough, the screen becomes blank again */
|
|
|
|
+ for (i = 0; i < SCROLL_LINES; i++)
|
|
|
|
+ vidconsole_put_char(con, '\n');
|
|
|
|
+ ut_asserteq(46, compress_frame_buffer(dev));
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Test text output through the console uclass */
|
|
|
|
+static int dm_test_video_context(struct unit_test_state *uts)
|
|
|
|
+{
|
|
|
|
+ return check_vidconsole_output(uts, 0, 788, 453);
|
|
|
|
+}
|
|
|
|
+DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|