summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:22:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:22:22 +0000
commit3f13df4d019cfcbef3f9909e3b993896d3c934e6 (patch)
tree6c515810bee8549d81e68c548a26a63909f8e716 /tests
parentInitial commit. (diff)
downloadlibdrm-3f13df4d019cfcbef3f9909e3b993896d3c934e6.tar.xz
libdrm-3f13df4d019cfcbef3f9909e3b993896d3c934e6.zip
Adding upstream version 2.4.114.upstream/2.4.114upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.mk1
l---------tests/amdgpu/.editorconfig1
-rw-r--r--tests/amdgpu/amdgpu_stress.c418
-rw-r--r--tests/amdgpu/amdgpu_test.c830
-rw-r--r--tests/amdgpu/amdgpu_test.h546
-rw-r--r--tests/amdgpu/basic_tests.c2556
-rw-r--r--tests/amdgpu/bo_tests.c317
-rw-r--r--tests/amdgpu/cp_dma_tests.c533
-rw-r--r--tests/amdgpu/cs_tests.c471
-rw-r--r--tests/amdgpu/deadlock_tests.c696
-rw-r--r--tests/amdgpu/decode_messages.h881
-rw-r--r--tests/amdgpu/frame.h1949
-rw-r--r--tests/amdgpu/hotunplug_tests.c443
-rw-r--r--tests/amdgpu/jpeg_tests.c579
-rw-r--r--tests/amdgpu/meson.build46
-rw-r--r--tests/amdgpu/ras_tests.c1003
-rw-r--r--tests/amdgpu/security_tests.c486
-rw-r--r--tests/amdgpu/shader_code.h153
-rw-r--r--tests/amdgpu/shader_code_gfx10.h202
-rw-r--r--tests/amdgpu/shader_code_gfx11.h320
-rw-r--r--tests/amdgpu/shader_code_gfx9.h204
-rw-r--r--tests/amdgpu/shader_code_hang.h104
-rw-r--r--tests/amdgpu/shader_test_util.c2156
-rw-r--r--tests/amdgpu/syncobj_tests.c314
-rw-r--r--tests/amdgpu/uvd_enc_tests.c491
-rw-r--r--tests/amdgpu/uve_ib.h527
-rw-r--r--tests/amdgpu/vce_ib.h335
-rw-r--r--tests/amdgpu/vce_tests.c764
-rw-r--r--tests/amdgpu/vcn_tests.c1635
-rw-r--r--tests/amdgpu/vm_tests.c270
-rw-r--r--tests/drmdevice.c164
-rw-r--r--tests/drmsl.c184
-rw-r--r--tests/etnaviv/cmdstream.xml.h242
-rw-r--r--tests/etnaviv/etnaviv_2d_test.c290
-rw-r--r--tests/etnaviv/etnaviv_bo_cache_test.c117
-rw-r--r--tests/etnaviv/etnaviv_cmd_stream_test.c123
-rw-r--r--tests/etnaviv/meson.build45
-rw-r--r--tests/etnaviv/state.xml.h375
-rw-r--r--tests/etnaviv/state_2d.xml.h1497
-rw-r--r--tests/etnaviv/write_bmp.c149
-rw-r--r--tests/etnaviv/write_bmp.h34
-rw-r--r--tests/exynos/exynos_fimg2d_event.c333
-rw-r--r--tests/exynos/exynos_fimg2d_perf.c327
-rw-r--r--tests/exynos/exynos_fimg2d_test.c903
-rw-r--r--tests/exynos/meson.build51
-rw-r--r--tests/hash.c217
-rw-r--r--tests/meson.build74
-rw-r--r--tests/modeprint/meson.build29
-rw-r--r--tests/modeprint/modeprint.c418
-rw-r--r--tests/modetest/Android.mk14
-rw-r--r--tests/modetest/Makefile.sources6
-rw-r--r--tests/modetest/buffers.c340
-rw-r--r--tests/modetest/buffers.h40
-rw-r--r--tests/modetest/cursor.c206
-rw-r--r--tests/modetest/cursor.h33
-rw-r--r--tests/modetest/meson.build29
-rw-r--r--tests/modetest/modetest.c2285
-rw-r--r--tests/nouveau/.gitignore1
-rw-r--r--tests/nouveau/meson.build30
-rw-r--r--tests/nouveau/threaded.c156
-rw-r--r--tests/proptest/Android.mk14
-rw-r--r--tests/proptest/Makefile.sources2
-rw-r--r--tests/proptest/meson.build28
-rw-r--r--tests/proptest/proptest.c325
-rw-r--r--tests/radeon/meson.build27
-rw-r--r--tests/radeon/radeon_ttm.c77
-rw-r--r--tests/radeon/rbo.c171
-rw-r--r--tests/radeon/rbo.h50
-rw-r--r--tests/tegra/.gitignore2
-rw-r--r--tests/tegra/drm-test-tegra.c147
-rw-r--r--tests/tegra/drm-test-tegra.h55
-rw-r--r--tests/tegra/drm-test.c248
-rw-r--r--tests/tegra/drm-test.h72
-rw-r--r--tests/tegra/gr2d-fill.c146
-rw-r--r--tests/tegra/host1x.h34
-rw-r--r--tests/tegra/meson.build111
-rw-r--r--tests/tegra/openclose.c67
-rw-r--r--tests/tegra/syncpt-timeout.c163
-rw-r--r--tests/tegra/syncpt-wait.c151
-rw-r--r--tests/tegra/vic-blit.c333
-rw-r--r--tests/tegra/vic-clear.c173
-rw-r--r--tests/tegra/vic-flip.c333
-rw-r--r--tests/tegra/vic.c184
-rw-r--r--tests/tegra/vic.h181
-rw-r--r--tests/tegra/vic30.c458
-rw-r--r--tests/tegra/vic30.h439
-rw-r--r--tests/tegra/vic40.c338
-rw-r--r--tests/tegra/vic40.h285
-rw-r--r--tests/tegra/vic41.c342
-rw-r--r--tests/tegra/vic41.h372
-rw-r--r--tests/tegra/vic42.c342
-rw-r--r--tests/tegra/vic42.h597
-rw-r--r--tests/ttmtest/AUTHORS1
-rw-r--r--tests/ttmtest/ChangeLog23
-rw-r--r--tests/ttmtest/Makefile.am1
-rw-r--r--tests/ttmtest/NEWS0
-rw-r--r--tests/ttmtest/README0
-rw-r--r--tests/ttmtest/configure.ac33
-rwxr-xr-xtests/ttmtest/reconf2
-rw-r--r--tests/ttmtest/src/Makefile.am8
-rw-r--r--tests/ttmtest/src/ttmtest.c430
-rw-r--r--tests/ttmtest/src/xf86dri.c603
-rw-r--r--tests/ttmtest/src/xf86dri.h116
-rw-r--r--tests/ttmtest/src/xf86dristr.h390
-rw-r--r--tests/util/Android.mk38
-rw-r--r--tests/util/Makefile.sources8
-rw-r--r--tests/util/common.h33
-rw-r--r--tests/util/format.c123
-rw-r--r--tests/util/format.h65
-rw-r--r--tests/util/kms.c163
-rw-r--r--tests/util/kms.h34
-rw-r--r--tests/util/meson.build28
-rw-r--r--tests/util/pattern.c1282
-rw-r--r--tests/util/pattern.h46
-rw-r--r--tests/vbltest/meson.build28
-rw-r--r--tests/vbltest/vbltest.c186
116 files changed, 37851 insertions, 0 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/tests/amdgpu/.editorconfig b/tests/amdgpu/.editorconfig
new file mode 120000
index 0000000..70734e4
--- /dev/null
+++ b/tests/amdgpu/.editorconfig
@@ -0,0 +1 @@
+../../amdgpu/.editorconfig \ No newline at end of file
diff --git a/tests/amdgpu/amdgpu_stress.c b/tests/amdgpu/amdgpu_stress.c
new file mode 100644
index 0000000..5c5c88c
--- /dev/null
+++ b/tests/amdgpu/amdgpu_stress.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "drm.h"
+#include "xf86drmMode.h"
+#include "xf86drm.h"
+#include "amdgpu.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#define MAX_CARDS_SUPPORTED 4
+#define NUM_BUFFER_OBJECTS 1024
+
+#define SDMA_PACKET(op, sub_op, e) ((((e) & 0xFFFF) << 16) | \
+ (((sub_op) & 0xFF) << 8) | \
+ (((op) & 0xFF) << 0))
+
+#define SDMA_OPCODE_COPY 1
+# define SDMA_COPY_SUB_OPCODE_LINEAR 0
+
+
+#define SDMA_PACKET_SI(op, b, t, s, cnt) ((((op) & 0xF) << 28) | \
+ (((b) & 0x1) << 26) | \
+ (((t) & 0x1) << 23) | \
+ (((s) & 0x1) << 22) | \
+ (((cnt) & 0xFFFFF) << 0))
+#define SDMA_OPCODE_COPY_SI 3
+
+
+/** Help string for command line parameters */
+static const char usage[] =
+ "Usage: %s [-?h] [-b v|g|vg size] "
+ "[-c from to size count]\n"
+ "where:\n"
+ " b - Allocate a BO in VRAM, GTT or VRAM|GTT of size bytes.\n"
+ " This flag can be used multiple times. The first bo will\n"
+ " have id `1`, then second id `2`, ...\n"
+ " c - Copy size bytes from BO (bo_id1) to BO (bo_id2), count times\n"
+ " h - Display this help\n"
+ "\n"
+ "Sizes can be postfixes with k, m or g for kilo, mega and gigabyte scaling\n";
+
+/** Specified options strings for getopt */
+static const char options[] = "?hb:c:";
+
+/* Open AMD devices.
+ * Returns the fd of the first device it could open.
+ */
+static int amdgpu_open_device(void)
+{
+ drmDevicePtr devices[MAX_CARDS_SUPPORTED];
+ unsigned int i;
+ int drm_count;
+
+ drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
+ if (drm_count < 0) {
+ fprintf(stderr, "drmGetDevices2() returned an error %d\n",
+ drm_count);
+ return drm_count;
+ }
+
+ for (i = 0; i < drm_count; i++) {
+ drmVersionPtr version;
+ int fd;
+
+ /* If this is not PCI device, skip*/
+ if (devices[i]->bustype != DRM_BUS_PCI)
+ continue;
+
+ /* If this is not AMD GPU vender ID, skip*/
+ if (devices[i]->deviceinfo.pci->vendor_id != 0x1002)
+ continue;
+
+ if (!(devices[i]->available_nodes & 1 << DRM_NODE_RENDER))
+ continue;
+
+ fd = open(devices[i]->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC);
+
+ /* This node is not available. */
+ if (fd < 0) continue;
+
+ version = drmGetVersion(fd);
+ if (!version) {
+ fprintf(stderr,
+ "Warning: Cannot get version for %s."
+ "Error is %s\n",
+ devices[i]->nodes[DRM_NODE_RENDER],
+ strerror(errno));
+ close(fd);
+ continue;
+ }
+
+ if (strcmp(version->name, "amdgpu")) {
+ /* This is not AMDGPU driver, skip.*/
+ drmFreeVersion(version);
+ close(fd);
+ continue;
+ }
+
+ drmFreeVersion(version);
+ drmFreeDevices(devices, drm_count);
+ return fd;
+ }
+
+ return -1;
+}
+
+amdgpu_device_handle device_handle;
+amdgpu_context_handle context_handle;
+
+amdgpu_bo_handle resources[NUM_BUFFER_OBJECTS];
+uint64_t virtual[NUM_BUFFER_OBJECTS];
+unsigned int num_buffers;
+uint32_t *pm4;
+
+int alloc_bo(uint32_t domain, uint64_t size)
+{
+ struct amdgpu_bo_alloc_request request = {};
+ amdgpu_bo_handle bo;
+ amdgpu_va_handle va;
+ uint64_t addr;
+ int r;
+
+ if (num_buffers >= NUM_BUFFER_OBJECTS)
+ return -ENOSPC;
+
+ request.alloc_size = size;
+ request.phys_alignment = 0;
+ request.preferred_heap = domain;
+ request.flags = 0;
+ r = amdgpu_bo_alloc(device_handle, &request, &bo);
+ if (r)
+ return r;
+
+ r = amdgpu_va_range_alloc(device_handle, amdgpu_gpu_va_range_general,
+ size, 0, 0, &addr, &va, 0);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_va_op_raw(device_handle, bo, 0, size, addr,
+ AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE |
+ AMDGPU_VM_PAGE_EXECUTABLE, AMDGPU_VA_OP_MAP);
+ if (r)
+ return r;
+
+ resources[num_buffers] = bo;
+ virtual[num_buffers] = addr;
+ fprintf(stdout, "Allocated BO number %u at 0x%lx, domain 0x%x, size %lu\n",
+ num_buffers++, addr, domain, size);
+ return 0;
+}
+
+int submit_ib(uint32_t from, uint32_t to, uint64_t size, uint32_t count)
+{
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_fence fence_status;
+ struct amdgpu_cs_ib_info ib_info;
+ uint64_t copied = size, delta;
+ struct timespec start, stop;
+
+ uint64_t src = virtual[from];
+ uint64_t dst = virtual[to];
+ uint32_t expired;
+ int i, r;
+
+ i = 0;
+ while (size) {
+ uint64_t bytes = size < 0x40000 ? size : 0x40000;
+
+ if (device_handle->info.family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, 0, 0, 0,
+ bytes);
+ pm4[i++] = 0xffffffff & dst;
+ pm4[i++] = 0xffffffff & src;
+ pm4[i++] = (0xffffffff00000000 & dst) >> 32;
+ pm4[i++] = (0xffffffff00000000 & src) >> 32;
+ } else {
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY,
+ SDMA_COPY_SUB_OPCODE_LINEAR,
+ 0);
+ if ( device_handle->info.family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = bytes - 1;
+ else
+ pm4[i++] = bytes;
+ pm4[i++] = 0;
+ pm4[i++] = 0xffffffff & src;
+ pm4[i++] = (0xffffffff00000000 & src) >> 32;
+ pm4[i++] = 0xffffffff & dst;
+ pm4[i++] = (0xffffffff00000000 & dst) >> 32;
+ }
+
+ size -= bytes;
+ src += bytes;
+ dst += bytes;
+ }
+
+ memset(&ib_info, 0, sizeof(ib_info));
+ ib_info.ib_mc_address = virtual[0];
+ ib_info.size = i;
+
+ memset(&ibs_request, 0, sizeof(ibs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_DMA;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = clock_gettime(CLOCK_MONOTONIC, &start);
+ if (r)
+ return errno;
+
+ r = amdgpu_bo_list_create(device_handle, num_buffers, resources, NULL,
+ &ibs_request.resources);
+ if (r)
+ return r;
+
+ for (i = 0; i < count; ++i) {
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+ }
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ memset(&fence_status, 0, sizeof(fence_status));
+ fence_status.ip_type = ibs_request.ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.ring = ibs_request.ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request.seq_no;
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ r = clock_gettime(CLOCK_MONOTONIC, &stop);
+ if (r)
+ return errno;
+
+ delta = stop.tv_nsec + stop.tv_sec * 1000000000UL;
+ delta -= start.tv_nsec + start.tv_sec * 1000000000UL;
+
+ fprintf(stdout, "Submitted %u IBs to copy from %u(%lx) to %u(%lx) %lu bytes took %lu usec\n",
+ count, from, virtual[from], to, virtual[to], copied, delta / 1000);
+ return 0;
+}
+
+void next_arg(int argc, char **argv, const char *msg)
+{
+ optarg = argv[optind++];
+ if (optind > argc || optarg[0] == '-') {
+ fprintf(stderr, "%s\n", msg);
+ exit(EXIT_FAILURE);
+ }
+}
+
+uint64_t parse_size(void)
+{
+ uint64_t size;
+ char ext[2];
+
+ ext[0] = 0;
+ if (sscanf(optarg, "%li%1[kmgKMG]", &size, ext) < 1) {
+ fprintf(stderr, "Can't parse size arg: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ switch (ext[0]) {
+ case 'k':
+ case 'K':
+ size *= 1024;
+ break;
+ case 'm':
+ case 'M':
+ size *= 1024 * 1024;
+ break;
+ case 'g':
+ case 'G':
+ size *= 1024 * 1024 * 1024;
+ break;
+ default:
+ break;
+ }
+ return size;
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t major_version, minor_version;
+ uint32_t domain, from, to, count;
+ uint64_t size;
+ int fd, r, c;
+
+ fd = amdgpu_open_device();
+ if (fd < 0) {
+ perror("Cannot open AMDGPU device");
+ exit(EXIT_FAILURE);
+ }
+
+ r = amdgpu_device_initialize(fd, &major_version, &minor_version, &device_handle);
+ if (r) {
+ fprintf(stderr, "amdgpu_device_initialize returned %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r) {
+ fprintf(stderr, "amdgpu_cs_ctx_create returned %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+
+ if (argc == 1) {
+ fprintf(stderr, usage, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ r = alloc_bo(AMDGPU_GEM_DOMAIN_GTT, 2ULL * 1024 * 1024);
+ if (r) {
+ fprintf(stderr, "Buffer allocation failed with %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+
+ r = amdgpu_bo_cpu_map(resources[0], (void **)&pm4);
+ if (r) {
+ fprintf(stderr, "Buffer mapping failed with %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, options)) != -1) {
+ switch (c) {
+ case 'b':
+ if (!strcmp(optarg, "v"))
+ domain = AMDGPU_GEM_DOMAIN_VRAM;
+ else if (!strcmp(optarg, "g"))
+ domain = AMDGPU_GEM_DOMAIN_GTT;
+ else if (!strcmp(optarg, "vg"))
+ domain = AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT;
+ else {
+ fprintf(stderr, "Invalid domain: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ next_arg(argc, argv, "Missing buffer size");
+ size = parse_size();
+ if (size < getpagesize()) {
+ fprintf(stderr, "Buffer size to small %lu\n", size);
+ exit(EXIT_FAILURE);
+ }
+ r = alloc_bo(domain, size);
+ if (r) {
+ fprintf(stderr, "Buffer allocation failed with %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'c':
+ if (sscanf(optarg, "%u", &from) != 1) {
+ fprintf(stderr, "Can't parse from buffer: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ next_arg(argc, argv, "Missing to buffer");
+ if (sscanf(optarg, "%u", &to) != 1) {
+ fprintf(stderr, "Can't parse to buffer: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ next_arg(argc, argv, "Missing size");
+ size = parse_size();
+ next_arg(argc, argv, "Missing count");
+ count = parse_size();
+ r = submit_ib(from, to, size, count);
+ if (r) {
+ fprintf(stderr, "IB submission failed with %d\n", r);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '?':
+ case 'h':
+ fprintf(stderr, usage, argv[0]);
+ exit(EXIT_SUCCESS);
+ default:
+ fprintf(stderr, usage, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c
new file mode 100644
index 0000000..9abe573
--- /dev/null
+++ b/tests/amdgpu/amdgpu_test.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdint.h>
+#ifdef __linux__
+#include <linux/limits.h>
+#elif __FreeBSD__
+/* SPECNAMELEN in FreeBSD is defined here: */
+#include <sys/param.h>
+#endif
+#ifdef MAJOR_IN_MKDEV
+#include <sys/mkdev.h>
+#endif
+#ifdef MAJOR_IN_SYSMACROS
+#include <sys/sysmacros.h>
+#endif
+
+#include "drm.h"
+#include "xf86drmMode.h"
+#include "xf86drm.h"
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_internal.h"
+
+/* Test suite names */
+#define BASIC_TESTS_STR "Basic Tests"
+#define BO_TESTS_STR "BO Tests"
+#define CS_TESTS_STR "CS Tests"
+#define VCE_TESTS_STR "VCE Tests"
+#define VCN_TESTS_STR "VCN Tests"
+#define JPEG_TESTS_STR "JPEG Tests"
+#define UVD_ENC_TESTS_STR "UVD ENC Tests"
+#define DEADLOCK_TESTS_STR "Deadlock Tests"
+#define VM_TESTS_STR "VM Tests"
+#define RAS_TESTS_STR "RAS Tests"
+#define SYNCOBJ_TIMELINE_TESTS_STR "SYNCOBJ TIMELINE Tests"
+#define SECURITY_TESTS_STR "Security Tests"
+#define HOTUNPLUG_TESTS_STR "Hotunplug Tests"
+#define CP_DMA_TESTS_STR "CP DMA Tests"
+
+/**
+ * Open handles for amdgpu devices
+ *
+ */
+int drm_amdgpu[MAX_CARDS_SUPPORTED];
+
+/** Open render node to test */
+int open_render_node = 0; /* By default run most tests on primary node */
+
+/** The table of all known test suites to run */
+static CU_SuiteInfo suites[] = {
+ {
+ .pName = BASIC_TESTS_STR,
+ .pInitFunc = suite_basic_tests_init,
+ .pCleanupFunc = suite_basic_tests_clean,
+ .pTests = basic_tests,
+ },
+ {
+ .pName = BO_TESTS_STR,
+ .pInitFunc = suite_bo_tests_init,
+ .pCleanupFunc = suite_bo_tests_clean,
+ .pTests = bo_tests,
+ },
+ {
+ .pName = CS_TESTS_STR,
+ .pInitFunc = suite_cs_tests_init,
+ .pCleanupFunc = suite_cs_tests_clean,
+ .pTests = cs_tests,
+ },
+ {
+ .pName = VCE_TESTS_STR,
+ .pInitFunc = suite_vce_tests_init,
+ .pCleanupFunc = suite_vce_tests_clean,
+ .pTests = vce_tests,
+ },
+ {
+ .pName = VCN_TESTS_STR,
+ .pInitFunc = suite_vcn_tests_init,
+ .pCleanupFunc = suite_vcn_tests_clean,
+ .pTests = vcn_tests,
+ },
+ {
+ .pName = JPEG_TESTS_STR,
+ .pInitFunc = suite_jpeg_tests_init,
+ .pCleanupFunc = suite_jpeg_tests_clean,
+ .pTests = jpeg_tests,
+ },
+ {
+ .pName = UVD_ENC_TESTS_STR,
+ .pInitFunc = suite_uvd_enc_tests_init,
+ .pCleanupFunc = suite_uvd_enc_tests_clean,
+ .pTests = uvd_enc_tests,
+ },
+ {
+ .pName = DEADLOCK_TESTS_STR,
+ .pInitFunc = suite_deadlock_tests_init,
+ .pCleanupFunc = suite_deadlock_tests_clean,
+ .pTests = deadlock_tests,
+ },
+ {
+ .pName = VM_TESTS_STR,
+ .pInitFunc = suite_vm_tests_init,
+ .pCleanupFunc = suite_vm_tests_clean,
+ .pTests = vm_tests,
+ },
+ {
+ .pName = RAS_TESTS_STR,
+ .pInitFunc = suite_ras_tests_init,
+ .pCleanupFunc = suite_ras_tests_clean,
+ .pTests = ras_tests,
+ },
+ {
+ .pName = SYNCOBJ_TIMELINE_TESTS_STR,
+ .pInitFunc = suite_syncobj_timeline_tests_init,
+ .pCleanupFunc = suite_syncobj_timeline_tests_clean,
+ .pTests = syncobj_timeline_tests,
+ },
+ {
+ .pName = SECURITY_TESTS_STR,
+ .pInitFunc = suite_security_tests_init,
+ .pCleanupFunc = suite_security_tests_clean,
+ .pTests = security_tests,
+ },
+ {
+ .pName = HOTUNPLUG_TESTS_STR,
+ .pInitFunc = suite_hotunplug_tests_init,
+ .pCleanupFunc = suite_hotunplug_tests_clean,
+ .pTests = hotunplug_tests,
+ },
+ {
+ .pName = CP_DMA_TESTS_STR,
+ .pInitFunc = suite_cp_dma_tests_init,
+ .pCleanupFunc = suite_cp_dma_tests_clean,
+ .pTests = cp_dma_tests,
+ },
+
+ CU_SUITE_INFO_NULL,
+};
+
+typedef CU_BOOL (*active__stat_func)(void);
+
+typedef struct Suites_Active_Status {
+ char* pName;
+ active__stat_func pActive;
+}Suites_Active_Status;
+
+static CU_BOOL always_active()
+{
+ return CU_TRUE;
+}
+
+static Suites_Active_Status suites_active_stat[] = {
+ {
+ .pName = BASIC_TESTS_STR,
+ .pActive = suite_basic_tests_enable,
+ },
+ {
+ .pName = BO_TESTS_STR,
+ .pActive = always_active,
+ },
+ {
+ .pName = CS_TESTS_STR,
+ .pActive = suite_cs_tests_enable,
+ },
+ {
+ .pName = VCE_TESTS_STR,
+ .pActive = suite_vce_tests_enable,
+ },
+ {
+ .pName = VCN_TESTS_STR,
+ .pActive = suite_vcn_tests_enable,
+ },
+ {
+ .pName = JPEG_TESTS_STR,
+ .pActive = suite_jpeg_tests_enable,
+ },
+ {
+ .pName = UVD_ENC_TESTS_STR,
+ .pActive = suite_uvd_enc_tests_enable,
+ },
+ {
+ .pName = DEADLOCK_TESTS_STR,
+ .pActive = suite_deadlock_tests_enable,
+ },
+ {
+ .pName = VM_TESTS_STR,
+ .pActive = suite_vm_tests_enable,
+ },
+ {
+ .pName = RAS_TESTS_STR,
+ .pActive = suite_ras_tests_enable,
+ },
+ {
+ .pName = SYNCOBJ_TIMELINE_TESTS_STR,
+ .pActive = suite_syncobj_timeline_tests_enable,
+ },
+ {
+ .pName = SECURITY_TESTS_STR,
+ .pActive = suite_security_tests_enable,
+ },
+ {
+ .pName = HOTUNPLUG_TESTS_STR,
+ .pActive = suite_hotunplug_tests_enable,
+ },
+ {
+ .pName = CP_DMA_TESTS_STR,
+ .pActive = suite_cp_dma_tests_enable,
+ },
+};
+
+
+/*
+ * Display information about all suites and their tests
+ *
+ * NOTE: Must be run after registry is initialized and suites registered.
+ */
+static void display_test_suites(void)
+{
+ int iSuite;
+ int iTest;
+ CU_pSuite pSuite = NULL;
+ CU_pTest pTest = NULL;
+
+ printf("%5s: %2s: %8s: %s\n", "What", "ID", "Status", "Name");
+
+ for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) {
+
+ pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1,
+ CU_get_registry());
+
+ if (!pSuite) {
+ fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1);
+ continue;
+ }
+
+ printf("Suite: %2d: %8s: %s\n",
+ iSuite + 1,
+ pSuite->fActive ? "ENABLED" : "DISABLED",
+ suites[iSuite].pName);
+
+ if (!pSuite->fActive)
+ continue;
+
+ for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL;
+ iTest++) {
+ pTest = CU_get_test_by_index((unsigned int) iTest + 1,
+ pSuite);
+ if (!pTest) {
+ fprintf(stderr, "Invalid test id : %d\n", iTest + 1);
+ continue;
+ }
+ printf(" Test: %2d: %8s: %s\n",
+ iTest + 1,
+ pSuite->fActive && pTest->fActive ? "ENABLED" : "DISABLED",
+ suites[iSuite].pTests[iTest].pName);
+ }
+ }
+}
+
+/** Help string for command line parameters */
+static const char usage[] =
+ "Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>] [-f]] "
+ "[-b <pci_bus_id> [-d <pci_device_id>]]\n"
+ "where:\n"
+ " l - Display all suites and their tests\n"
+ " r - Run the tests on render node\n"
+ " b - Specify device's PCI bus id to run tests\n"
+ " d - Specify device's PCI device id to run tests (optional)\n"
+ " p - Display information of AMDGPU devices in system\n"
+ " f - Force executing inactive suite or test\n"
+ " h - Display this help\n";
+/** Specified options strings for getopt */
+static const char options[] = "hlrps:t:b:d:f";
+
+/* Open AMD devices.
+ * Return the number of AMD device opened.
+ */
+static int amdgpu_open_devices(int open_render_node)
+{
+ drmDevicePtr devices[MAX_CARDS_SUPPORTED];
+ int i;
+ int drm_node;
+ int amd_index = 0;
+ int drm_count;
+ int fd;
+ drmVersionPtr version;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED; i++) {
+ drm_amdgpu[i] = -1;
+ }
+
+ drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
+
+ if (drm_count < 0) {
+ fprintf(stderr,
+ "drmGetDevices2() returned an error %d\n",
+ drm_count);
+ return 0;
+ }
+
+ for (i = 0; i < drm_count; i++) {
+ /* If this is not PCI device, skip*/
+ if (devices[i]->bustype != DRM_BUS_PCI)
+ continue;
+
+ /* If this is not AMD GPU vender ID, skip*/
+ if (devices[i]->deviceinfo.pci->vendor_id != 0x1002)
+ continue;
+
+ if (open_render_node)
+ drm_node = DRM_NODE_RENDER;
+ else
+ drm_node = DRM_NODE_PRIMARY;
+
+ fd = -1;
+ if (devices[i]->available_nodes & 1 << drm_node)
+ fd = open(
+ devices[i]->nodes[drm_node],
+ O_RDWR | O_CLOEXEC);
+
+ /* This node is not available. */
+ if (fd < 0) continue;
+
+ version = drmGetVersion(fd);
+ if (!version) {
+ fprintf(stderr,
+ "Warning: Cannot get version for %s."
+ "Error is %s\n",
+ devices[i]->nodes[drm_node],
+ strerror(errno));
+ close(fd);
+ continue;
+ }
+
+ if (strcmp(version->name, "amdgpu")) {
+ /* This is not AMDGPU driver, skip.*/
+ drmFreeVersion(version);
+ close(fd);
+ continue;
+ }
+
+ drmFreeVersion(version);
+
+ drm_amdgpu[amd_index] = fd;
+ amd_index++;
+ }
+
+ drmFreeDevices(devices, drm_count);
+ return amd_index;
+}
+
+/* Close AMD devices.
+ */
+void amdgpu_close_devices()
+{
+ int i;
+ for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
+ if (drm_amdgpu[i] >=0) {
+ close(drm_amdgpu[i]);
+ }
+}
+
+/* Print AMD devices information */
+static void amdgpu_print_devices()
+{
+ int i;
+ drmDevicePtr device;
+
+ /* Open the first AMD device to print driver information. */
+ if (drm_amdgpu[0] >=0) {
+ /* Display AMD driver version information.*/
+ drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]);
+
+ if (retval == NULL) {
+ perror("Cannot get version for AMDGPU device");
+ return;
+ }
+
+ printf("Driver name: %s, Date: %s, Description: %s.\n",
+ retval->name, retval->date, retval->desc);
+ drmFreeVersion(retval);
+ }
+
+ /* Display information of AMD devices */
+ printf("Devices:\n");
+ for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++)
+ if (drmGetDevice2(drm_amdgpu[i],
+ DRM_DEVICE_GET_PCI_REVISION,
+ &device) == 0) {
+ if (device->bustype == DRM_BUS_PCI) {
+ printf("PCI ");
+ printf(" domain:%04x",
+ device->businfo.pci->domain);
+ printf(" bus:%02x",
+ device->businfo.pci->bus);
+ printf(" device:%02x",
+ device->businfo.pci->dev);
+ printf(" function:%01x",
+ device->businfo.pci->func);
+ printf(" vendor_id:%04x",
+ device->deviceinfo.pci->vendor_id);
+ printf(" device_id:%04x",
+ device->deviceinfo.pci->device_id);
+ printf(" subvendor_id:%04x",
+ device->deviceinfo.pci->subvendor_id);
+ printf(" subdevice_id:%04x",
+ device->deviceinfo.pci->subdevice_id);
+ printf(" revision_id:%02x",
+ device->deviceinfo.pci->revision_id);
+ printf("\n");
+ }
+ drmFreeDevice(&device);
+ }
+}
+
+/* Find a match AMD device in PCI bus
+ * Return the index of the device or -1 if not found
+ */
+static int amdgpu_find_device(uint8_t bus, uint16_t dev)
+{
+ int i;
+ drmDevicePtr device;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
+ if (drmGetDevice2(drm_amdgpu[i],
+ DRM_DEVICE_GET_PCI_REVISION,
+ &device) == 0) {
+ if (device->bustype == DRM_BUS_PCI)
+ if ((bus == 0xFF || device->businfo.pci->bus == bus) &&
+ device->deviceinfo.pci->device_id == dev) {
+ drmFreeDevice(&device);
+ return i;
+ }
+
+ drmFreeDevice(&device);
+ }
+ }
+
+ return -1;
+}
+
+static void amdgpu_disable_suites()
+{
+ amdgpu_device_handle device_handle;
+ uint32_t major_version, minor_version, family_id;
+ drmDevicePtr devices[MAX_CARDS_SUPPORTED];
+ int i, drm_count;
+ int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]);
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return;
+
+ family_id = device_handle->info.family_id;
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return;
+
+ drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
+
+ /* Set active status for suites based on their policies */
+ for (i = 0; i < size; ++i)
+ if (amdgpu_set_suite_active(suites_active_stat[i].pName,
+ suites_active_stat[i].pActive()))
+ fprintf(stderr, "suite deactivation failed - %s\n", CU_get_error_msg());
+
+ /* Explicitly disable specific tests due to known bugs or preferences */
+ /*
+ * BUG: Compute ring stalls and never recovers when the address is
+ * written after the command already submitted
+ */
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "compute ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "sdma ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "gfx ring slow bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "sdma ring corrupted header test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
+ "sdma ring slow linear copy test (set amdgpu.lockup_timeout=50)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "bo eviction Test", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX8 and GFX9 only */
+ if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) {
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test (GFX)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test (Compute)", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+ }
+
+ /* This test was ran on GFX9 only */
+ if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "Draw Test", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* This test was ran on GFX9 only */
+ //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
+ if (amdgpu_set_test_active(BASIC_TESTS_STR, "GPU reset Test", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+ /* You need at least 2 devices for this */
+ if (drm_count < 2)
+ if (amdgpu_set_test_active(HOTUNPLUG_TESTS_STR, "Unplug with exported fence", CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+}
+
+int test_device_index;
+
+int amdgpu_open_device_on_test_index(int render_node)
+{
+ int i;
+
+ if (amdgpu_open_devices(open_render_node) <= 0) {
+ perror("Cannot open AMDGPU device");
+ return -1;
+ }
+
+ if (test_device_index >= 0) {
+ /* Most tests run on device of drm_amdgpu[0].
+ * Swap the chosen device to drm_amdgpu[0].
+ */
+ i = drm_amdgpu[0];
+ drm_amdgpu[0] = drm_amdgpu[test_device_index];
+ drm_amdgpu[test_device_index] = i;
+ }
+
+ return 0;
+
+
+}
+
+
+static bool amdgpu_node_is_drm(int maj, int min)
+{
+#ifdef __linux__
+ char path[64];
+ struct stat sbuf;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
+ maj, min);
+ return stat(path, &sbuf) == 0;
+#elif defined(__FreeBSD__)
+ char name[SPECNAMELEN];
+
+ if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name)))
+ return 0;
+ /* Handle drm/ and dri/ as both are present in different FreeBSD version
+ * FreeBSD on amd64/i386/powerpc external kernel modules create node in
+ * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
+ * only device nodes in /dev/dri/ */
+ return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4));
+#else
+ return maj == DRM_MAJOR;
+#endif
+}
+
+char *amdgpu_get_device_from_fd(int fd)
+{
+#ifdef __linux__
+ struct stat sbuf;
+ char path[PATH_MAX + 1];
+ unsigned int maj, min;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (!amdgpu_node_is_drm(maj, min) || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+ return strdup(path);
+#else
+ return NULL;
+#endif
+}
+
+/* The main() function for setting up and running the tests.
+ * Returns a CUE_SUCCESS on successful running, another
+ * CUnit error code on failure.
+ */
+int main(int argc, char **argv)
+{
+ int c; /* Character received from getopt */
+ int i = 0;
+ int suite_id = -1; /* By default run everything */
+ int test_id = -1; /* By default run all tests in the suite */
+ int pci_bus_id = -1; /* By default PC bus ID is not specified */
+ int pci_device_id = 0; /* By default PC device ID is zero */
+ int display_devices = 0;/* By default not to display devices' info */
+ CU_pSuite pSuite = NULL;
+ CU_pTest pTest = NULL;
+ int display_list = 0;
+ int force_run = 0;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
+ drm_amdgpu[i] = -1;
+
+
+ /* Parse command line string */
+ opterr = 0; /* Do not print error messages from getopt */
+ while ((c = getopt(argc, argv, options)) != -1) {
+ switch (c) {
+ case 'l':
+ display_list = 1;
+ break;
+ case 's':
+ suite_id = atoi(optarg);
+ break;
+ case 't':
+ test_id = atoi(optarg);
+ break;
+ case 'b':
+ pci_bus_id = atoi(optarg);
+ break;
+ case 'd':
+ sscanf(optarg, "%x", &pci_device_id);
+ break;
+ case 'p':
+ display_devices = 1;
+ break;
+ case 'r':
+ open_render_node = 1;
+ break;
+ case 'f':
+ force_run = 1;
+ break;
+ case '?':
+ case 'h':
+ fprintf(stderr, usage, argv[0]);
+ exit(EXIT_SUCCESS);
+ default:
+ fprintf(stderr, usage, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (amdgpu_open_devices(open_render_node) <= 0) {
+ perror("Cannot open AMDGPU device");
+ exit(EXIT_FAILURE);
+ }
+
+ if (drm_amdgpu[0] < 0) {
+ perror("Cannot open AMDGPU device");
+ exit(EXIT_FAILURE);
+ }
+
+ if (display_devices) {
+ amdgpu_print_devices();
+ amdgpu_close_devices();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (pci_bus_id > 0 || pci_device_id) {
+ /* A device was specified to run the test */
+ test_device_index = amdgpu_find_device(pci_bus_id,
+ pci_device_id);
+
+ if (test_device_index >= 0) {
+ /* Most tests run on device of drm_amdgpu[0].
+ * Swap the chosen device to drm_amdgpu[0].
+ */
+ i = drm_amdgpu[0];
+ drm_amdgpu[0] = drm_amdgpu[test_device_index];
+ drm_amdgpu[test_device_index] = i;
+ } else {
+ fprintf(stderr,
+ "The specified GPU device does not exist.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Initialize test suites to run */
+
+ /* initialize the CUnit test registry */
+ if (CUE_SUCCESS != CU_initialize_registry()) {
+ amdgpu_close_devices();
+ return CU_get_error();
+ }
+
+ /* Register suites. */
+ if (CU_register_suites(suites) != CUE_SUCCESS) {
+ fprintf(stderr, "suite registration failed - %s\n",
+ CU_get_error_msg());
+ CU_cleanup_registry();
+ amdgpu_close_devices();
+ exit(EXIT_FAILURE);
+ }
+
+ /* Run tests using the CUnit Basic interface */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+
+ /* Disable suites and individual tests based on misc. conditions */
+ amdgpu_disable_suites();
+
+ if (display_list) {
+ display_test_suites();
+ goto end;
+ }
+
+ if (suite_id != -1) { /* If user specify particular suite? */
+ pSuite = CU_get_suite_by_index((unsigned int) suite_id,
+ CU_get_registry());
+
+ if (pSuite) {
+
+ if (force_run)
+ CU_set_suite_active(pSuite, CU_TRUE);
+
+ if (test_id != -1) { /* If user specify test id */
+ pTest = CU_get_test_by_index(
+ (unsigned int) test_id,
+ pSuite);
+ if (pTest) {
+ if (force_run)
+ CU_set_test_active(pTest, CU_TRUE);
+
+ CU_basic_run_test(pSuite, pTest);
+ }
+ else {
+ fprintf(stderr, "Invalid test id: %d\n",
+ test_id);
+ CU_cleanup_registry();
+ amdgpu_close_devices();
+ exit(EXIT_FAILURE);
+ }
+ } else
+ CU_basic_run_suite(pSuite);
+ } else {
+ fprintf(stderr, "Invalid suite id : %d\n",
+ suite_id);
+ CU_cleanup_registry();
+ amdgpu_close_devices();
+ exit(EXIT_FAILURE);
+ }
+ } else
+ CU_basic_run_tests();
+
+end:
+ CU_cleanup_registry();
+ amdgpu_close_devices();
+ return CU_get_error();
+}
diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h
new file mode 100644
index 0000000..e2ba043
--- /dev/null
+++ b/tests/amdgpu/amdgpu_test.h
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _AMDGPU_TEST_H_
+#define _AMDGPU_TEST_H_
+
+#include "amdgpu.h"
+#include "amdgpu_drm.h"
+
+/**
+ * Define max. number of card in system which we are able to handle
+ */
+#define MAX_CARDS_SUPPORTED 128
+
+/* Forward reference for array to keep "drm" handles */
+extern int drm_amdgpu[MAX_CARDS_SUPPORTED];
+
+/* Global variables */
+extern int open_render_node;
+
+/************************* Basic test suite ********************************/
+
+/*
+ * Define basic test suite to serve as the starting point for future testing
+*/
+
+/**
+ * Initialize basic test suite
+ */
+int suite_basic_tests_init();
+
+/**
+ * Deinitialize basic test suite
+ */
+int suite_basic_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_basic_tests_enable(void);
+
+/**
+ * Tests in basic test suite
+ */
+extern CU_TestInfo basic_tests[];
+
+/**
+ * Initialize bo test suite
+ */
+int suite_bo_tests_init();
+
+/**
+ * Deinitialize bo test suite
+ */
+int suite_bo_tests_clean();
+
+/**
+ * Tests in bo test suite
+ */
+extern CU_TestInfo bo_tests[];
+
+/**
+ * Initialize cs test suite
+ */
+int suite_cs_tests_init();
+
+/**
+ * Deinitialize cs test suite
+ */
+int suite_cs_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_cs_tests_enable(void);
+
+/**
+ * Tests in cs test suite
+ */
+extern CU_TestInfo cs_tests[];
+
+/**
+ * Initialize vce test suite
+ */
+int suite_vce_tests_init();
+
+/**
+ * Deinitialize vce test suite
+ */
+int suite_vce_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vce_tests_enable(void);
+
+/**
+ * Tests in vce test suite
+ */
+extern CU_TestInfo vce_tests[];
+
+/**
++ * Initialize vcn test suite
++ */
+int suite_vcn_tests_init();
+
+/**
++ * Deinitialize vcn test suite
++ */
+int suite_vcn_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vcn_tests_enable(void);
+
+/**
++ * Tests in vcn test suite
++ */
+extern CU_TestInfo vcn_tests[];
+
+/**
++ * Initialize jpeg test suite
++ */
+int suite_jpeg_tests_init();
+
+/**
++ * Deinitialize jpeg test suite
++ */
+int suite_jpeg_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_jpeg_tests_enable(void);
+
+/**
++ * Tests in vcn test suite
++ */
+extern CU_TestInfo jpeg_tests[];
+
+/**
+ * Initialize uvd enc test suite
+ */
+int suite_uvd_enc_tests_init();
+
+/**
+ * Deinitialize uvd enc test suite
+ */
+int suite_uvd_enc_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_uvd_enc_tests_enable(void);
+
+/**
+ * Tests in uvd enc test suite
+ */
+extern CU_TestInfo uvd_enc_tests[];
+
+/**
+ * Initialize deadlock test suite
+ */
+int suite_deadlock_tests_init();
+
+/**
+ * Deinitialize deadlock test suite
+ */
+int suite_deadlock_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_deadlock_tests_enable(void);
+
+/**
+ * Tests in uvd enc test suite
+ */
+extern CU_TestInfo deadlock_tests[];
+
+/**
+ * Initialize vm test suite
+ */
+int suite_vm_tests_init();
+
+/**
+ * Deinitialize deadlock test suite
+ */
+int suite_vm_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vm_tests_enable(void);
+
+/**
+ * Tests in vm test suite
+ */
+extern CU_TestInfo vm_tests[];
+
+
+/**
+ * Initialize ras test suite
+ */
+int suite_ras_tests_init();
+
+/**
+ * Deinitialize deadlock test suite
+ */
+int suite_ras_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_ras_tests_enable(void);
+
+/**
+ * Tests in ras test suite
+ */
+extern CU_TestInfo ras_tests[];
+
+
+/**
+ * Initialize syncobj timeline test suite
+ */
+int suite_syncobj_timeline_tests_init();
+
+/**
+ * Deinitialize syncobj timeline test suite
+ */
+int suite_syncobj_timeline_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_syncobj_timeline_tests_enable(void);
+
+/**
+ * Tests in syncobj timeline test suite
+ */
+extern CU_TestInfo syncobj_timeline_tests[];
+
+
+/**
+ * Initialize cp dma test suite
+ */
+int suite_cp_dma_tests_init();
+
+/**
+ * Deinitialize cp dma test suite
+ */
+int suite_cp_dma_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_cp_dma_tests_enable(void);
+
+/**
+ * Tests in cp dma test suite
+ */
+extern CU_TestInfo cp_dma_tests[];
+
+/**
+ * Initialize security test suite
+ */
+int suite_security_tests_init();
+
+/**
+ * Deinitialize security test suite
+ */
+int suite_security_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_security_tests_enable(void);
+
+/**
+ * Tests in security test suite
+ */
+extern CU_TestInfo security_tests[];
+
+extern void
+amdgpu_command_submission_write_linear_helper_with_secure(amdgpu_device_handle
+ device,
+ unsigned ip_type,
+ bool secure);
+
+extern void amdgpu_test_dispatch_helper(amdgpu_device_handle device_handle, unsigned ip);
+extern void amdgpu_test_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip);
+extern void amdgpu_test_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip);
+extern void amdgpu_test_draw_helper(amdgpu_device_handle device_handle);
+extern void amdgpu_test_draw_hang_helper(amdgpu_device_handle device_handle);
+extern void amdgpu_test_draw_hang_slow_helper(amdgpu_device_handle device_handle);
+
+/**
+ * Initialize hotunplug test suite
+ */
+int suite_hotunplug_tests_init();
+
+/**
+ * Deinitialize hotunplug test suite
+ */
+int suite_hotunplug_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_hotunplug_tests_enable(void);
+
+/**
+ * Tests in uvd enc test suite
+ */
+extern CU_TestInfo hotunplug_tests[];
+
+
+/**
+ * Helper functions
+ */
+static inline amdgpu_bo_handle gpu_mem_alloc(
+ amdgpu_device_handle device_handle,
+ uint64_t size,
+ uint64_t alignment,
+ uint32_t type,
+ uint64_t flags,
+ uint64_t *vmc_addr,
+ amdgpu_va_handle *va_handle)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle = NULL;
+ int r;
+
+ req.alloc_size = size;
+ req.phys_alignment = alignment;
+ req.preferred_heap = type;
+ req.flags = flags;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ return NULL;
+
+ if (vmc_addr && va_handle) {
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ size, alignment, 0, vmc_addr,
+ va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ goto error_free_bo;
+
+ r = amdgpu_bo_va_op(buf_handle, 0, size, *vmc_addr, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ goto error_free_va;
+ }
+
+ return buf_handle;
+
+error_free_va:
+ r = amdgpu_va_range_free(*va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+error_free_bo:
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ return NULL;
+}
+
+static inline int gpu_mem_free(amdgpu_bo_handle bo,
+ amdgpu_va_handle va_handle,
+ uint64_t vmc_addr,
+ uint64_t size)
+{
+ int r;
+
+ if (!bo)
+ return 0;
+
+ if (va_handle) {
+ r = amdgpu_bo_va_op(bo, 0, size, vmc_addr, 0,
+ AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ return r;
+
+ r = amdgpu_va_range_free(va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ return r;
+ }
+
+ r = amdgpu_bo_free(bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ return r;
+}
+
+static inline int
+amdgpu_bo_alloc_wrap(amdgpu_device_handle dev, unsigned size,
+ unsigned alignment, unsigned heap, uint64_t flags,
+ amdgpu_bo_handle *bo)
+{
+ struct amdgpu_bo_alloc_request request = {};
+ amdgpu_bo_handle buf_handle;
+ int r;
+
+ request.alloc_size = size;
+ request.phys_alignment = alignment;
+ request.preferred_heap = heap;
+ request.flags = flags;
+
+ r = amdgpu_bo_alloc(dev, &request, &buf_handle);
+ if (r)
+ return r;
+
+ *bo = buf_handle;
+
+ return 0;
+}
+
+int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size,
+ unsigned alignment, unsigned heap, uint64_t alloc_flags,
+ uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu,
+ uint64_t *mc_address,
+ amdgpu_va_handle *va_handle);
+
+static inline int
+amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size,
+ unsigned alignment, unsigned heap, uint64_t alloc_flags,
+ amdgpu_bo_handle *bo, void **cpu, uint64_t *mc_address,
+ amdgpu_va_handle *va_handle)
+{
+ return amdgpu_bo_alloc_and_map_raw(dev, size, alignment, heap,
+ alloc_flags, 0, bo, cpu, mc_address, va_handle);
+}
+
+static inline int
+amdgpu_bo_unmap_and_free(amdgpu_bo_handle bo, amdgpu_va_handle va_handle,
+ uint64_t mc_addr, uint64_t size)
+{
+ amdgpu_bo_cpu_unmap(bo);
+ amdgpu_bo_va_op(bo, 0, size, mc_addr, 0, AMDGPU_VA_OP_UNMAP);
+ amdgpu_va_range_free(va_handle);
+ amdgpu_bo_free(bo);
+
+ return 0;
+
+}
+
+static inline int
+amdgpu_get_bo_list(amdgpu_device_handle dev, amdgpu_bo_handle bo1,
+ amdgpu_bo_handle bo2, amdgpu_bo_list_handle *list)
+{
+ amdgpu_bo_handle resources[] = {bo1, bo2};
+
+ return amdgpu_bo_list_create(dev, bo2 ? 2 : 1, resources, NULL, list);
+}
+
+
+static inline CU_ErrorCode amdgpu_set_suite_active(const char *suite_name,
+ CU_BOOL active)
+{
+ CU_ErrorCode r = CU_set_suite_active(CU_get_suite(suite_name), active);
+
+ if (r != CUE_SUCCESS)
+ fprintf(stderr, "Failed to obtain suite %s\n", suite_name);
+
+ return r;
+}
+
+static inline CU_ErrorCode amdgpu_set_test_active(const char *suite_name,
+ const char *test_name, CU_BOOL active)
+{
+ CU_ErrorCode r;
+ CU_pSuite pSuite = CU_get_suite(suite_name);
+
+ if (!pSuite) {
+ fprintf(stderr, "Failed to obtain suite %s\n",
+ suite_name);
+ return CUE_NOSUITE;
+ }
+
+ r = CU_set_test_active(CU_get_test(pSuite, test_name), active);
+ if (r != CUE_SUCCESS)
+ fprintf(stderr, "Failed to obtain test %s\n", test_name);
+
+ return r;
+}
+
+
+static inline bool asic_is_gfx_pipe_removed(uint32_t family_id, uint32_t chip_id, uint32_t chip_rev)
+{
+
+ if (family_id != AMDGPU_FAMILY_AI)
+ return false;
+
+ switch (chip_id - chip_rev) {
+ /* Arcturus */
+ case 0x32:
+ /* Aldebaran */
+ case 0x3c:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void amdgpu_test_exec_cs_helper_raw(amdgpu_device_handle device_handle,
+ amdgpu_context_handle context_handle,
+ unsigned ip_type, int instance, int pm4_dw,
+ uint32_t *pm4_src, int res_cnt,
+ amdgpu_bo_handle *resources,
+ struct amdgpu_cs_ib_info *ib_info,
+ struct amdgpu_cs_request *ibs_request,
+ bool secure);
+
+void amdgpu_close_devices();
+int amdgpu_open_device_on_test_index(int render_node);
+char *amdgpu_get_device_from_fd(int fd);
+
+#endif /* #ifdef _AMDGPU_TEST_H_ */
diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c
new file mode 100644
index 0000000..42176c0
--- /dev/null
+++ b/tests/amdgpu/basic_tests.c
@@ -0,0 +1,2556 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef MAJOR_IN_SYSMACROS
+#include <sys/sysmacros.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+#include <sys/wait.h>
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "util_math.h"
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t chip_id;
+static uint32_t chip_rev;
+
+static void amdgpu_query_info_test(void);
+static void amdgpu_command_submission_gfx(void);
+static void amdgpu_command_submission_compute(void);
+static void amdgpu_command_submission_multi_fence(void);
+static void amdgpu_command_submission_sdma(void);
+static void amdgpu_userptr_test(void);
+static void amdgpu_semaphore_test(void);
+static void amdgpu_sync_dependency_test(void);
+static void amdgpu_bo_eviction_test(void);
+static void amdgpu_compute_dispatch_test(void);
+static void amdgpu_gfx_dispatch_test(void);
+static void amdgpu_draw_test(void);
+static void amdgpu_gpu_reset_test(void);
+static void amdgpu_stable_pstate_test(void);
+
+static void amdgpu_command_submission_write_linear_helper(unsigned ip_type);
+static void amdgpu_command_submission_const_fill_helper(unsigned ip_type);
+static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type);
+static void amdgpu_test_exec_cs_helper(amdgpu_context_handle context_handle,
+ unsigned ip_type,
+ int instance, int pm4_dw, uint32_t *pm4_src,
+ int res_cnt, amdgpu_bo_handle *resources,
+ struct amdgpu_cs_ib_info *ib_info,
+ struct amdgpu_cs_request *ibs_request);
+
+CU_TestInfo basic_tests[] = {
+ { "Query Info Test", amdgpu_query_info_test },
+ { "Userptr Test", amdgpu_userptr_test },
+ { "bo eviction Test", amdgpu_bo_eviction_test },
+ { "Command submission Test (GFX)", amdgpu_command_submission_gfx },
+ { "Command submission Test (Compute)", amdgpu_command_submission_compute },
+ { "Command submission Test (Multi-Fence)", amdgpu_command_submission_multi_fence },
+ { "Command submission Test (SDMA)", amdgpu_command_submission_sdma },
+ { "SW semaphore Test", amdgpu_semaphore_test },
+ { "Sync dependency Test", amdgpu_sync_dependency_test },
+ { "Dispatch Test (Compute)", amdgpu_compute_dispatch_test },
+ { "Dispatch Test (GFX)", amdgpu_gfx_dispatch_test },
+ { "Draw Test", amdgpu_draw_test },
+ { "GPU reset Test", amdgpu_gpu_reset_test },
+ { "Stable pstate Test", amdgpu_stable_pstate_test },
+ CU_TEST_INFO_NULL,
+};
+#define BUFFER_SIZE (MAX2(8 * 1024, getpagesize()))
+#define SDMA_PKT_HEADER_op_offset 0
+#define SDMA_PKT_HEADER_op_mask 0x000000FF
+#define SDMA_PKT_HEADER_op_shift 0
+#define SDMA_PKT_HEADER_OP(x) (((x) & SDMA_PKT_HEADER_op_mask) << SDMA_PKT_HEADER_op_shift)
+#define SDMA_OPCODE_CONSTANT_FILL 11
+# define SDMA_CONSTANT_FILL_EXTRA_SIZE(x) ((x) << 14)
+ /* 0 = byte fill
+ * 2 = DW fill
+ */
+#define SDMA_PACKET(op, sub_op, e) ((((e) & 0xFFFF) << 16) | \
+ (((sub_op) & 0xFF) << 8) | \
+ (((op) & 0xFF) << 0))
+#define SDMA_OPCODE_WRITE 2
+# define SDMA_WRITE_SUB_OPCODE_LINEAR 0
+# define SDMA_WRTIE_SUB_OPCODE_TILED 1
+
+#define SDMA_OPCODE_COPY 1
+# define SDMA_COPY_SUB_OPCODE_LINEAR 0
+
+#define SDMA_OPCODE_ATOMIC 10
+# define SDMA_ATOMIC_LOOP(x) ((x) << 0)
+ /* 0 - single_pass_atomic.
+ * 1 - loop_until_compare_satisfied.
+ */
+# define SDMA_ATOMIC_TMZ(x) ((x) << 2)
+ /* 0 - non-TMZ.
+ * 1 - TMZ.
+ */
+# define SDMA_ATOMIC_OPCODE(x) ((x) << 9)
+ /* TC_OP_ATOMIC_CMPSWAP_RTN_32 0x00000008
+ * same as Packet 3
+ */
+
+#define GFX_COMPUTE_NOP 0xffff1000
+#define SDMA_NOP 0x0
+
+/* PM4 */
+#define PACKET_TYPE0 0
+#define PACKET_TYPE1 1
+#define PACKET_TYPE2 2
+#define PACKET_TYPE3 3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) ((h) & 0xFFFF)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \
+ ((reg) & 0xFFFF) | \
+ ((n) & 0x3FFF) << 16)
+#define CP_PACKET2 0x80000000
+#define PACKET2_PAD_SHIFT 0
+#define PACKET2_PAD_MASK (0x3fffffff << 0)
+
+#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
+ (((op) & 0xFF) << 8) | \
+ ((n) & 0x3FFF) << 16)
+#define PACKET3_COMPUTE(op, n) PACKET3(op, n) | (1 << 1)
+
+/* Packet 3 types */
+#define PACKET3_NOP 0x10
+
+#define PACKET3_WRITE_DATA 0x37
+#define WRITE_DATA_DST_SEL(x) ((x) << 8)
+ /* 0 - register
+ * 1 - memory (sync - via GRBM)
+ * 2 - gl2
+ * 3 - gds
+ * 4 - reserved
+ * 5 - memory (async - direct)
+ */
+#define WR_ONE_ADDR (1 << 16)
+#define WR_CONFIRM (1 << 20)
+#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25)
+ /* 0 - LRU
+ * 1 - Stream
+ */
+#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
+ /* 0 - me
+ * 1 - pfp
+ * 2 - ce
+ */
+
+#define PACKET3_ATOMIC_MEM 0x1E
+#define TC_OP_ATOMIC_CMPSWAP_RTN_32 0x00000008
+#define ATOMIC_MEM_COMMAND(x) ((x) << 8)
+ /* 0 - single_pass_atomic.
+ * 1 - loop_until_compare_satisfied.
+ */
+#define ATOMIC_MEM_CACHEPOLICAY(x) ((x) << 25)
+ /* 0 - lru.
+ * 1 - stream.
+ */
+#define ATOMIC_MEM_ENGINESEL(x) ((x) << 30)
+ /* 0 - micro_engine.
+ */
+
+#define PACKET3_DMA_DATA 0x50
+/* 1. header
+ * 2. CONTROL
+ * 3. SRC_ADDR_LO or DATA [31:0]
+ * 4. SRC_ADDR_HI [31:0]
+ * 5. DST_ADDR_LO [31:0]
+ * 6. DST_ADDR_HI [7:0]
+ * 7. COMMAND [30:21] | BYTE_COUNT [20:0]
+ */
+/* CONTROL */
+# define PACKET3_DMA_DATA_ENGINE(x) ((x) << 0)
+ /* 0 - ME
+ * 1 - PFP
+ */
+# define PACKET3_DMA_DATA_SRC_CACHE_POLICY(x) ((x) << 13)
+ /* 0 - LRU
+ * 1 - Stream
+ * 2 - Bypass
+ */
+# define PACKET3_DMA_DATA_SRC_VOLATILE (1 << 15)
+# define PACKET3_DMA_DATA_DST_SEL(x) ((x) << 20)
+ /* 0 - DST_ADDR using DAS
+ * 1 - GDS
+ * 3 - DST_ADDR using L2
+ */
+# define PACKET3_DMA_DATA_DST_CACHE_POLICY(x) ((x) << 25)
+ /* 0 - LRU
+ * 1 - Stream
+ * 2 - Bypass
+ */
+# define PACKET3_DMA_DATA_DST_VOLATILE (1 << 27)
+# define PACKET3_DMA_DATA_SRC_SEL(x) ((x) << 29)
+ /* 0 - SRC_ADDR using SAS
+ * 1 - GDS
+ * 2 - DATA
+ * 3 - SRC_ADDR using L2
+ */
+# define PACKET3_DMA_DATA_CP_SYNC (1 << 31)
+/* COMMAND */
+# define PACKET3_DMA_DATA_DIS_WC (1 << 21)
+# define PACKET3_DMA_DATA_CMD_SRC_SWAP(x) ((x) << 22)
+ /* 0 - none
+ * 1 - 8 in 16
+ * 2 - 8 in 32
+ * 3 - 8 in 64
+ */
+# define PACKET3_DMA_DATA_CMD_DST_SWAP(x) ((x) << 24)
+ /* 0 - none
+ * 1 - 8 in 16
+ * 2 - 8 in 32
+ * 3 - 8 in 64
+ */
+# define PACKET3_DMA_DATA_CMD_SAS (1 << 26)
+ /* 0 - memory
+ * 1 - register
+ */
+# define PACKET3_DMA_DATA_CMD_DAS (1 << 27)
+ /* 0 - memory
+ * 1 - register
+ */
+# define PACKET3_DMA_DATA_CMD_SAIC (1 << 28)
+# define PACKET3_DMA_DATA_CMD_DAIC (1 << 29)
+# define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30)
+
+#define SDMA_PACKET_SI(op, b, t, s, cnt) ((((op) & 0xF) << 28) | \
+ (((b) & 0x1) << 26) | \
+ (((t) & 0x1) << 23) | \
+ (((s) & 0x1) << 22) | \
+ (((cnt) & 0xFFFFF) << 0))
+#define SDMA_OPCODE_COPY_SI 3
+#define SDMA_OPCODE_CONSTANT_FILL_SI 13
+#define SDMA_NOP_SI 0xf
+#define GFX_COMPUTE_NOP_SI 0x80000000
+#define PACKET3_DMA_DATA_SI 0x41
+# define PACKET3_DMA_DATA_SI_ENGINE(x) ((x) << 27)
+ /* 0 - ME
+ * 1 - PFP
+ */
+# define PACKET3_DMA_DATA_SI_DST_SEL(x) ((x) << 20)
+ /* 0 - DST_ADDR using DAS
+ * 1 - GDS
+ * 3 - DST_ADDR using L2
+ */
+# define PACKET3_DMA_DATA_SI_SRC_SEL(x) ((x) << 29)
+ /* 0 - SRC_ADDR using SAS
+ * 1 - GDS
+ * 2 - DATA
+ * 3 - SRC_ADDR using L2
+ */
+# define PACKET3_DMA_DATA_SI_CP_SYNC (1 << 31)
+
+
+#define PKT3_CONTEXT_CONTROL 0x28
+#define CONTEXT_CONTROL_LOAD_ENABLE(x) (((unsigned)(x) & 0x1) << 31)
+#define CONTEXT_CONTROL_LOAD_CE_RAM(x) (((unsigned)(x) & 0x1) << 28)
+#define CONTEXT_CONTROL_SHADOW_ENABLE(x) (((unsigned)(x) & 0x1) << 31)
+
+#define PKT3_CLEAR_STATE 0x12
+
+#define PKT3_SET_SH_REG 0x76
+#define PACKET3_SET_SH_REG_START 0x00002c00
+
+#define PKT3_SET_SH_REG_INDEX 0x9B
+
+#define PACKET3_DISPATCH_DIRECT 0x15
+#define PACKET3_EVENT_WRITE 0x46
+#define PACKET3_ACQUIRE_MEM 0x58
+#define PACKET3_SET_CONTEXT_REG 0x69
+#define PACKET3_SET_UCONFIG_REG 0x79
+#define PACKET3_DRAW_INDEX_AUTO 0x2D
+/* gfx 8 */
+#define mmCOMPUTE_PGM_LO 0x2e0c
+#define mmCOMPUTE_PGM_RSRC1 0x2e12
+#define mmCOMPUTE_TMPRING_SIZE 0x2e18
+#define mmCOMPUTE_USER_DATA_0 0x2e40
+#define mmCOMPUTE_USER_DATA_1 0x2e41
+#define mmCOMPUTE_RESOURCE_LIMITS 0x2e15
+#define mmCOMPUTE_NUM_THREAD_X 0x2e07
+
+
+
+#define SWAP_32(num) (((num & 0xff000000) >> 24) | \
+ ((num & 0x0000ff00) << 8) | \
+ ((num & 0x00ff0000) >> 8) | \
+ ((num & 0x000000ff) << 24))
+
+
+/* Shader code
+ * void main()
+{
+
+ float x = some_input;
+ for (unsigned i = 0; i < 1000000; i++)
+ x = sin(x);
+
+ u[0] = 42u;
+}
+*/
+
+static uint32_t shader_bin[] = {
+ SWAP_32(0x800082be), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0x040085bf),
+ SWAP_32(0x02810281), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0xfcff84bf),
+ SWAP_32(0xff0083be), SWAP_32(0x00f00000), SWAP_32(0xc10082be), SWAP_32(0xaa02007e),
+ SWAP_32(0x000070e0), SWAP_32(0x00000080), SWAP_32(0x000081bf)
+};
+
+#define CODE_OFFSET 512
+#define DATA_OFFSET 1024
+
+enum cs_type {
+ CS_BUFFERCLEAR,
+ CS_BUFFERCOPY,
+ CS_HANG,
+ CS_HANG_SLOW
+};
+
+static const uint32_t bufferclear_cs_shader_gfx9[] = {
+ 0x260000ff, 0x000003ff, 0xd1fd0000, 0x04010c08,
+ 0x7e020280, 0x7e040204, 0x7e060205, 0x7e080206,
+ 0x7e0a0207, 0xe01c2000, 0x80000200, 0xbf8c0000,
+ 0xbf810000
+};
+
+static const uint32_t bufferclear_cs_shader_gfx10[] = {
+ 0xD7460004, 0x04010C08, 0x7E000204, 0x7E020205,
+ 0x7E040206, 0x7E060207, 0xE01C2000, 0x80000004,
+ 0xBF810000
+};
+
+static const uint32_t bufferclear_cs_shader_registers_gfx9[][2] = {
+ {0x2e12, 0x000C0041}, //{ mmCOMPUTE_PGM_RSRC1, 0x000C0041 },
+ {0x2e13, 0x00000090}, //{ mmCOMPUTE_PGM_RSRC2, 0x00000090 },
+ {0x2e07, 0x00000040}, //{ mmCOMPUTE_NUM_THREAD_X, 0x00000040 },
+ {0x2e08, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Y, 0x00000001 },
+ {0x2e09, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Z, 0x00000001 }
+};
+
+static const uint32_t bufferclear_cs_shader_registers_num_gfx9 = 5;
+
+static const uint32_t buffercopy_cs_shader_gfx9[] = {
+ 0x260000ff, 0x000003ff, 0xd1fd0000, 0x04010c08,
+ 0x7e020280, 0xe00c2000, 0x80000200, 0xbf8c0f70,
+ 0xe01c2000, 0x80010200, 0xbf810000
+};
+
+static const uint32_t buffercopy_cs_shader_gfx10[] = {
+ 0xD7460001, 0x04010C08, 0xE00C2000, 0x80000201,
+ 0xBF8C3F70, 0xE01C2000, 0x80010201, 0xBF810000
+};
+
+static const uint32_t preamblecache_gfx9[] = {
+ 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0,
+ 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000,
+ 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0,
+ 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0,
+ 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0,
+ 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0,
+ 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0,
+ 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xc0036900, 0x311, 0x3, 0, 0x100000, 0xc0026900, 0x316, 0x1e, 0x20,
+ 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0,
+ 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x19, 0x0,
+ 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0,
+ 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff,
+ 0xc0016900, 0x314, 0x0, 0xc0016900, 0x2a6, 0, 0xc0016900, 0x210, 0,
+ 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1,
+ 0xc0016900, 0x18, 0x2, 0xc0016900, 0x206, 0x300, 0xc0017900, 0x20000243, 0x0,
+ 0xc0017900, 0x248, 0xffffffff, 0xc0017900, 0x249, 0x0, 0xc0017900, 0x24a, 0x0,
+ 0xc0017900, 0x24b, 0x0
+};
+
+static const uint32_t preamblecache_gfx10[] = {
+ 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0,
+ 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000,
+ 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0,
+ 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0,
+ 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0,
+ 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0,
+ 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0,
+ 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xc0046900, 0x310, 0, 0x3, 0, 0x100000, 0xc0026900, 0x316, 0xe, 0x20,
+ 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0,
+ 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x6, 0x0,
+ 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0,
+ 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff,
+ 0xc0016900, 0x314, 0x0, 0xc0016900, 0x10a, 0, 0xc0016900, 0x2a6, 0, 0xc0016900, 0x210, 0,
+ 0xc0016900, 0x2db, 0, 0xc0016900, 0x1d4, 0, 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1, 0xc0016900, 0xe, 0x2,
+ 0xc0016900, 0x206, 0x300, 0xc0016900, 0x212, 0x200, 0xc0017900, 0x7b, 0x20, 0xc0017a00, 0x20000243, 0x0,
+ 0xc0017900, 0x249, 0, 0xc0017900, 0x24a, 0, 0xc0017900, 0x24b, 0, 0xc0017900, 0x259, 0xffffffff,
+ 0xc0017900, 0x25f, 0, 0xc0017900, 0x260, 0, 0xc0017900, 0x262, 0,
+ 0xc0017600, 0x45, 0x0, 0xc0017600, 0x6, 0x0,
+ 0xc0067600, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0067600, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+enum ps_type {
+ PS_CONST,
+ PS_TEX,
+ PS_HANG,
+ PS_HANG_SLOW
+};
+
+static const uint32_t ps_const_shader_gfx9[] = {
+ 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203,
+ 0xD2960000, 0x00020300, 0xD2960001, 0x00020702,
+ 0xC4001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_const_shader_patchinfo_code_size_gfx9 = 6;
+
+static const uint32_t ps_const_shader_patchinfo_code_gfx9[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000300 },
+ { 0xD2960000, 0x00020300, 0xD2960001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2950000, 0x00020300, 0xD2950001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2940000, 0x00020300, 0xD2940001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2970000, 0x00020300, 0xD2970001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2980000, 0x00020300, 0xD2980001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x03020100 }
+ }
+};
+
+static const uint32_t ps_const_shader_patchinfo_offset_gfx9[] = {
+ 0x00000004
+};
+
+static const uint32_t ps_num_sh_registers_gfx9 = 2;
+
+static const uint32_t ps_const_sh_registers_gfx9[][2] = {
+ {0x2C0A, 0x000C0040},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0040 },
+ {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 }
+};
+
+static const uint32_t ps_num_context_registers_gfx9 = 7;
+
+static const uint32_t ps_const_context_reg_gfx9[][2] = {
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000000}, //{ mmSPI_PS_IN_CONTROL, 0x00000000 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 }
+};
+
+static const uint32_t ps_const_shader_gfx10[] = {
+ 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203,
+ 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000,
+ 0xF8001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_const_shader_patchinfo_code_size_gfx10 = 6;
+
+static const uint32_t ps_const_shader_patchinfo_code_gfx10[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000300 },
+ { 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 },
+ { 0xD7690000, 0x00020300, 0xD7690001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD7680000, 0x00020300, 0xD7680001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD76A0000, 0x00020300, 0xD76A0001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD76B0000, 0x00020300, 0xD76B0001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x03020100 }
+ }
+};
+
+static const uint32_t ps_const_shader_patchinfo_offset_gfx10[] = {
+ 0x00000004
+};
+
+static const uint32_t ps_num_sh_registers_gfx10 = 2;
+
+static const uint32_t ps_const_sh_registers_gfx10[][2] = {
+ {0x2C0A, 0x000C0000},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0000 },
+ {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 }
+};
+
+static const uint32_t ps_tex_shader_gfx9[] = {
+ 0xBEFC000C, 0xBE8E017E, 0xBEFE077E, 0xD4180000,
+ 0xD4190001, 0xD41C0100, 0xD41D0101, 0xF0800F00,
+ 0x00400206, 0xBEFE010E, 0xBF8C0F70, 0xD2960000,
+ 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F,
+ 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_tex_shader_patchinfo_offset_gfx9[] = {
+ 0x0000000B
+};
+
+static const uint32_t ps_tex_shader_patchinfo_code_size_gfx9 = 6;
+
+static const uint32_t ps_tex_shader_patchinfo_code_gfx9[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000002 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000302 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000502 },
+ { 0xD2960000, 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2950000, 0x00020702, 0xD2950001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2940000, 0x00020702, 0xD2940001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2970000, 0x00020702, 0xD2970001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2980000, 0x00020702, 0xD2980001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x05040302 }
+ }
+};
+
+static const uint32_t ps_tex_sh_registers_gfx9[][2] = {
+ {0x2C0A, 0x000C0081},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0081 },
+ {0x2C0B, 0x00000018}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000018 }
+};
+
+static const uint32_t ps_tex_context_reg_gfx9[][2] = {
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000001}, //{ mmSPI_PS_IN_CONTROL, 0x00000001 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 }
+};
+
+static const uint32_t ps_tex_shader_gfx10[] = {
+ 0xBEFC030C, 0xBE8E047E, 0xBEFE0A7E, 0xC8080000,
+ 0xC80C0100, 0xC8090001, 0xC80D0101, 0xF0800F0A,
+ 0x00400402, 0x00000003, 0xBEFE040E, 0xBF8C0F70,
+ 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000,
+ 0xF8001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_tex_shader_patchinfo_offset_gfx10[] = {
+ 0x0000000C
+};
+
+static const uint32_t ps_tex_shader_patchinfo_code_size_gfx10 = 6;
+
+static const uint32_t ps_tex_shader_patchinfo_code_gfx10[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000004 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000504 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000704 },
+ { 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 },
+ { 0xD7690000, 0x00020B04, 0xD7690001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD7680000, 0x00020B04, 0xD7680001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD76A0000, 0x00020B04, 0xD76A0001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD76B0000, 0x00020B04, 0xD76B0001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x07060504 }
+ }
+};
+
+static const uint32_t vs_RectPosTexFast_shader_gfx9[] = {
+ 0x7E000B00, 0x020000F3, 0xD042000A, 0x00010100,
+ 0x7E020202, 0x7E040200, 0x020000F3, 0x7E060206,
+ 0x7E080204, 0xD1000001, 0x002A0302, 0x7C840080,
+ 0x7E000200, 0x7E040203, 0x7E0A0201, 0xD1000003,
+ 0x002A0704, 0x7E0C0207, 0x7E0E0205, 0x00000101,
+ 0x00020505, 0x7E040208, 0x7E0A02F2, 0x00060903,
+ 0x00080D07, 0x7E0C0209, 0xC40008CF, 0x05020100,
+ 0xC400020F, 0x05060403, 0xBF810000
+};
+
+static const uint32_t vs_RectPosTexFast_shader_gfx10[] = {
+ 0x7E000B00, 0x060000F3, 0x7E020202, 0x7E040206,
+ 0x7C040080, 0x060000F3, 0xD5010001, 0x01AA0200,
+ 0x7E060203, 0xD5010002, 0x01AA0404, 0x7E080207,
+ 0x7C040080, 0xD5010000, 0x01A80101, 0xD5010001,
+ 0x01AA0601, 0x7E060208, 0x7E0A02F2, 0xD5010002,
+ 0x01A80902, 0xD5010004, 0x01AA0805, 0x7E0C0209,
+ 0xF80008CF, 0x05030100, 0xF800020F, 0x05060402,
+ 0xBF810000
+};
+
+static const uint32_t cached_cmd_gfx9[] = {
+ 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0,
+ 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020,
+ 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf,
+ 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x12,
+ 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0,
+ 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011,
+ 0xc0026900, 0x292, 0x20, 0x60201b8,
+ 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0
+};
+
+static const uint32_t cached_cmd_gfx10[] = {
+ 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0,
+ 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020,
+ 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf,
+ 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x18,
+ 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0,
+ 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011,
+ 0xc0026900, 0x292, 0x20, 0x6020000,
+ 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0
+};
+
+unsigned int memcpy_ps_hang[] = {
+ 0xFFFFFFFF, 0xBEFE0A7E, 0xBEFC0304, 0xC0C20100,
+ 0xC0800300, 0xC8080000, 0xC80C0100, 0xC8090001,
+ 0xC80D0101, 0xBF8C007F, 0xF0800F00, 0x00010002,
+ 0xBEFE040C, 0xBF8C0F70, 0xBF800000, 0xBF800000,
+ 0xF800180F, 0x03020100, 0xBF810000
+};
+
+struct amdgpu_test_shader {
+ uint32_t *shader;
+ uint32_t header_length;
+ uint32_t body_length;
+ uint32_t foot_length;
+};
+
+unsigned int memcpy_cs_hang_slow_ai_codes[] = {
+ 0xd1fd0000, 0x04010c08, 0xe00c2000, 0x80000100,
+ 0xbf8c0f70, 0xe01c2000, 0x80010100, 0xbf810000
+};
+
+struct amdgpu_test_shader memcpy_cs_hang_slow_ai = {
+ memcpy_cs_hang_slow_ai_codes,
+ 4,
+ 3,
+ 1
+};
+
+unsigned int memcpy_cs_hang_slow_rv_codes[] = {
+ 0x8e00860c, 0x32000000, 0xe00c2000, 0x80010100,
+ 0xbf8c0f70, 0xe01c2000, 0x80020100, 0xbf810000
+};
+
+struct amdgpu_test_shader memcpy_cs_hang_slow_rv = {
+ memcpy_cs_hang_slow_rv_codes,
+ 4,
+ 3,
+ 1
+};
+
+unsigned int memcpy_cs_hang_slow_nv_codes[] = {
+ 0xd7460000, 0x04010c08, 0xe00c2000, 0x80000100,
+ 0xbf8c0f70, 0xe01ca000, 0x80010100, 0xbf810000
+};
+
+struct amdgpu_test_shader memcpy_cs_hang_slow_nv = {
+ memcpy_cs_hang_slow_nv_codes,
+ 4,
+ 3,
+ 1
+};
+
+unsigned int memcpy_ps_hang_slow_ai_codes[] = {
+ 0xbefc000c, 0xbe8e017e, 0xbefe077e, 0xd4080000,
+ 0xd4090001, 0xd40c0100, 0xd40d0101, 0xf0800f00,
+ 0x00400002, 0xbefe010e, 0xbf8c0f70, 0xbf800000,
+ 0xbf800000, 0xbf800000, 0xbf800000, 0xc400180f,
+ 0x03020100, 0xbf810000
+};
+
+struct amdgpu_test_shader memcpy_ps_hang_slow_ai = {
+ memcpy_ps_hang_slow_ai_codes,
+ 7,
+ 2,
+ 9
+};
+
+int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size,
+ unsigned alignment, unsigned heap, uint64_t alloc_flags,
+ uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu,
+ uint64_t *mc_address,
+ amdgpu_va_handle *va_handle)
+{
+ struct amdgpu_bo_alloc_request request = {};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle handle;
+ uint64_t vmc_addr;
+ int r;
+
+ request.alloc_size = size;
+ request.phys_alignment = alignment;
+ request.preferred_heap = heap;
+ request.flags = alloc_flags;
+
+ r = amdgpu_bo_alloc(dev, &request, &buf_handle);
+ if (r)
+ return r;
+
+ r = amdgpu_va_range_alloc(dev,
+ amdgpu_gpu_va_range_general,
+ size, alignment, 0, &vmc_addr,
+ &handle, 0);
+ if (r)
+ goto error_va_alloc;
+
+ r = amdgpu_bo_va_op_raw(dev, buf_handle, 0, ALIGN(size, getpagesize()), vmc_addr,
+ AMDGPU_VM_PAGE_READABLE |
+ AMDGPU_VM_PAGE_WRITEABLE |
+ AMDGPU_VM_PAGE_EXECUTABLE |
+ mapping_flags,
+ AMDGPU_VA_OP_MAP);
+ if (r)
+ goto error_va_map;
+
+ r = amdgpu_bo_cpu_map(buf_handle, cpu);
+ if (r)
+ goto error_cpu_map;
+
+ *bo = buf_handle;
+ *mc_address = vmc_addr;
+ *va_handle = handle;
+
+ return 0;
+
+ error_cpu_map:
+ amdgpu_bo_cpu_unmap(buf_handle);
+
+ error_va_map:
+ amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP);
+
+ error_va_alloc:
+ amdgpu_bo_free(buf_handle);
+ return r;
+}
+
+
+
+CU_BOOL suite_basic_tests_enable(void)
+{
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+
+ family_id = device_handle->info.family_id;
+ chip_id = device_handle->info.chip_external_rev;
+ chip_rev = device_handle->info.chip_rev;
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ /* disable gfx engine basic test cases for some asics have no CPG */
+ if (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) {
+ if (amdgpu_set_test_active("Basic Tests",
+ "Command submission Test (GFX)",
+ CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n",
+ CU_get_error_msg());
+
+ if (amdgpu_set_test_active("Basic Tests",
+ "Command submission Test (Multi-Fence)",
+ CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n",
+ CU_get_error_msg());
+
+ if (amdgpu_set_test_active("Basic Tests",
+ "Sync dependency Test",
+ CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n",
+ CU_get_error_msg());
+ }
+
+ return CU_TRUE;
+}
+
+int suite_basic_tests_init(void)
+{
+ struct amdgpu_gpu_info gpu_info = {0};
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+ return CUE_SINIT_FAILED;
+ }
+
+ r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ family_id = gpu_info.family_id;
+
+ return CUE_SUCCESS;
+}
+
+int suite_basic_tests_clean(void)
+{
+ int r = amdgpu_device_deinitialize(device_handle);
+
+ if (r == 0)
+ return CUE_SUCCESS;
+ else
+ return CUE_SCLEAN_FAILED;
+}
+
+static void amdgpu_query_info_test(void)
+{
+ struct amdgpu_gpu_info gpu_info = {0};
+ uint32_t version, feature;
+ int r;
+
+ r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_query_firmware_version(device_handle, AMDGPU_INFO_FW_VCE, 0,
+ 0, &version, &feature);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_gfx_separate_ibs(void)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle, ib_result_ce_handle;
+ void *ib_result_cpu, *ib_result_ce_cpu;
+ uint64_t ib_result_mc_address, ib_result_ce_mc_address;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info[2];
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t *ptr;
+ uint32_t expired;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle, va_handle_ce;
+ int r, i = 0;
+ struct drm_amdgpu_info_hw_ip info;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (info.hw_ip_version_major >= 11)
+ return;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_ce_handle, &ib_result_ce_cpu,
+ &ib_result_ce_mc_address, &va_handle_ce);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle,
+ ib_result_ce_handle, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(ib_info, 0, 2 * sizeof(struct amdgpu_cs_ib_info));
+
+ /* IT_SET_CE_DE_COUNTERS */
+ ptr = ib_result_ce_cpu;
+ if (family_id != AMDGPU_FAMILY_SI) {
+ ptr[i++] = 0xc0008900;
+ ptr[i++] = 0;
+ }
+ ptr[i++] = 0xc0008400;
+ ptr[i++] = 1;
+ ib_info[0].ib_mc_address = ib_result_ce_mc_address;
+ ib_info[0].size = i;
+ ib_info[0].flags = AMDGPU_IB_FLAG_CE;
+
+ /* IT_WAIT_ON_CE_COUNTER */
+ ptr = ib_result_cpu;
+ ptr[0] = 0xc0008600;
+ ptr[1] = 0x00000001;
+ ib_info[1].ib_mc_address = ib_result_mc_address;
+ ib_info[1].size = 2;
+
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.number_of_ibs = 2;
+ ibs_request.ibs = ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_GFX;
+ fence_status.ip_instance = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_ce_handle, va_handle_ce,
+ ib_result_ce_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+}
+
+static void amdgpu_command_submission_gfx_shared_ib(void)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info[2];
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t *ptr;
+ uint32_t expired;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ int r, i = 0;
+ struct drm_amdgpu_info_hw_ip info;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (info.hw_ip_version_major >= 11)
+ return;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(ib_info, 0, 2 * sizeof(struct amdgpu_cs_ib_info));
+
+ /* IT_SET_CE_DE_COUNTERS */
+ ptr = ib_result_cpu;
+ if (family_id != AMDGPU_FAMILY_SI) {
+ ptr[i++] = 0xc0008900;
+ ptr[i++] = 0;
+ }
+ ptr[i++] = 0xc0008400;
+ ptr[i++] = 1;
+ ib_info[0].ib_mc_address = ib_result_mc_address;
+ ib_info[0].size = i;
+ ib_info[0].flags = AMDGPU_IB_FLAG_CE;
+
+ ptr = (uint32_t *)ib_result_cpu + 4;
+ ptr[0] = 0xc0008600;
+ ptr[1] = 0x00000001;
+ ib_info[1].ib_mc_address = ib_result_mc_address + 16;
+ ib_info[1].size = 2;
+
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.number_of_ibs = 2;
+ ibs_request.ibs = ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_GFX;
+ fence_status.ip_instance = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_gfx_cp_write_data(void)
+{
+ amdgpu_command_submission_write_linear_helper(AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_command_submission_gfx_cp_const_fill(void)
+{
+ amdgpu_command_submission_const_fill_helper(AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_command_submission_gfx_cp_copy_data(void)
+{
+ amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_bo_eviction_test(void)
+{
+ const int sdma_write_length = 1024;
+ const int pm4_dw = 256;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle bo1, bo2, vram_max[2], gtt_max[2];
+ amdgpu_bo_handle *resources;
+ uint32_t *pm4;
+ struct amdgpu_cs_ib_info *ib_info;
+ struct amdgpu_cs_request *ibs_request;
+ uint64_t bo1_mc, bo2_mc;
+ volatile unsigned char *bo1_cpu, *bo2_cpu;
+ int i, j, r, loop1, loop2;
+ uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
+ amdgpu_va_handle bo1_va_handle, bo2_va_handle;
+ struct amdgpu_heap_info vram_info, gtt_info;
+
+ pm4 = calloc(pm4_dw, sizeof(*pm4));
+ CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+ ib_info = calloc(1, sizeof(*ib_info));
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+ ibs_request = calloc(1, sizeof(*ibs_request));
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* prepare resource */
+ resources = calloc(4, sizeof(amdgpu_bo_handle));
+ CU_ASSERT_NOT_EQUAL(resources, NULL);
+
+ r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_VRAM,
+ 0, &vram_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096,
+ AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[0]);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096,
+ AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[1]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_GTT,
+ 0, &gtt_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, &gtt_max[0]);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, &gtt_max[1]);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+
+ loop1 = loop2 = 0;
+ /* run 9 circle to test all mapping combination */
+ while(loop1 < 2) {
+ while(loop2 < 2) {
+ /* allocate UC bo1for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop1], &bo1,
+ (void**)&bo1_cpu, &bo1_mc,
+ &bo1_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* set bo1 */
+ memset((void*)bo1_cpu, 0xaa, sdma_write_length);
+
+ /* allocate UC bo2 for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop2], &bo2,
+ (void**)&bo2_cpu, &bo2_mc,
+ &bo2_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* clear bo2 */
+ memset((void*)bo2_cpu, 0, sdma_write_length);
+
+ resources[0] = bo1;
+ resources[1] = bo2;
+ resources[2] = vram_max[loop2];
+ resources[3] = gtt_max[loop2];
+
+ /* fulfill PM4: test DMA copy linear */
+ i = j = 0;
+ if (family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, 0, 0, 0,
+ sdma_write_length);
+ pm4[i++] = 0xffffffff & bo2_mc;
+ pm4[i++] = 0xffffffff & bo1_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ } else {
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0);
+ if (family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = sdma_write_length - 1;
+ else
+ pm4[i++] = sdma_write_length;
+ pm4[i++] = 0;
+ pm4[i++] = 0xffffffff & bo1_mc;
+ pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ pm4[i++] = 0xffffffff & bo2_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ }
+
+ amdgpu_test_exec_cs_helper(context_handle,
+ AMDGPU_HW_IP_DMA, 0,
+ i, pm4,
+ 4, resources,
+ ib_info, ibs_request);
+
+ /* verify if SDMA test result meets with expected */
+ i = 0;
+ while(i < sdma_write_length) {
+ CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa);
+ }
+ r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+ loop2++;
+ }
+ loop2 = 0;
+ loop1++;
+ }
+ amdgpu_bo_free(vram_max[0]);
+ amdgpu_bo_free(vram_max[1]);
+ amdgpu_bo_free(gtt_max[0]);
+ amdgpu_bo_free(gtt_max[1]);
+ /* clean resources */
+ free(resources);
+ free(ibs_request);
+ free(ib_info);
+ free(pm4);
+
+ /* end of test */
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+
+static void amdgpu_command_submission_gfx(void)
+{
+ /* write data using the CP */
+ amdgpu_command_submission_gfx_cp_write_data();
+ /* const fill using the CP */
+ amdgpu_command_submission_gfx_cp_const_fill();
+ /* copy data using the CP */
+ amdgpu_command_submission_gfx_cp_copy_data();
+ /* separate IB buffers for multi-IB submission */
+ amdgpu_command_submission_gfx_separate_ibs();
+ /* shared IB buffer for multi-IB submission */
+ amdgpu_command_submission_gfx_shared_ib();
+}
+
+static void amdgpu_semaphore_test(void)
+{
+ amdgpu_context_handle context_handle[2];
+ amdgpu_semaphore_handle sem;
+ amdgpu_bo_handle ib_result_handle[2];
+ void *ib_result_cpu[2];
+ uint64_t ib_result_mc_address[2];
+ struct amdgpu_cs_request ibs_request[2] = {0};
+ struct amdgpu_cs_ib_info ib_info[2] = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t *ptr;
+ uint32_t expired;
+ uint32_t sdma_nop, gfx_nop;
+ amdgpu_bo_list_handle bo_list[2];
+ amdgpu_va_handle va_handle[2];
+ int r, i;
+ struct amdgpu_gpu_info gpu_info = {0};
+ unsigned gc_ip_type;
+
+ r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ gc_ip_type = (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) ?
+ AMDGPU_HW_IP_COMPUTE : AMDGPU_HW_IP_GFX;
+
+ if (family_id == AMDGPU_FAMILY_SI) {
+ sdma_nop = SDMA_PACKET_SI(SDMA_NOP_SI, 0, 0, 0, 0);
+ gfx_nop = GFX_COMPUTE_NOP_SI;
+ } else {
+ sdma_nop = SDMA_PKT_HEADER_OP(SDMA_NOP);
+ gfx_nop = GFX_COMPUTE_NOP;
+ }
+
+ r = amdgpu_cs_create_semaphore(&sem);
+ CU_ASSERT_EQUAL(r, 0);
+ for (i = 0; i < 2; i++) {
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle[i]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle[i], &ib_result_cpu[i],
+ &ib_result_mc_address[i], &va_handle[i]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle[i],
+ NULL, &bo_list[i]);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ /* 1. same context different engine */
+ ptr = ib_result_cpu[0];
+ ptr[0] = sdma_nop;
+ ib_info[0].ib_mc_address = ib_result_mc_address[0];
+ ib_info[0].size = 1;
+
+ ibs_request[0].ip_type = AMDGPU_HW_IP_DMA;
+ ibs_request[0].number_of_ibs = 1;
+ ibs_request[0].ibs = &ib_info[0];
+ ibs_request[0].resources = bo_list[0];
+ ibs_request[0].fence_info.handle = NULL;
+ r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_signal_semaphore(context_handle[0], AMDGPU_HW_IP_DMA, 0, 0, sem);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_wait_semaphore(context_handle[0], gc_ip_type, 0, 0, sem);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr = ib_result_cpu[1];
+ ptr[0] = gfx_nop;
+ ib_info[1].ib_mc_address = ib_result_mc_address[1];
+ ib_info[1].size = 1;
+
+ ibs_request[1].ip_type = gc_ip_type;
+ ibs_request[1].number_of_ibs = 1;
+ ibs_request[1].ibs = &ib_info[1];
+ ibs_request[1].resources = bo_list[1];
+ ibs_request[1].fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[1], 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.context = context_handle[0];
+ fence_status.ip_type = gc_ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.fence = ibs_request[1].seq_no;
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ 500000000, 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ /* 2. same engine different context */
+ ptr = ib_result_cpu[0];
+ ptr[0] = gfx_nop;
+ ib_info[0].ib_mc_address = ib_result_mc_address[0];
+ ib_info[0].size = 1;
+
+ ibs_request[0].ip_type = gc_ip_type;
+ ibs_request[0].number_of_ibs = 1;
+ ibs_request[0].ibs = &ib_info[0];
+ ibs_request[0].resources = bo_list[0];
+ ibs_request[0].fence_info.handle = NULL;
+ r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_signal_semaphore(context_handle[0], gc_ip_type, 0, 0, sem);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_wait_semaphore(context_handle[1], gc_ip_type, 0, 0, sem);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr = ib_result_cpu[1];
+ ptr[0] = gfx_nop;
+ ib_info[1].ib_mc_address = ib_result_mc_address[1];
+ ib_info[1].size = 1;
+
+ ibs_request[1].ip_type = gc_ip_type;
+ ibs_request[1].number_of_ibs = 1;
+ ibs_request[1].ibs = &ib_info[1];
+ ibs_request[1].resources = bo_list[1];
+ ibs_request[1].fence_info.handle = NULL;
+ r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request[1], 1);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.context = context_handle[1];
+ fence_status.ip_type = gc_ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.fence = ibs_request[1].seq_no;
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ 500000000, 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ for (i = 0; i < 2; i++) {
+ r = amdgpu_bo_unmap_and_free(ib_result_handle[i], va_handle[i],
+ ib_result_mc_address[i], 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list[i]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle[i]);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ r = amdgpu_cs_destroy_semaphore(sem);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_compute_nop(void)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t *ptr;
+ uint32_t expired;
+ int r, instance;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ struct drm_amdgpu_info_hw_ip info;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (instance = 0; (1 << instance) & info.available_rings; instance++) {
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ memset(ptr, 0, 16);
+ ptr[0]=PACKET3(PACKET3_NOP, 14);
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_COMPUTE;
+ ibs_request.ring = instance;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_COMPUTE;
+ fence_status.ip_instance = 0;
+ fence_status.ring = instance;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_compute_cp_write_data(void)
+{
+ amdgpu_command_submission_write_linear_helper(AMDGPU_HW_IP_COMPUTE);
+}
+
+static void amdgpu_command_submission_compute_cp_const_fill(void)
+{
+ amdgpu_command_submission_const_fill_helper(AMDGPU_HW_IP_COMPUTE);
+}
+
+static void amdgpu_command_submission_compute_cp_copy_data(void)
+{
+ amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_COMPUTE);
+}
+
+static void amdgpu_command_submission_compute(void)
+{
+ /* write data using the CP */
+ amdgpu_command_submission_compute_cp_write_data();
+ /* const fill using the CP */
+ amdgpu_command_submission_compute_cp_const_fill();
+ /* copy data using the CP */
+ amdgpu_command_submission_compute_cp_copy_data();
+ /* nop test */
+ amdgpu_command_submission_compute_nop();
+}
+
+/*
+ * caller need create/release:
+ * pm4_src, resources, ib_info, and ibs_request
+ * submit command stream described in ibs_request and wait for this IB accomplished
+ */
+void
+amdgpu_test_exec_cs_helper_raw(amdgpu_device_handle device_handle,
+ amdgpu_context_handle context_handle,
+ unsigned ip_type, int instance, int pm4_dw,
+ uint32_t *pm4_src, int res_cnt,
+ amdgpu_bo_handle *resources,
+ struct amdgpu_cs_ib_info *ib_info,
+ struct amdgpu_cs_request *ibs_request,
+ bool secure)
+{
+ int r;
+ uint32_t expired;
+ uint32_t *ring_ptr;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_fence fence_status = {0};
+ amdgpu_bo_handle *all_res = alloca(sizeof(resources[0]) * (res_cnt + 1));
+ amdgpu_va_handle va_handle;
+
+ /* prepare CS */
+ CU_ASSERT_NOT_EQUAL(pm4_src, NULL);
+ CU_ASSERT_NOT_EQUAL(resources, NULL);
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+ CU_ASSERT_TRUE(pm4_dw <= 1024);
+
+ /* allocate IB */
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* copy PM4 packet to ring from caller */
+ ring_ptr = ib_result_cpu;
+ memcpy(ring_ptr, pm4_src, pm4_dw * sizeof(*pm4_src));
+
+ ib_info->ib_mc_address = ib_result_mc_address;
+ ib_info->size = pm4_dw;
+ if (secure)
+ ib_info->flags |= AMDGPU_IB_FLAGS_SECURE;
+
+ ibs_request->ip_type = ip_type;
+ ibs_request->ring = instance;
+ ibs_request->number_of_ibs = 1;
+ ibs_request->ibs = ib_info;
+ ibs_request->fence_info.handle = NULL;
+
+ memcpy(all_res, resources, sizeof(resources[0]) * res_cnt);
+ all_res[res_cnt] = ib_result_handle;
+
+ r = amdgpu_bo_list_create(device_handle, res_cnt+1, all_res,
+ NULL, &ibs_request->resources);
+ CU_ASSERT_EQUAL(r, 0);
+
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ /* submit CS */
+ r = amdgpu_cs_submit(context_handle, 0, ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(ibs_request->resources);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.ip_type = ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.ring = ibs_request->ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request->seq_no;
+
+ /* wait for IB accomplished */
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void
+amdgpu_test_exec_cs_helper(amdgpu_context_handle context_handle,
+ unsigned ip_type, int instance, int pm4_dw,
+ uint32_t *pm4_src, int res_cnt,
+ amdgpu_bo_handle *resources,
+ struct amdgpu_cs_ib_info *ib_info,
+ struct amdgpu_cs_request *ibs_request)
+{
+ amdgpu_test_exec_cs_helper_raw(device_handle, context_handle,
+ ip_type, instance, pm4_dw, pm4_src,
+ res_cnt, resources, ib_info,
+ ibs_request, false);
+}
+
+void
+amdgpu_command_submission_write_linear_helper_with_secure(amdgpu_device_handle
+ device, unsigned
+ ip_type, bool secure)
+{
+ const int sdma_write_length = 128;
+ const int pm4_dw = 256;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle bo;
+ amdgpu_bo_handle *resources;
+ uint32_t *pm4;
+ struct amdgpu_cs_ib_info *ib_info;
+ struct amdgpu_cs_request *ibs_request;
+ uint64_t bo_mc;
+ volatile uint32_t *bo_cpu;
+ uint32_t bo_cpu_origin;
+ int i, j, r, loop, ring_id;
+ uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
+ amdgpu_va_handle va_handle;
+ struct drm_amdgpu_info_hw_ip hw_ip_info;
+
+ pm4 = calloc(pm4_dw, sizeof(*pm4));
+ CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+ ib_info = calloc(1, sizeof(*ib_info));
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+ ibs_request = calloc(1, sizeof(*ibs_request));
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ r = amdgpu_query_hw_ip_info(device, ip_type, 0, &hw_ip_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (i = 0; secure && (i < 2); i++)
+ gtt_flags[i] |= AMDGPU_GEM_CREATE_ENCRYPTED;
+
+ r = amdgpu_cs_ctx_create(device, &context_handle);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* prepare resource */
+ resources = calloc(1, sizeof(amdgpu_bo_handle));
+ CU_ASSERT_NOT_EQUAL(resources, NULL);
+
+ for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+ loop = 0;
+ while(loop < 2) {
+ /* allocate UC bo for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device,
+ sdma_write_length * sizeof(uint32_t),
+ 4096, AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop], &bo, (void**)&bo_cpu,
+ &bo_mc, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* clear bo */
+ memset((void*)bo_cpu, 0, sdma_write_length * sizeof(uint32_t));
+
+ resources[0] = bo;
+
+ /* fulfill PM4: test DMA write-linear */
+ i = j = 0;
+ if (ip_type == AMDGPU_HW_IP_DMA) {
+ if (family_id == AMDGPU_FAMILY_SI)
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0,
+ sdma_write_length);
+ else
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+ SDMA_WRITE_SUB_OPCODE_LINEAR,
+ secure ? SDMA_ATOMIC_TMZ(1) : 0);
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ if (family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = sdma_write_length - 1;
+ else if (family_id != AMDGPU_FAMILY_SI)
+ pm4[i++] = sdma_write_length;
+ while(j++ < sdma_write_length)
+ pm4[i++] = 0xdeadbeaf;
+ } else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+ (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+ pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length);
+ pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ while(j++ < sdma_write_length)
+ pm4[i++] = 0xdeadbeaf;
+ }
+
+ amdgpu_test_exec_cs_helper_raw(device, context_handle,
+ ip_type, ring_id, i, pm4,
+ 1, resources, ib_info,
+ ibs_request, secure);
+
+ /* verify if SDMA test result meets with expected */
+ i = 0;
+ if (!secure) {
+ while(i < sdma_write_length) {
+ CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
+ }
+ } else if (ip_type == AMDGPU_HW_IP_GFX) {
+ memset((void*)pm4, 0, pm4_dw * sizeof(uint32_t));
+ pm4[i++] = PACKET3(PACKET3_ATOMIC_MEM, 7);
+ /* atomic opcode for 32b w/ RTN and ATOMIC_SWAPCMP_RTN
+ * command, 1-loop_until_compare_satisfied.
+ * single_pass_atomic, 0-lru
+ * engine_sel, 0-micro_engine
+ */
+ pm4[i++] = (TC_OP_ATOMIC_CMPSWAP_RTN_32 |
+ ATOMIC_MEM_COMMAND(1) |
+ ATOMIC_MEM_CACHEPOLICAY(0) |
+ ATOMIC_MEM_ENGINESEL(0));
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = 0x12345678;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0x100;
+ amdgpu_test_exec_cs_helper_raw(device, context_handle,
+ ip_type, ring_id, i, pm4,
+ 1, resources, ib_info,
+ ibs_request, true);
+ } else if (ip_type == AMDGPU_HW_IP_DMA) {
+ /* restore the bo_cpu to compare */
+ bo_cpu_origin = bo_cpu[0];
+ memset((void*)pm4, 0, pm4_dw * sizeof(uint32_t));
+ /* atomic opcode for 32b w/ RTN and ATOMIC_SWAPCMP_RTN
+ * loop, 1-loop_until_compare_satisfied.
+ * single_pass_atomic, 0-lru
+ */
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_ATOMIC,
+ 0,
+ SDMA_ATOMIC_LOOP(1) |
+ SDMA_ATOMIC_TMZ(1) |
+ SDMA_ATOMIC_OPCODE(TC_OP_ATOMIC_CMPSWAP_RTN_32));
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = 0x12345678;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0x100;
+ amdgpu_test_exec_cs_helper_raw(device, context_handle,
+ ip_type, ring_id, i, pm4,
+ 1, resources, ib_info,
+ ibs_request, true);
+ /* DMA's atomic behavir is unlike GFX
+ * If the comparing data is not equal to destination data,
+ * For GFX, loop again till gfx timeout(system hang).
+ * For DMA, loop again till timer expired and then send interrupt.
+ * So testcase can't use interrupt mechanism.
+ * We take another way to verify. When the comparing data is not
+ * equal to destination data, overwrite the source data to the destination
+ * buffer. Otherwise, original destination data unchanged.
+ * So if the bo_cpu data is overwritten, the result is passed.
+ */
+ CU_ASSERT_NOT_EQUAL(bo_cpu[0], bo_cpu_origin);
+
+ /* compare again for the case of dest_data != cmp_data */
+ i = 0;
+ /* restore again, here dest_data should be */
+ bo_cpu_origin = bo_cpu[0];
+ memset((void*)pm4, 0, pm4_dw * sizeof(uint32_t));
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_ATOMIC,
+ 0,
+ SDMA_ATOMIC_LOOP(1) |
+ SDMA_ATOMIC_TMZ(1) |
+ SDMA_ATOMIC_OPCODE(TC_OP_ATOMIC_CMPSWAP_RTN_32));
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = 0x87654321;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = 0x0;
+ pm4[i++] = 0x100;
+ amdgpu_test_exec_cs_helper_raw(device, context_handle,
+ ip_type, ring_id, i, pm4,
+ 1, resources, ib_info,
+ ibs_request, true);
+ /* here bo_cpu[0] should be unchanged, still is 0x12345678, otherwise failed*/
+ CU_ASSERT_EQUAL(bo_cpu[0], bo_cpu_origin);
+ }
+
+ r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
+ sdma_write_length * sizeof(uint32_t));
+ CU_ASSERT_EQUAL(r, 0);
+ loop++;
+ }
+ }
+ /* clean resources */
+ free(resources);
+ free(ibs_request);
+ free(ib_info);
+ free(pm4);
+
+ /* end of test */
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_write_linear_helper(unsigned ip_type)
+{
+ amdgpu_command_submission_write_linear_helper_with_secure(device_handle,
+ ip_type,
+ false);
+}
+
+static void amdgpu_command_submission_sdma_write_linear(void)
+{
+ amdgpu_command_submission_write_linear_helper(AMDGPU_HW_IP_DMA);
+}
+
+static void amdgpu_command_submission_const_fill_helper(unsigned ip_type)
+{
+ const int sdma_write_length = 1024 * 1024;
+ const int pm4_dw = 256;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle bo;
+ amdgpu_bo_handle *resources;
+ uint32_t *pm4;
+ struct amdgpu_cs_ib_info *ib_info;
+ struct amdgpu_cs_request *ibs_request;
+ uint64_t bo_mc;
+ volatile uint32_t *bo_cpu;
+ int i, j, r, loop, ring_id;
+ uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
+ amdgpu_va_handle va_handle;
+ struct drm_amdgpu_info_hw_ip hw_ip_info;
+
+ pm4 = calloc(pm4_dw, sizeof(*pm4));
+ CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+ ib_info = calloc(1, sizeof(*ib_info));
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+ ibs_request = calloc(1, sizeof(*ibs_request));
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* prepare resource */
+ resources = calloc(1, sizeof(amdgpu_bo_handle));
+ CU_ASSERT_NOT_EQUAL(resources, NULL);
+
+ for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+ loop = 0;
+ while(loop < 2) {
+ /* allocate UC bo for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop], &bo, (void**)&bo_cpu,
+ &bo_mc, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* clear bo */
+ memset((void*)bo_cpu, 0, sdma_write_length);
+
+ resources[0] = bo;
+
+ /* fulfill PM4: test DMA const fill */
+ i = j = 0;
+ if (ip_type == AMDGPU_HW_IP_DMA) {
+ if (family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_CONSTANT_FILL_SI,
+ 0, 0, 0,
+ sdma_write_length / 4);
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 16;
+ } else {
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0,
+ SDMA_CONSTANT_FILL_EXTRA_SIZE(2));
+ pm4[i++] = 0xffffffff & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = 0xdeadbeaf;
+ if (family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = sdma_write_length - 1;
+ else
+ pm4[i++] = sdma_write_length;
+ }
+ } else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+ (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+ if (family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4);
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) |
+ PACKET3_DMA_DATA_SI_DST_SEL(0) |
+ PACKET3_DMA_DATA_SI_SRC_SEL(2) |
+ PACKET3_DMA_DATA_SI_CP_SYNC;
+ pm4[i++] = 0xffffffff & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = sdma_write_length;
+ } else {
+ pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
+ pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
+ PACKET3_DMA_DATA_DST_SEL(0) |
+ PACKET3_DMA_DATA_SRC_SEL(2) |
+ PACKET3_DMA_DATA_CP_SYNC;
+ pm4[i++] = 0xdeadbeaf;
+ pm4[i++] = 0;
+ pm4[i++] = 0xfffffffc & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ pm4[i++] = sdma_write_length;
+ }
+ }
+
+ amdgpu_test_exec_cs_helper(context_handle,
+ ip_type, ring_id,
+ i, pm4,
+ 1, resources,
+ ib_info, ibs_request);
+
+ /* verify if SDMA test result meets with expected */
+ i = 0;
+ while(i < (sdma_write_length / 4)) {
+ CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
+ }
+
+ r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+ loop++;
+ }
+ }
+ /* clean resources */
+ free(resources);
+ free(ibs_request);
+ free(ib_info);
+ free(pm4);
+
+ /* end of test */
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_sdma_const_fill(void)
+{
+ amdgpu_command_submission_const_fill_helper(AMDGPU_HW_IP_DMA);
+}
+
+static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type)
+{
+ const int sdma_write_length = 1024;
+ const int pm4_dw = 256;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle bo1, bo2;
+ amdgpu_bo_handle *resources;
+ uint32_t *pm4;
+ struct amdgpu_cs_ib_info *ib_info;
+ struct amdgpu_cs_request *ibs_request;
+ uint64_t bo1_mc, bo2_mc;
+ volatile unsigned char *bo1_cpu, *bo2_cpu;
+ int i, j, r, loop1, loop2, ring_id;
+ uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
+ amdgpu_va_handle bo1_va_handle, bo2_va_handle;
+ struct drm_amdgpu_info_hw_ip hw_ip_info;
+
+ pm4 = calloc(pm4_dw, sizeof(*pm4));
+ CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+ ib_info = calloc(1, sizeof(*ib_info));
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+ ibs_request = calloc(1, sizeof(*ibs_request));
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* prepare resource */
+ resources = calloc(2, sizeof(amdgpu_bo_handle));
+ CU_ASSERT_NOT_EQUAL(resources, NULL);
+
+ for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+ loop1 = loop2 = 0;
+ /* run 9 circle to test all mapping combination */
+ while(loop1 < 2) {
+ while(loop2 < 2) {
+ /* allocate UC bo1for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop1], &bo1,
+ (void**)&bo1_cpu, &bo1_mc,
+ &bo1_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* set bo1 */
+ memset((void*)bo1_cpu, 0xaa, sdma_write_length);
+
+ /* allocate UC bo2 for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ gtt_flags[loop2], &bo2,
+ (void**)&bo2_cpu, &bo2_mc,
+ &bo2_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* clear bo2 */
+ memset((void*)bo2_cpu, 0, sdma_write_length);
+
+ resources[0] = bo1;
+ resources[1] = bo2;
+
+ /* fulfill PM4: test DMA copy linear */
+ i = j = 0;
+ if (ip_type == AMDGPU_HW_IP_DMA) {
+ if (family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI,
+ 0, 0, 0,
+ sdma_write_length);
+ pm4[i++] = 0xffffffff & bo2_mc;
+ pm4[i++] = 0xffffffff & bo1_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ } else {
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY,
+ SDMA_COPY_SUB_OPCODE_LINEAR,
+ 0);
+ if (family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = sdma_write_length - 1;
+ else
+ pm4[i++] = sdma_write_length;
+ pm4[i++] = 0;
+ pm4[i++] = 0xffffffff & bo1_mc;
+ pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ pm4[i++] = 0xffffffff & bo2_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ }
+ } else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+ (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+ if (family_id == AMDGPU_FAMILY_SI) {
+ pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4);
+ pm4[i++] = 0xfffffffc & bo1_mc;
+ pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) |
+ PACKET3_DMA_DATA_SI_DST_SEL(0) |
+ PACKET3_DMA_DATA_SI_SRC_SEL(0) |
+ PACKET3_DMA_DATA_SI_CP_SYNC |
+ (0xffff00000000 & bo1_mc) >> 32;
+ pm4[i++] = 0xfffffffc & bo2_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ pm4[i++] = sdma_write_length;
+ } else {
+ pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
+ pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
+ PACKET3_DMA_DATA_DST_SEL(0) |
+ PACKET3_DMA_DATA_SRC_SEL(0) |
+ PACKET3_DMA_DATA_CP_SYNC;
+ pm4[i++] = 0xfffffffc & bo1_mc;
+ pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ pm4[i++] = 0xfffffffc & bo2_mc;
+ pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ pm4[i++] = sdma_write_length;
+ }
+ }
+
+ amdgpu_test_exec_cs_helper(context_handle,
+ ip_type, ring_id,
+ i, pm4,
+ 2, resources,
+ ib_info, ibs_request);
+
+ /* verify if SDMA test result meets with expected */
+ i = 0;
+ while(i < sdma_write_length) {
+ CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa);
+ }
+ r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+ loop2++;
+ }
+ loop1++;
+ }
+ }
+ /* clean resources */
+ free(resources);
+ free(ibs_request);
+ free(ib_info);
+ free(pm4);
+
+ /* end of test */
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_sdma_copy_linear(void)
+{
+ amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_DMA);
+}
+
+static void amdgpu_command_submission_sdma(void)
+{
+ amdgpu_command_submission_sdma_write_linear();
+ amdgpu_command_submission_sdma_const_fill();
+ amdgpu_command_submission_sdma_copy_linear();
+}
+
+static void amdgpu_command_submission_multi_fence_wait_all(bool wait_all)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle, ib_result_ce_handle;
+ void *ib_result_cpu, *ib_result_ce_cpu;
+ uint64_t ib_result_mc_address, ib_result_ce_mc_address;
+ struct amdgpu_cs_request ibs_request[2] = {0};
+ struct amdgpu_cs_ib_info ib_info[2];
+ struct amdgpu_cs_fence fence_status[2] = {0};
+ uint32_t *ptr;
+ uint32_t expired;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle, va_handle_ce;
+ int r;
+ int i = 0, ib_cs_num = 2;
+ struct drm_amdgpu_info_hw_ip info;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (info.hw_ip_version_major >= 11)
+ return;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_ce_handle, &ib_result_ce_cpu,
+ &ib_result_ce_mc_address, &va_handle_ce);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle,
+ ib_result_ce_handle, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(ib_info, 0, 2 * sizeof(struct amdgpu_cs_ib_info));
+
+ /* IT_SET_CE_DE_COUNTERS */
+ ptr = ib_result_ce_cpu;
+ if (family_id != AMDGPU_FAMILY_SI) {
+ ptr[i++] = 0xc0008900;
+ ptr[i++] = 0;
+ }
+ ptr[i++] = 0xc0008400;
+ ptr[i++] = 1;
+ ib_info[0].ib_mc_address = ib_result_ce_mc_address;
+ ib_info[0].size = i;
+ ib_info[0].flags = AMDGPU_IB_FLAG_CE;
+
+ /* IT_WAIT_ON_CE_COUNTER */
+ ptr = ib_result_cpu;
+ ptr[0] = 0xc0008600;
+ ptr[1] = 0x00000001;
+ ib_info[1].ib_mc_address = ib_result_mc_address;
+ ib_info[1].size = 2;
+
+ for (i = 0; i < ib_cs_num; i++) {
+ ibs_request[i].ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request[i].number_of_ibs = 2;
+ ibs_request[i].ibs = ib_info;
+ ibs_request[i].resources = bo_list;
+ ibs_request[i].fence_info.handle = NULL;
+ }
+
+ r = amdgpu_cs_submit(context_handle, 0,ibs_request, ib_cs_num);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (i = 0; i < ib_cs_num; i++) {
+ fence_status[i].context = context_handle;
+ fence_status[i].ip_type = AMDGPU_HW_IP_GFX;
+ fence_status[i].fence = ibs_request[i].seq_no;
+ }
+
+ r = amdgpu_cs_wait_fences(fence_status, ib_cs_num, wait_all,
+ AMDGPU_TIMEOUT_INFINITE,
+ &expired, NULL);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_ce_handle, va_handle_ce,
+ ib_result_ce_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_multi_fence(void)
+{
+ amdgpu_command_submission_multi_fence_wait_all(true);
+ amdgpu_command_submission_multi_fence_wait_all(false);
+}
+
+static void amdgpu_userptr_test(void)
+{
+ int i, r, j;
+ uint32_t *pm4 = NULL;
+ uint64_t bo_mc;
+ void *ptr = NULL;
+ int pm4_dw = 256;
+ int sdma_write_length = 4;
+ amdgpu_bo_handle handle;
+ amdgpu_context_handle context_handle;
+ struct amdgpu_cs_ib_info *ib_info;
+ struct amdgpu_cs_request *ibs_request;
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+
+ pm4 = calloc(pm4_dw, sizeof(*pm4));
+ CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+ ib_info = calloc(1, sizeof(*ib_info));
+ CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+ ibs_request = calloc(1, sizeof(*ibs_request));
+ CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ posix_memalign(&ptr, sysconf(_SC_PAGE_SIZE), BUFFER_SIZE);
+ CU_ASSERT_NOT_EQUAL(ptr, NULL);
+ memset(ptr, 0, BUFFER_SIZE);
+
+ r = amdgpu_create_bo_from_user_mem(device_handle,
+ ptr, BUFFER_SIZE, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ BUFFER_SIZE, 1, 0, &bo_mc,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, BUFFER_SIZE, bo_mc, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ handle = buf_handle;
+
+ j = i = 0;
+
+ if (family_id == AMDGPU_FAMILY_SI)
+ pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0,
+ sdma_write_length);
+ else
+ pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+ SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+ pm4[i++] = 0xffffffff & bo_mc;
+ pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+ if (family_id >= AMDGPU_FAMILY_AI)
+ pm4[i++] = sdma_write_length - 1;
+ else if (family_id != AMDGPU_FAMILY_SI)
+ pm4[i++] = sdma_write_length;
+
+ while (j++ < sdma_write_length)
+ pm4[i++] = 0xdeadbeaf;
+
+ if (!fork()) {
+ pm4[0] = 0x0;
+ exit(0);
+ }
+
+ amdgpu_test_exec_cs_helper(context_handle,
+ AMDGPU_HW_IP_DMA, 0,
+ i, pm4,
+ 1, &handle,
+ ib_info, ibs_request);
+ i = 0;
+ while (i < sdma_write_length) {
+ CU_ASSERT_EQUAL(((int*)ptr)[i++], 0xdeadbeaf);
+ }
+ free(ibs_request);
+ free(ib_info);
+ free(pm4);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, BUFFER_SIZE, bo_mc, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_va_range_free(va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ free(ptr);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ wait(NULL);
+}
+
+static void amdgpu_sync_dependency_test(void)
+{
+ amdgpu_context_handle context_handle[2];
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t expired;
+ int i, j, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ static uint32_t *ptr;
+ uint64_t seq_no;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle[0]);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle[1]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 8192, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ i = 0;
+
+ memcpy(ptr + CODE_OFFSET , shader_bin, sizeof(shader_bin));
+
+ /* Dispatch minimal init config and verify it's executed */
+ ptr[i++] = PACKET3(PKT3_CONTEXT_CONTROL, 1);
+ ptr[i++] = 0x80000000;
+ ptr[i++] = 0x80000000;
+
+ ptr[i++] = PACKET3(PKT3_CLEAR_STATE, 0);
+ ptr[i++] = 0x80000000;
+
+
+ /* Program compute regs */
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+ ptr[i++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START;
+ ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 8;
+ ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 40;
+
+
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+ ptr[i++] = mmCOMPUTE_PGM_RSRC1 - PACKET3_SET_SH_REG_START;
+ /*
+ * 002c0040 COMPUTE_PGM_RSRC1 <- VGPRS = 0
+ SGPRS = 1
+ PRIORITY = 0
+ FLOAT_MODE = 192 (0xc0)
+ PRIV = 0
+ DX10_CLAMP = 1
+ DEBUG_MODE = 0
+ IEEE_MODE = 0
+ BULKY = 0
+ CDBG_USER = 0
+ *
+ */
+ ptr[i++] = 0x002c0040;
+
+
+ /*
+ * 00000010 COMPUTE_PGM_RSRC2 <- SCRATCH_EN = 0
+ USER_SGPR = 8
+ TRAP_PRESENT = 0
+ TGID_X_EN = 0
+ TGID_Y_EN = 0
+ TGID_Z_EN = 0
+ TG_SIZE_EN = 0
+ TIDIG_COMP_CNT = 0
+ EXCP_EN_MSB = 0
+ LDS_SIZE = 0
+ EXCP_EN = 0
+ *
+ */
+ ptr[i++] = 0x00000010;
+
+
+/*
+ * 00000100 COMPUTE_TMPRING_SIZE <- WAVES = 256 (0x100)
+ WAVESIZE = 0
+ *
+ */
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1);
+ ptr[i++] = mmCOMPUTE_TMPRING_SIZE - PACKET3_SET_SH_REG_START;
+ ptr[i++] = 0x00000100;
+
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+ ptr[i++] = mmCOMPUTE_USER_DATA_0 - PACKET3_SET_SH_REG_START;
+ ptr[i++] = 0xffffffff & (ib_result_mc_address + DATA_OFFSET * 4);
+ ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32;
+
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1);
+ ptr[i++] = mmCOMPUTE_RESOURCE_LIMITS - PACKET3_SET_SH_REG_START;
+ ptr[i++] = 0;
+
+ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3);
+ ptr[i++] = mmCOMPUTE_NUM_THREAD_X - PACKET3_SET_SH_REG_START;
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+
+
+ /* Dispatch */
+ ptr[i++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+ ptr[i++] = 0x00000045; /* DISPATCH DIRECT field */
+
+
+ while (i & 7)
+ ptr[i++] = 0xffff1000; /* type3 nop packet */
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = i;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+ seq_no = ibs_request.seq_no;
+
+
+
+ /* Prepare second command with dependency on the first */
+ j = i;
+ ptr[i++] = PACKET3(PACKET3_WRITE_DATA, 3);
+ ptr[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
+ ptr[i++] = 0xfffffffc & (ib_result_mc_address + DATA_OFFSET * 4);
+ ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32;
+ ptr[i++] = 99;
+
+ while (i & 7)
+ ptr[i++] = 0xffff1000; /* type3 nop packet */
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address + j * 4;
+ ib_info.size = i - j;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ ibs_request.number_of_dependencies = 1;
+
+ ibs_request.dependencies = calloc(1, sizeof(*ibs_request.dependencies));
+ ibs_request.dependencies[0].context = context_handle[1];
+ ibs_request.dependencies[0].ip_instance = 0;
+ ibs_request.dependencies[0].ring = 0;
+ ibs_request.dependencies[0].fence = seq_no;
+
+
+ r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle[0];
+ fence_status.ip_type = AMDGPU_HW_IP_GFX;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Expect the second command to wait for shader to complete */
+ CU_ASSERT_EQUAL(ptr[DATA_OFFSET], 99);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle[0]);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_ctx_free(context_handle[1]);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free(ibs_request.dependencies);
+}
+
+static void amdgpu_compute_dispatch_test(void)
+{
+ amdgpu_test_dispatch_helper(device_handle, AMDGPU_HW_IP_COMPUTE);
+}
+static void amdgpu_gfx_dispatch_test(void)
+{
+ amdgpu_test_dispatch_helper(device_handle, AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_draw_test(void)
+{
+ amdgpu_test_draw_helper(device_handle);
+}
+static void amdgpu_gpu_reset_test(void)
+{
+ int r;
+ char debugfs_path[256], tmp[10];
+ int fd;
+ struct stat sbuf;
+ amdgpu_context_handle context_handle;
+ uint32_t hang_state, hangs;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = fstat(drm_amdgpu[0], &sbuf);
+ CU_ASSERT_EQUAL(r, 0);
+
+ sprintf(debugfs_path, "/sys/kernel/debug/dri/%d/amdgpu_gpu_recover", minor(sbuf.st_rdev));
+ fd = open(debugfs_path, O_RDONLY);
+ CU_ASSERT(fd >= 0);
+
+ r = read(fd, tmp, sizeof(tmp)/sizeof(char));
+ CU_ASSERT(r > 0);
+
+ r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET);
+
+ close(fd);
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ amdgpu_compute_dispatch_test();
+ amdgpu_gfx_dispatch_test();
+}
+
+static void amdgpu_stable_pstate_test(void)
+{
+ int r;
+ amdgpu_context_handle context_handle;
+ uint32_t current_pstate = 0, new_pstate = 0;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_stable_pstate(context_handle,
+ AMDGPU_CTX_OP_GET_STABLE_PSTATE,
+ 0, &current_pstate);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(new_pstate, AMDGPU_CTX_STABLE_PSTATE_NONE);
+
+ r = amdgpu_cs_ctx_stable_pstate(context_handle,
+ AMDGPU_CTX_OP_SET_STABLE_PSTATE,
+ AMDGPU_CTX_STABLE_PSTATE_PEAK, NULL);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_stable_pstate(context_handle,
+ AMDGPU_CTX_OP_GET_STABLE_PSTATE,
+ 0, &new_pstate);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(new_pstate, AMDGPU_CTX_STABLE_PSTATE_PEAK);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
diff --git a/tests/amdgpu/bo_tests.c b/tests/amdgpu/bo_tests.c
new file mode 100644
index 0000000..8fc7fe2
--- /dev/null
+++ b/tests/amdgpu/bo_tests.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#define BUFFER_SIZE (4*1024)
+#define BUFFER_ALIGN (4*1024)
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+
+static amdgpu_bo_handle buffer_handle;
+static uint64_t virtual_mc_base_address;
+static amdgpu_va_handle va_handle;
+
+static void amdgpu_bo_export_import(void);
+static void amdgpu_bo_metadata(void);
+static void amdgpu_bo_map_unmap(void);
+static void amdgpu_memory_alloc(void);
+static void amdgpu_mem_fail_alloc(void);
+static void amdgpu_bo_find_by_cpu_mapping(void);
+
+CU_TestInfo bo_tests[] = {
+ { "Export/Import", amdgpu_bo_export_import },
+ { "Metadata", amdgpu_bo_metadata },
+ { "CPU map/unmap", amdgpu_bo_map_unmap },
+ { "Memory alloc Test", amdgpu_memory_alloc },
+ { "Memory fail alloc Test", amdgpu_mem_fail_alloc },
+ { "Find bo by CPU mapping", amdgpu_bo_find_by_cpu_mapping },
+ CU_TEST_INFO_NULL,
+};
+
+int suite_bo_tests_init(void)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ uint64_t va;
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+
+ return CUE_SINIT_FAILED;
+ }
+
+ req.alloc_size = BUFFER_SIZE;
+ req.phys_alignment = BUFFER_ALIGN;
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ BUFFER_SIZE, BUFFER_ALIGN, 0,
+ &va, &va_handle, 0);
+ if (r)
+ goto error_va_alloc;
+
+ r = amdgpu_bo_va_op(buf_handle, 0, BUFFER_SIZE, va, 0, AMDGPU_VA_OP_MAP);
+ if (r)
+ goto error_va_map;
+
+ buffer_handle = buf_handle;
+ virtual_mc_base_address = va;
+
+ return CUE_SUCCESS;
+
+error_va_map:
+ amdgpu_va_range_free(va_handle);
+
+error_va_alloc:
+ amdgpu_bo_free(buf_handle);
+ return CUE_SINIT_FAILED;
+}
+
+int suite_bo_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_va_op(buffer_handle, 0, BUFFER_SIZE,
+ virtual_mc_base_address, 0,
+ AMDGPU_VA_OP_UNMAP);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_va_range_free(va_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_bo_free(buffer_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static void amdgpu_bo_export_import_do_type(enum amdgpu_bo_handle_type type)
+{
+ struct amdgpu_bo_import_result res = {0};
+ uint32_t shared_handle;
+ int r;
+
+ r = amdgpu_bo_export(buffer_handle, type, &shared_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_import(device_handle, type, shared_handle, &res);
+ CU_ASSERT_EQUAL(r, 0);
+
+ CU_ASSERT_EQUAL(res.buf_handle, buffer_handle);
+ CU_ASSERT_EQUAL(res.alloc_size, BUFFER_SIZE);
+
+ r = amdgpu_bo_free(res.buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_bo_export_import(void)
+{
+ if (open_render_node) {
+ printf("(DRM render node is used. Skip export/Import test) ");
+ return;
+ }
+
+ amdgpu_bo_export_import_do_type(amdgpu_bo_handle_type_gem_flink_name);
+ amdgpu_bo_export_import_do_type(amdgpu_bo_handle_type_dma_buf_fd);
+}
+
+static void amdgpu_bo_metadata(void)
+{
+ struct amdgpu_bo_metadata meta = {0};
+ struct amdgpu_bo_info info = {0};
+ int r;
+
+ meta.size_metadata = 4;
+ meta.umd_metadata[0] = 0xdeadbeef;
+
+ r = amdgpu_bo_set_metadata(buffer_handle, &meta);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_query_info(buffer_handle, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ CU_ASSERT_EQUAL(info.metadata.size_metadata, 4);
+ CU_ASSERT_EQUAL(info.metadata.umd_metadata[0], 0xdeadbeef);
+}
+
+static void amdgpu_bo_map_unmap(void)
+{
+ uint32_t *ptr;
+ int i, r;
+
+ r = amdgpu_bo_cpu_map(buffer_handle, (void **)&ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_NOT_EQUAL(ptr, NULL);
+
+ for (i = 0; i < (BUFFER_SIZE / 4); ++i)
+ ptr[i] = 0xdeadbeef;
+
+ r = amdgpu_bo_cpu_unmap(buffer_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_memory_alloc(void)
+{
+ amdgpu_bo_handle bo;
+ amdgpu_va_handle va_handle;
+ uint64_t bo_mc;
+ int r;
+
+ /* Test visible VRAM */
+ bo = gpu_mem_alloc(device_handle,
+ 4096, 4096,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test invisible VRAM */
+ bo = gpu_mem_alloc(device_handle,
+ 4096, 4096,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test GART Cacheable */
+ bo = gpu_mem_alloc(device_handle,
+ 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ 0, &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test GART USWC */
+ bo = gpu_mem_alloc(device_handle,
+ 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ AMDGPU_GEM_CREATE_CPU_GTT_USWC,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test GDS */
+ bo = gpu_mem_alloc(device_handle, 1024, 0,
+ AMDGPU_GEM_DOMAIN_GDS, 0,
+ NULL, NULL);
+ r = gpu_mem_free(bo, NULL, 0, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test GWS */
+ bo = gpu_mem_alloc(device_handle, 1, 0,
+ AMDGPU_GEM_DOMAIN_GWS, 0,
+ NULL, NULL);
+ r = gpu_mem_free(bo, NULL, 0, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test OA */
+ bo = gpu_mem_alloc(device_handle, 1, 0,
+ AMDGPU_GEM_DOMAIN_OA, 0,
+ NULL, NULL);
+ r = gpu_mem_free(bo, NULL, 0, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_mem_fail_alloc(void)
+{
+ int r;
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+
+ /* Test impossible mem allocation, 1TB */
+ req.alloc_size = 0xE8D4A51000;
+ req.phys_alignment = 4096;
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM;
+ req.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, -ENOMEM);
+
+ if (!r) {
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+}
+
+static void amdgpu_bo_find_by_cpu_mapping(void)
+{
+ amdgpu_bo_handle bo_handle, find_bo_handle;
+ amdgpu_va_handle va_handle;
+ void *bo_cpu;
+ uint64_t bo_mc_address;
+ uint64_t offset;
+ int r;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &bo_handle, &bo_cpu,
+ &bo_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_find_bo_by_cpu_mapping(device_handle,
+ bo_cpu,
+ 4096,
+ &find_bo_handle,
+ &offset);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(offset, 0);
+ CU_ASSERT_EQUAL(bo_handle->handle, find_bo_handle->handle);
+
+ atomic_dec(&find_bo_handle->refcount, 1);
+ r = amdgpu_bo_unmap_and_free(bo_handle, va_handle,
+ bo_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+}
diff --git a/tests/amdgpu/cp_dma_tests.c b/tests/amdgpu/cp_dma_tests.c
new file mode 100644
index 0000000..e82214f
--- /dev/null
+++ b/tests/amdgpu/cp_dma_tests.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#define IB_SIZE 4096
+#define MAX_RESOURCES 8
+
+#define DMA_SIZE 4097
+#define DMA_DATA_BYTE 0xea
+
+static bool do_p2p;
+
+static amdgpu_device_handle executing_device_handle;
+static uint32_t executing_device_major_version;
+static uint32_t executing_device_minor_version;
+
+static amdgpu_device_handle peer_exporting_device_handle;
+static uint32_t peer_exporting_device_major_version;
+static uint32_t peer_exporting_device_minor_version;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static uint32_t *ib_cpu;
+static uint64_t ib_mc_address;
+static amdgpu_va_handle ib_va_handle;
+static uint32_t num_dword;
+
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static uint8_t* reference_data;
+
+static void amdgpu_cp_dma_host_to_vram(void);
+static void amdgpu_cp_dma_vram_to_host(void);
+static void amdgpu_cp_dma_p2p_vram_to_vram(void);
+static void amdgpu_cp_dma_p2p_host_to_vram(void);
+static void amdgpu_cp_dma_p2p_vram_to_host(void);
+
+/**
+ * Tests in cp dma test suite
+ */
+CU_TestInfo cp_dma_tests[] = {
+ { "CP DMA write Host to VRAM", amdgpu_cp_dma_host_to_vram },
+ { "CP DMA write VRAM to Host", amdgpu_cp_dma_vram_to_host },
+
+ { "Peer to Peer CP DMA write VRAM to VRAM", amdgpu_cp_dma_p2p_vram_to_vram },
+ { "Peer to Peer CP DMA write Host to VRAM", amdgpu_cp_dma_p2p_host_to_vram },
+ { "Peer to Peer CP DMA write VRAM to Host", amdgpu_cp_dma_p2p_vram_to_host },
+ CU_TEST_INFO_NULL,
+};
+
+struct amdgpu_cp_dma_bo{
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t gpu_va;
+ uint64_t size;
+};
+
+static int allocate_bo_and_va(amdgpu_device_handle dev,
+ uint64_t size, uint64_t alignment,
+ uint32_t heap, uint64_t alloc_flags,
+ struct amdgpu_cp_dma_bo *bo) {
+ struct amdgpu_bo_alloc_request request = {};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t vmc_addr;
+ int r;
+
+ request.alloc_size = size;
+ request.phys_alignment = alignment;
+ request.preferred_heap = heap;
+ request.flags = alloc_flags;
+
+ r = amdgpu_bo_alloc(dev, &request, &buf_handle);
+ if (r)
+ goto error_bo_alloc;
+
+ r = amdgpu_va_range_alloc(dev, amdgpu_gpu_va_range_general,
+ size, alignment, 0,
+ &vmc_addr, &va_handle, 0);
+ if (r)
+ goto error_va_alloc;
+
+ r = amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr,
+ AMDGPU_VM_PAGE_READABLE |
+ AMDGPU_VM_PAGE_WRITEABLE |
+ AMDGPU_VM_PAGE_EXECUTABLE,
+ AMDGPU_VA_OP_MAP);
+ if (r)
+ goto error_va_map;
+
+ bo->buf_handle = buf_handle;
+ bo->va_handle = va_handle;
+ bo->gpu_va = vmc_addr;
+ bo->size = size;
+
+ return 0;
+
+error_va_map:
+ amdgpu_bo_va_op(buf_handle, 0,
+ size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP);
+
+error_va_alloc:
+ amdgpu_va_range_free(va_handle);
+
+error_bo_alloc:
+ amdgpu_bo_free(buf_handle);
+
+ return r;
+}
+
+static int import_dma_buf_to_bo(amdgpu_device_handle dev,
+ int dmabuf_fd, struct amdgpu_cp_dma_bo *bo) {
+ amdgpu_va_handle va_handle;
+ uint64_t vmc_addr;
+ int r;
+ struct amdgpu_bo_import_result bo_import_result = {};
+
+ r = amdgpu_bo_import(dev, amdgpu_bo_handle_type_dma_buf_fd,
+ dmabuf_fd, &bo_import_result);
+ if (r)
+ goto error_bo_import;
+
+ r = amdgpu_va_range_alloc(dev, amdgpu_gpu_va_range_general,
+ bo_import_result.alloc_size, 0, 0,
+ &vmc_addr, &va_handle, 0);
+ if (r)
+ goto error_va_alloc;
+
+ r = amdgpu_bo_va_op(bo_import_result.buf_handle, 0,
+ bo_import_result.alloc_size, vmc_addr,
+ AMDGPU_VM_PAGE_READABLE |
+ AMDGPU_VM_PAGE_WRITEABLE |
+ AMDGPU_VM_PAGE_EXECUTABLE,
+ AMDGPU_VA_OP_MAP);
+ if (r)
+ goto error_va_map;
+
+ bo->buf_handle = bo_import_result.buf_handle;
+ bo->va_handle = va_handle;
+ bo->gpu_va = vmc_addr;
+ bo->size = bo_import_result.alloc_size;
+
+ return 0;
+
+error_va_map:
+ amdgpu_bo_va_op(bo_import_result.buf_handle, 0,
+ bo_import_result.alloc_size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP);
+
+error_va_alloc:
+ amdgpu_va_range_free(va_handle);
+
+error_bo_import:
+ amdgpu_bo_free(bo_import_result.buf_handle);
+
+ return r;
+}
+
+static int free_bo(struct amdgpu_cp_dma_bo bo) {
+ int r;
+ r = amdgpu_bo_va_op(bo.buf_handle, 0,
+ bo.size, bo.gpu_va, 0, AMDGPU_VA_OP_UNMAP);
+ if(r)
+ return r;
+
+ r = amdgpu_va_range_free(bo.va_handle);
+ if(r)
+ return r;
+
+ r = amdgpu_bo_free(bo.buf_handle);
+ if(r)
+ return r;
+
+ return 0;
+}
+
+static int submit_and_sync() {
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ uint32_t family_id, chip_id, chip_rev;
+ unsigned gc_ip_type;
+ int r;
+
+ r = amdgpu_bo_list_create(executing_device_handle,
+ num_resources, resources,
+ NULL, &ibs_request.resources);
+ if (r)
+ return r;
+
+ family_id = executing_device_handle->info.family_id;
+ chip_id = executing_device_handle->info.chip_external_rev;
+ chip_rev = executing_device_handle->info.chip_rev;
+
+ gc_ip_type = (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) ?
+ AMDGPU_HW_IP_COMPUTE : AMDGPU_HW_IP_GFX;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = num_dword;
+
+ ibs_request.ip_type = gc_ip_type;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = gc_ip_type;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void cp_dma_cmd(struct amdgpu_cp_dma_bo src_bo,
+ struct amdgpu_cp_dma_bo dst_bo) {
+ _Static_assert(DMA_SIZE < (1 << 26), "DMA size exceeds CP DMA maximium!");
+
+ ib_cpu[0] = 0xc0055000;
+ ib_cpu[1] = 0x80000000;
+ ib_cpu[2] = src_bo.gpu_va & 0x00000000ffffffff;
+ ib_cpu[3] = (src_bo.gpu_va & 0xffffffff00000000) >> 32;
+ ib_cpu[4] = dst_bo.gpu_va & 0x00000000ffffffff;
+ ib_cpu[5] = (dst_bo.gpu_va & 0xffffffff00000000) >> 32;
+ // size is read from the lower 26bits.
+ ib_cpu[6] = ((1 << 26) - 1) & DMA_SIZE;
+ ib_cpu[7] = 0xffff1000;
+
+ num_dword = 8;
+
+ resources[0] = src_bo.buf_handle;
+ resources[1] = dst_bo.buf_handle;
+ resources[2] = ib_handle;
+ num_resources = 3;
+}
+
+static void amdgpu_cp_dma(uint32_t src_heap, uint32_t dst_heap) {
+ int r;
+ struct amdgpu_cp_dma_bo src_bo = {0};
+ struct amdgpu_cp_dma_bo dst_bo = {0};
+ void *src_bo_cpu;
+ void *dst_bo_cpu;
+
+ /* allocate the src bo, set its data to DMA_DATA_BYTE */
+ r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096,
+ src_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &src_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(src_bo.buf_handle, (void **)&src_bo_cpu);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(src_bo_cpu, DMA_DATA_BYTE, DMA_SIZE);
+
+ r = amdgpu_bo_cpu_unmap(src_bo.buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* allocate the dst bo and clear its content to all 0 */
+ r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096,
+ dst_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &dst_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(dst_bo.buf_handle, (void **)&dst_bo_cpu);
+ CU_ASSERT_EQUAL(r, 0);
+
+ _Static_assert(DMA_DATA_BYTE != 0, "Initialization data should be different from DMA data!");
+ memset(dst_bo_cpu, 0, DMA_SIZE);
+
+ /* record CP DMA command and dispatch the command */
+ cp_dma_cmd(src_bo, dst_bo);
+
+ r = submit_and_sync();
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* verify the dst bo is filled with DMA_DATA_BYTE */
+ CU_ASSERT_EQUAL(memcmp(dst_bo_cpu, reference_data, DMA_SIZE) == 0, true);
+
+ r = amdgpu_bo_cpu_unmap(dst_bo.buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = free_bo(src_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = free_bo(dst_bo);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cp_dma_p2p(uint32_t src_heap, uint32_t dst_heap) {
+ int r;
+ struct amdgpu_cp_dma_bo exported_bo = {0};
+ int dma_buf_fd;
+ int dma_buf_fd_dup;
+ struct amdgpu_cp_dma_bo src_bo = {0};
+ struct amdgpu_cp_dma_bo imported_dst_bo = {0};
+ void *exported_bo_cpu;
+ void *src_bo_cpu;
+
+ /* allocate a bo on the peer device and export it to dma-buf */
+ r = allocate_bo_and_va(peer_exporting_device_handle, DMA_SIZE, 4096,
+ src_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &exported_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* map the exported bo and clear its content to 0 */
+ _Static_assert(DMA_DATA_BYTE != 0, "Initialization data should be different from DMA data!");
+ r = amdgpu_bo_cpu_map(exported_bo.buf_handle, (void **)&exported_bo_cpu);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(exported_bo_cpu, 0, DMA_SIZE);
+
+ r = amdgpu_bo_export(exported_bo.buf_handle,
+ amdgpu_bo_handle_type_dma_buf_fd, (uint32_t*)&dma_buf_fd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ // According to amdgpu_drm:
+ // "Buffer must be "imported" only using new "fd"
+ // (different from one used by "exporter")"
+ dma_buf_fd_dup = dup(dma_buf_fd);
+ r = close(dma_buf_fd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* import the dma-buf to the executing device, imported bo is the DMA destination */
+ r = import_dma_buf_to_bo(
+ executing_device_handle, dma_buf_fd_dup, &imported_dst_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = close(dma_buf_fd_dup);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* allocate the src bo and set its content to DMA_DATA_BYTE */
+ r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096,
+ dst_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &src_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(src_bo.buf_handle, (void **)&src_bo_cpu);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(src_bo_cpu, DMA_DATA_BYTE, DMA_SIZE);
+
+ r = amdgpu_bo_cpu_unmap(src_bo.buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* record CP DMA command and dispatch the command */
+ cp_dma_cmd(src_bo, imported_dst_bo);
+
+ r = submit_and_sync();
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* verify the bo from the peer device is filled with DMA_DATA_BYTE */
+ CU_ASSERT_EQUAL(memcmp(exported_bo_cpu, reference_data, DMA_SIZE) == 0, true);
+
+ r = amdgpu_bo_cpu_unmap(exported_bo.buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = free_bo(exported_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = free_bo(imported_dst_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = free_bo(src_bo);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cp_dma_host_to_vram(void) {
+ amdgpu_cp_dma(AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_DOMAIN_VRAM);
+}
+
+static void amdgpu_cp_dma_vram_to_host(void) {
+ amdgpu_cp_dma(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_GTT);
+}
+
+static void amdgpu_cp_dma_p2p_vram_to_vram(void) {
+ amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_VRAM);
+}
+
+static void amdgpu_cp_dma_p2p_host_to_vram(void) {
+ amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_DOMAIN_VRAM);
+}
+
+static void amdgpu_cp_dma_p2p_vram_to_host(void) {
+ amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_GTT);
+}
+
+int suite_cp_dma_tests_init() {
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0],
+ &executing_device_major_version,
+ &executing_device_minor_version,
+ &executing_device_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_cs_ctx_create(executing_device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(executing_device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_handle, (void**)&ib_cpu,
+ &ib_mc_address, &ib_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ if (do_p2p) {
+ r = amdgpu_device_initialize(drm_amdgpu[1],
+ &peer_exporting_device_major_version,
+ &peer_exporting_device_minor_version,
+ &peer_exporting_device_handle);
+
+ if (r)
+ return CUE_SINIT_FAILED;
+ }
+
+ reference_data = (uint8_t*)malloc(DMA_SIZE);
+ if (!reference_data)
+ return CUE_SINIT_FAILED;
+ memset(reference_data, DMA_DATA_BYTE, DMA_SIZE);
+
+ return CUE_SUCCESS;
+}
+
+int suite_cp_dma_tests_clean() {
+ int r;
+
+ free(reference_data);
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+ ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(executing_device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ if (do_p2p) {
+ r = amdgpu_device_deinitialize(peer_exporting_device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+ }
+
+ return CUE_SUCCESS;
+}
+
+CU_BOOL suite_cp_dma_tests_enable(void) {
+ int r = 0;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0],
+ &executing_device_major_version,
+ &executing_device_minor_version,
+ &executing_device_handle))
+ return CU_FALSE;
+
+ if (!(executing_device_handle->info.family_id >= AMDGPU_FAMILY_AI &&
+ executing_device_handle->info.family_id <= AMDGPU_FAMILY_NV)) {
+ printf("Testing device has ASIC that is not supported by CP-DMA test suite!\n");
+ return CU_FALSE;
+ }
+
+ if (amdgpu_device_deinitialize(executing_device_handle))
+ return CU_FALSE;
+
+ if (drm_amdgpu[1] >= 0) {
+ r = amdgpu_device_initialize(drm_amdgpu[1],
+ &peer_exporting_device_major_version,
+ &peer_exporting_device_minor_version,
+ &peer_exporting_device_handle);
+
+ if (r == 0 && (peer_exporting_device_handle->info.family_id >= AMDGPU_FAMILY_AI &&
+ peer_exporting_device_handle->info.family_id <= AMDGPU_FAMILY_NV)) {
+ do_p2p = true;
+ }
+
+ if (r == 0 && amdgpu_device_deinitialize(peer_exporting_device_handle) != 0) {
+ printf("Deinitialize peer_exporting_device_handle failed!\n");
+ return CU_FALSE;
+ }
+ }
+
+ if (!do_p2p) {
+ amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write VRAM to VRAM", CU_FALSE);
+ amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write Host to VRAM", CU_FALSE);
+ amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write VRAM to Host", CU_FALSE);
+ printf("Peer device is not opened or has ASIC not supported by the suite, skip all Peer to Peer tests.\n");
+ }
+
+ return CU_TRUE;
+}
diff --git a/tests/amdgpu/cs_tests.c b/tests/amdgpu/cs_tests.c
new file mode 100644
index 0000000..f509678
--- /dev/null
+++ b/tests/amdgpu/cs_tests.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "decode_messages.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#define IB_SIZE 4096
+#define MAX_RESOURCES 16
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+static amdgpu_va_handle ib_va_handle;
+
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static void amdgpu_cs_uvd_create(void);
+static void amdgpu_cs_uvd_decode(void);
+static void amdgpu_cs_uvd_destroy(void);
+
+CU_TestInfo cs_tests[] = {
+ { "UVD create", amdgpu_cs_uvd_create },
+ { "UVD decode", amdgpu_cs_uvd_decode },
+ { "UVD destroy", amdgpu_cs_uvd_destroy },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_cs_tests_enable(void)
+{
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ family_id = device_handle->info.family_id;
+ chip_id = device_handle->info.chip_external_rev;
+ chip_rev = device_handle->info.chip_rev;
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+
+ if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI ||
+ asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) {
+ printf("\n\nThe ASIC NOT support UVD, suite disabled\n");
+ return CU_FALSE;
+ }
+
+ return CU_TRUE;
+}
+
+int suite_cs_tests_init(void)
+{
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ amdgpu_va_handle ib_result_va_handle;
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+
+ return CUE_SINIT_FAILED;
+ }
+
+ family_id = device_handle->info.family_id;
+ /* VI asic POLARIS10/11 have specific external_rev_id */
+ chip_rev = device_handle->info.chip_rev;
+ chip_id = device_handle->info.chip_external_rev;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address,
+ &ib_result_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ ib_handle = ib_result_handle;
+ ib_mc_address = ib_result_mc_address;
+ ib_cpu = ib_result_cpu;
+ ib_va_handle = ib_result_va_handle;
+
+ return CUE_SUCCESS;
+}
+
+int suite_cs_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+ ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ int r;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = ndw;
+
+ ibs_request.ip_type = ip;
+
+ r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+ NULL, &ibs_request.resources);
+ if (r)
+ return r;
+
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void uvd_cmd(uint64_t addr, unsigned cmd, int *idx)
+{
+ ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC4 : 0x81C4;
+ ib_cpu[(*idx)++] = addr;
+ ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC5 : 0x81C5;
+ ib_cpu[(*idx)++] = addr >> 32;
+ ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC3 : 0x81C3;
+ ib_cpu[(*idx)++] = cmd << 1;
+}
+
+static void amdgpu_cs_uvd_create(void)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ uint64_t va = 0;
+ amdgpu_va_handle va_handle;
+ void *msg;
+ int i, r;
+
+ req.alloc_size = 4*1024;
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ 4096, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, 4096, va, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(buf_handle, &msg);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memcpy(msg, uvd_create_msg, sizeof(uvd_create_msg));
+
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ ((uint8_t*)msg)[0x10] = 7;
+ /* chip beyond polaris 10/11 */
+ if ((family_id == AMDGPU_FAMILY_AI) ||
+ (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+ chip_id == chip_rev+0x64)) {
+ /* dpb size */
+ ((uint8_t*)msg)[0x28] = 0x00;
+ ((uint8_t*)msg)[0x29] = 0x94;
+ ((uint8_t*)msg)[0x2A] = 0x6B;
+ ((uint8_t*)msg)[0x2B] = 0x00;
+ }
+ }
+
+ r = amdgpu_bo_cpu_unmap(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ num_resources = 0;
+ resources[num_resources++] = buf_handle;
+ resources[num_resources++] = ib_handle;
+
+ i = 0;
+ uvd_cmd(va, 0x0, &i);
+ for (; i % 16; ++i)
+ ib_cpu[i] = 0x80000000;
+
+ r = submit(i, AMDGPU_HW_IP_UVD);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, 4096, va, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_uvd_decode(void)
+{
+ const unsigned dpb_size = 15923584, dt_size = 737280;
+ uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr;
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ uint64_t sum;
+ uint8_t *ptr;
+ int i, r;
+
+ req.alloc_size = 4*1024; /* msg */
+ req.alloc_size += 4*1024; /* fb */
+ if (family_id >= AMDGPU_FAMILY_VI)
+ req.alloc_size += 4096; /*it_scaling_table*/
+ req.alloc_size += ALIGN(sizeof(uvd_bitstream), 4*1024);
+ req.alloc_size += ALIGN(dpb_size, 4*1024);
+ req.alloc_size += ALIGN(dt_size, 4*1024);
+
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(buf_handle, (void **)&ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memcpy(ptr, uvd_decode_msg, sizeof(uvd_decode_msg));
+ memcpy(ptr + sizeof(uvd_decode_msg), avc_decode_msg, sizeof(avc_decode_msg));
+
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ ptr[0x10] = 7;
+ ptr[0x98] = 0x00;
+ ptr[0x99] = 0x02;
+ /* chip beyond polaris10/11 */
+ if ((family_id == AMDGPU_FAMILY_AI) ||
+ (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+ chip_id == chip_rev+0x64)) {
+ /* dpb size */
+ ptr[0x24] = 0x00;
+ ptr[0x25] = 0x94;
+ ptr[0x26] = 0x6B;
+ ptr[0x27] = 0x00;
+ /*ctx size */
+ ptr[0x2C] = 0x00;
+ ptr[0x2D] = 0xAF;
+ ptr[0x2E] = 0x50;
+ ptr[0x2F] = 0x00;
+ }
+ }
+
+ ptr += 4*1024;
+ memset(ptr, 0, 4*1024);
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ ptr += 4*1024;
+ memcpy(ptr, uvd_it_scaling_table, sizeof(uvd_it_scaling_table));
+ }
+
+ ptr += 4*1024;
+ memcpy(ptr, uvd_bitstream, sizeof(uvd_bitstream));
+
+ ptr += ALIGN(sizeof(uvd_bitstream), 4*1024);
+ memset(ptr, 0, dpb_size);
+
+ ptr += ALIGN(dpb_size, 4*1024);
+ memset(ptr, 0, dt_size);
+
+ num_resources = 0;
+ resources[num_resources++] = buf_handle;
+ resources[num_resources++] = ib_handle;
+
+ msg_addr = va;
+ fb_addr = msg_addr + 4*1024;
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ it_addr = fb_addr + 4*1024;
+ bs_addr = it_addr + 4*1024;
+ } else
+ bs_addr = fb_addr + 4*1024;
+ dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
+
+ ctx_addr = 0;
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ if ((family_id == AMDGPU_FAMILY_AI) ||
+ (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+ chip_id == chip_rev+0x64)) {
+ ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
+ }
+ }
+
+ dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
+
+ i = 0;
+ uvd_cmd(msg_addr, 0x0, &i);
+ uvd_cmd(dpb_addr, 0x1, &i);
+ uvd_cmd(dt_addr, 0x2, &i);
+ uvd_cmd(fb_addr, 0x3, &i);
+ uvd_cmd(bs_addr, 0x100, &i);
+
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ uvd_cmd(it_addr, 0x204, &i);
+ if ((family_id == AMDGPU_FAMILY_AI) ||
+ (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+ chip_id == chip_rev+0x64))
+ uvd_cmd(ctx_addr, 0x206, &i);
+ }
+
+ ib_cpu[i++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC6 : 0x81C6;
+ ib_cpu[i++] = 0x1;
+ for (; i % 16; ++i)
+ ib_cpu[i] = 0x80000000;
+
+ r = submit(i, AMDGPU_HW_IP_UVD);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* TODO: use a real CRC32 */
+ for (i = 0, sum = 0; i < dt_size; ++i)
+ sum += ptr[i];
+ CU_ASSERT_EQUAL(sum, SUM_DECODE);
+
+ r = amdgpu_bo_cpu_unmap(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_uvd_destroy(void)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ void *msg;
+ int i, r;
+
+ req.alloc_size = 4*1024;
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(buf_handle, &msg);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memcpy(msg, uvd_destroy_msg, sizeof(uvd_destroy_msg));
+ if (family_id >= AMDGPU_FAMILY_VI)
+ ((uint8_t*)msg)[0x10] = 7;
+
+ r = amdgpu_bo_cpu_unmap(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ num_resources = 0;
+ resources[num_resources++] = buf_handle;
+ resources[num_resources++] = ib_handle;
+
+ i = 0;
+ uvd_cmd(va, 0x0, &i);
+ for (; i % 16; ++i)
+ ib_cpu[i] = 0x80000000;
+
+ r = submit(i, AMDGPU_HW_IP_UVD);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c
new file mode 100644
index 0000000..2928233
--- /dev/null
+++ b/tests/amdgpu/deadlock_tests.c
@@ -0,0 +1,696 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#include <pthread.h>
+
+
+/*
+ * This defines the delay in MS after which memory location designated for
+ * compression against reference value is written to, unblocking command
+ * processor
+ */
+#define WRITE_MEM_ADDRESS_DELAY_MS 100
+
+#define PACKET_TYPE3 3
+
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
+ (((op) & 0xFF) << 8) | \
+ ((n) & 0x3FFF) << 16)
+
+#define PACKET3_WAIT_REG_MEM 0x3C
+#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0)
+ /* 0 - always
+ * 1 - <
+ * 2 - <=
+ * 3 - ==
+ * 4 - !=
+ * 5 - >=
+ * 6 - >
+ */
+#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4)
+ /* 0 - reg
+ * 1 - mem
+ */
+#define WAIT_REG_MEM_OPERATION(x) ((x) << 6)
+ /* 0 - wait_reg_mem
+ * 1 - wr_wait_wr_reg
+ */
+#define WAIT_REG_MEM_ENGINE(x) ((x) << 8)
+ /* 0 - me
+ * 1 - pfp
+ */
+
+#define PACKET3_WRITE_DATA 0x37
+#define WRITE_DATA_DST_SEL(x) ((x) << 8)
+ /* 0 - register
+ * 1 - memory (sync - via GRBM)
+ * 2 - gl2
+ * 3 - gds
+ * 4 - reserved
+ * 5 - memory (async - direct)
+ */
+#define WR_ONE_ADDR (1 << 16)
+#define WR_CONFIRM (1 << 20)
+#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25)
+ /* 0 - LRU
+ * 1 - Stream
+ */
+#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
+ /* 0 - me
+ * 1 - pfp
+ * 2 - ce
+ */
+
+#define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x54f
+
+#define SDMA_PKT_HEADER_OP(x) (x & 0xff)
+#define SDMA_OP_POLL_REGMEM 8
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+
+static pthread_t stress_thread;
+static uint32_t *ptr;
+
+static uint32_t family_id;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+
+int use_uc_mtype = 0;
+
+static void amdgpu_deadlock_helper(unsigned ip_type);
+static void amdgpu_deadlock_gfx(void);
+static void amdgpu_deadlock_compute(void);
+static void amdgpu_illegal_reg_access();
+static void amdgpu_illegal_mem_access();
+static void amdgpu_deadlock_sdma(void);
+static void amdgpu_dispatch_hang_gfx(void);
+static void amdgpu_dispatch_hang_compute(void);
+static void amdgpu_dispatch_hang_slow_gfx(void);
+static void amdgpu_dispatch_hang_slow_compute(void);
+static void amdgpu_draw_hang_gfx(void);
+static void amdgpu_draw_hang_slow_gfx(void);
+static void amdgpu_hang_sdma(void);
+static void amdgpu_hang_slow_sdma(void);
+
+CU_BOOL suite_deadlock_tests_enable(void)
+{
+ CU_BOOL enable = CU_TRUE;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ family_id = device_handle->info.family_id;
+ chip_id = device_handle->info.chip_external_rev;
+ chip_rev = device_handle->info.chip_rev;
+
+ /*
+ * Only enable for ASICs supporting GPU reset and for which it's enabled
+ * by default (currently GFX8+ dGPUS and gfx9+ APUs). Note that Raven1
+ * did not support GPU reset, but newer variants do.
+ */
+ if (family_id == AMDGPU_FAMILY_SI ||
+ family_id == AMDGPU_FAMILY_KV ||
+ family_id == AMDGPU_FAMILY_CZ ||
+ family_id == AMDGPU_FAMILY_RV) {
+ printf("\n\nGPU reset is not enabled for the ASIC, deadlock suite disabled\n");
+ enable = CU_FALSE;
+ }
+
+ if (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) {
+ if (amdgpu_set_test_active("Deadlock Tests",
+ "gfx ring block test (set amdgpu.lockup_timeout=50)",
+ CU_FALSE))
+ fprintf(stderr, "test deactivation failed - %s\n",
+ CU_get_error_msg());
+ }
+
+ if (device_handle->info.family_id >= AMDGPU_FAMILY_AI)
+ use_uc_mtype = 1;
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ return enable;
+}
+
+int suite_deadlock_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+ return CUE_SINIT_FAILED;
+ }
+
+ return CUE_SUCCESS;
+}
+
+int suite_deadlock_tests_clean(void)
+{
+ int r = amdgpu_device_deinitialize(device_handle);
+
+ if (r == 0)
+ return CUE_SUCCESS;
+ else
+ return CUE_SCLEAN_FAILED;
+}
+
+
+CU_TestInfo deadlock_tests[] = {
+ { "gfx ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_gfx },
+ { "compute ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_compute },
+ { "sdma ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_sdma },
+ { "illegal reg access test", amdgpu_illegal_reg_access },
+ { "illegal mem access test (set amdgpu.vm_fault_stop=2)", amdgpu_illegal_mem_access },
+ { "gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_gfx },
+ { "compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_compute },
+ { "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_slow_gfx },
+ { "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_slow_compute },
+ { "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", amdgpu_draw_hang_gfx },
+ { "gfx ring slow bad draw test (set amdgpu.lockup_timeout=50)", amdgpu_draw_hang_slow_gfx },
+ { "sdma ring corrupted header test (set amdgpu.lockup_timeout=50)", amdgpu_hang_sdma },
+ { "sdma ring slow linear copy test (set amdgpu.lockup_timeout=50)", amdgpu_hang_slow_sdma },
+ CU_TEST_INFO_NULL,
+};
+
+static void *write_mem_address(void *data)
+{
+ int i;
+
+ /* useconds_t range is [0, 1,000,000] so use loop for waits > 1s */
+ for (i = 0; i < WRITE_MEM_ADDRESS_DELAY_MS; i++)
+ usleep(1000);
+
+ ptr[256] = 0x1;
+
+ return 0;
+}
+
+static void amdgpu_deadlock_gfx(void)
+{
+ amdgpu_deadlock_helper(AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_deadlock_compute(void)
+{
+ amdgpu_deadlock_helper(AMDGPU_HW_IP_COMPUTE);
+}
+
+static void amdgpu_deadlock_helper(unsigned ip_type)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t expired;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+
+ r = pthread_create(&stress_thread, NULL, write_mem_address, NULL);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, use_uc_mtype ? AMDGPU_VM_MTYPE_UC : 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+
+ ptr[0] = PACKET3(PACKET3_WAIT_REG_MEM, 5);
+ ptr[1] = (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+ WAIT_REG_MEM_FUNCTION(4) | /* != */
+ WAIT_REG_MEM_ENGINE(0)); /* me */
+ ptr[2] = (ib_result_mc_address + 256*4) & 0xfffffffc;
+ ptr[3] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff;
+ ptr[4] = 0x00000000; /* reference value */
+ ptr[5] = 0xffffffff; /* and mask */
+ ptr[6] = 0x00000004; /* poll interval */
+
+ for (i = 7; i < 16; ++i)
+ ptr[i] = 0xffff1000;
+
+
+ ptr[256] = 0x0; /* the memory we wait on to change */
+
+
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = ip_type;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+ for (i = 0; i < 200; i++) {
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ }
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ pthread_join(stress_thread, NULL);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_deadlock_sdma(void)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t expired;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ struct drm_amdgpu_info_hw_ip info;
+ uint32_t ring_id;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_DMA, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) {
+ r = pthread_create(&stress_thread, NULL, write_mem_address, NULL);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, use_uc_mtype ? AMDGPU_VM_MTYPE_UC : 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ i = 0;
+
+ ptr[i++] = SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
+ (0 << 26) | /* WAIT_REG_MEM */
+ (4 << 28) | /* != */
+ (1 << 31); /* memory */
+ ptr[i++] = (ib_result_mc_address + 256*4) & 0xfffffffc;
+ ptr[i++] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff;
+ ptr[i++] = 0x00000000; /* reference value */
+ ptr[i++] = 0xffffffff; /* and mask */
+ ptr[i++] = 4 | /* poll interval */
+ (0xfff << 16); /* retry count */
+
+ for (; i < 16; i++)
+ ptr[i] = 0;
+
+ ptr[256] = 0x0; /* the memory we wait on to change */
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_DMA;
+ ibs_request.ring = ring_id;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ for (i = 0; i < 200; i++) {
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ }
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_DMA;
+ fence_status.ip_instance = 0;
+ fence_status.ring = ring_id;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ pthread_join(stress_thread, NULL);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void bad_access_helper(int reg_access)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t expired;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ i = 0;
+
+ ptr[i++] = PACKET3(PACKET3_WRITE_DATA, 3);
+ ptr[i++] = (reg_access ? WRITE_DATA_DST_SEL(0) : WRITE_DATA_DST_SEL(5))| WR_CONFIRM;
+ ptr[i++] = reg_access ? mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR : 0xdeadbee0;
+ ptr[i++] = 0;
+ ptr[i++] = 0xdeadbeef;
+
+ for (; i < 16; ++i)
+ ptr[i] = 0xffff1000;
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_GFX;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_illegal_reg_access()
+{
+ bad_access_helper(1);
+}
+
+static void amdgpu_illegal_mem_access()
+{
+ bad_access_helper(0);
+}
+
+static void amdgpu_dispatch_hang_gfx(void)
+{
+ amdgpu_test_dispatch_hang_helper(device_handle, AMDGPU_HW_IP_GFX);
+}
+static void amdgpu_dispatch_hang_compute(void)
+{
+ amdgpu_test_dispatch_hang_helper(device_handle, AMDGPU_HW_IP_COMPUTE);
+}
+static void amdgpu_dispatch_hang_slow_gfx(void)
+{
+ amdgpu_test_dispatch_hang_slow_helper(device_handle, AMDGPU_HW_IP_GFX);
+}
+static void amdgpu_dispatch_hang_slow_compute(void)
+{
+ amdgpu_test_dispatch_hang_slow_helper(device_handle, AMDGPU_HW_IP_COMPUTE);
+}
+static void amdgpu_draw_hang_gfx(void)
+{
+ amdgpu_test_draw_hang_helper(device_handle);
+}
+static void amdgpu_draw_hang_slow_gfx(void)
+{
+ amdgpu_test_draw_hang_slow_helper(device_handle);
+}
+
+#define DMA_CORRUPTED_HEADER_HANG 1
+#define DMA_SLOW_LINEARCOPY_HANG 2
+
+static void amdgpu_hang_sdma_helper(unsigned hang_type)
+{
+ const int sdma_write_length = 1024;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ amdgpu_bo_handle bo1, bo2;
+ amdgpu_bo_handle resources[3];
+ amdgpu_bo_list_handle bo_list;
+ void *ib_result_cpu;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_fence fence_status;
+ uint64_t bo1_mc, bo2_mc;
+ uint64_t ib_result_mc_address;
+ volatile unsigned char *bo1_cpu, *bo2_cpu;
+ amdgpu_va_handle bo1_va_handle, bo2_va_handle;
+ amdgpu_va_handle va_handle;
+ struct drm_amdgpu_info_hw_ip hw_ip_info;
+ int i, j, r;
+ uint32_t expired, ib_size;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_DMA, 0, &hw_ip_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (hang_type == DMA_CORRUPTED_HEADER_HANG)
+ ib_size = 4096;
+ else
+ ib_size = 4096 * 0x20000;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, ib_size, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ 0, &bo1,
+ (void**)&bo1_cpu, &bo1_mc,
+ &bo1_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* set bo1 */
+ memset((void*)bo1_cpu, 0xaa, sdma_write_length);
+
+ /* allocate UC bo2 for sDMA use */
+ r = amdgpu_bo_alloc_and_map(device_handle,
+ sdma_write_length, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ 0, &bo2,
+ (void**)&bo2_cpu, &bo2_mc,
+ &bo2_va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* clear bo2 */
+ memset((void*)bo2_cpu, 0, sdma_write_length);
+
+ resources[0] = bo1;
+ resources[1] = bo2;
+ resources[2] = ib_result_handle;
+ r = amdgpu_bo_list_create(device_handle, 3,
+ resources, NULL, &bo_list);
+
+ /* fulfill PM4: with bad copy linear header */
+ ptr = ib_result_cpu;
+ i = 0;
+ if (hang_type == DMA_CORRUPTED_HEADER_HANG) {
+ ptr[i++] = 0x23decd3d;
+ ptr[i++] = sdma_write_length - 1;
+ ptr[i++] = 0;
+ ptr[i++] = 0xffffffff & bo1_mc;
+ ptr[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ ptr[i++] = 0xffffffff & bo2_mc;
+ ptr[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ } else {
+ for (j = 1; j < 0x20000; j++) {
+ ptr[i++] = 0x1;
+ ptr[i++] = sdma_write_length - 1;
+ ptr[i++] = 0;
+ ptr[i++] = 0xffffffff & bo1_mc;
+ ptr[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ ptr[i++] = 0xffffffff & bo2_mc;
+ ptr[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ ptr[i++] = 0x1;
+ ptr[i++] = sdma_write_length - 1;
+ ptr[i++] = 0;
+ ptr[i++] = 0xffffffff & bo2_mc;
+ ptr[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+ ptr[i++] = 0xffffffff & bo1_mc;
+ ptr[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+ }
+ }
+
+ /* exec command */
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = i;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_DMA;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = AMDGPU_HW_IP_DMA;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
+ sdma_write_length);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* end of test */
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_hang_sdma(void)
+{
+ amdgpu_hang_sdma_helper(DMA_CORRUPTED_HEADER_HANG);
+}
+static void amdgpu_hang_slow_sdma(void)
+{
+ amdgpu_hang_sdma_helper(DMA_SLOW_LINEARCOPY_HANG);
+}
diff --git a/tests/amdgpu/decode_messages.h b/tests/amdgpu/decode_messages.h
new file mode 100644
index 0000000..218cd77
--- /dev/null
+++ b/tests/amdgpu/decode_messages.h
@@ -0,0 +1,881 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _DECODE_MESSAGES_H_
+#define _DECODE_MESSAGES_H_
+
+#define SUM_DECODE 0x20345d8
+
+static const uint8_t uvd_create_msg[] = {
+ 0xe4,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x03,0x00,0x00,
+ 0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xf9,0xf2,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t uvd_bitstream[] ={
+ 0x00,0x00,0x01,0x25,0xb8,0x20,0x20,0x21,0x44,0xc5,0x00,0x01,0x57,0x9b,0xef,0xbe,
+ 0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,
+ 0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,
+ 0xbe,0xfb,0xef,0xbe,0xff,0x87,0xff,0xc2,0x58,0x0e,0x00,0x02,0x02,0xa0,0x00,0x20,
+ 0x3a,0x00,0x0d,0x00,0x01,0x01,0xa4,0xcb,0x94,0x73,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xaf,0x00,0x00,0x01,0x25,0x00,0xa2,0xb8,0x20,0x20,0x21,0x44,
+ 0xc5,0x00,0x01,0x57,0x9b,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,
+ 0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,
+ 0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xff,0x87,0xff,0xc2,0x58,
+ 0x0e,0x00,0x02,0x02,0xa0,0x00,0x20,0x3a,0x00,0x0d,0x00,0x01,0x01,0xa4,0xcb,0x94,
+ 0x73,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xaf,0x00,0x00,0x01,0x25,
+ 0x00,0x51,0x2e,0x08,0x08,0x08,0x51,0x31,0x40,0x00,0x55,0xe6,0xfb,0xef,0xbe,0xfb,
+ 0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,
+ 0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,
+ 0xfb,0xef,0xbf,0xe1,0xff,0xf0,0x96,0x03,0x80,0x00,0x80,0xa8,0x00,0x08,0x0e,0x80,
+ 0x03,0x40,0x00,0x40,0x69,0x32,0xe5,0x1c,0xfa,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xc0,0x00,0x00,0x01,0x25,0x00,0x79,0xae,0x08,0x08,0x08,0x51,0x31,
+ 0x40,0x00,0x55,0xe6,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,
+ 0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,
+ 0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbf,0xe1,0xff,0xf0,0x96,0x03,
+ 0x80,0x00,0x80,0xa8,0x00,0x08,0x0e,0x80,0x03,0x40,0x00,0x40,0x69,0x32,0xe5,0x1c,
+ 0xfa,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xc0,0x00,0x00,0x01,0x25,
+ 0x00,0x28,0x8b,0x82,0x02,0x02,0x14,0x4c,0x50,0x00,0x15,0x79,0xbe,0xfb,0xef,0xbe,
+ 0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,
+ 0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,0xbe,0xfb,0xef,
+ 0xbe,0xfb,0xef,0xf8,0x7f,0xfc,0x25,0x80,0xe0,0x00,0x20,0x2a,0x00,0x02,0x03,0xa0,
+ 0x00,0xd0,0x00,0x10,0x1a,0x4c,0xb9,0x47,0x3e,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,
+ 0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,
+ 0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,0xeb,0xae,0xba,
+ 0xeb,0xae,0xba,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t uvd_decode_msg[] = {
+ 0xe4,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x44,0x40,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xf9,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x80,0x07,0x00,0x00,0x60,0x09,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t avc_decode_msg[] = {
+ 0x02,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x88,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x01,0x00,0x03,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t uvd_destroy_msg[] = {
+ 0xe4,0x0d,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t uvd_it_scaling_table[] = {
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+};
+
+static const uint8_t vcn_dec_create_msg[] = {
+ 0x28,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,
+};
+
+static const uint8_t vcn_dec_decode_msg[] = {
+ 0x28,0x00,0x00,0x00,0x90,0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x44,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x38,0x00,0x00,0x00,
+ 0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0xec,0x00,0x00,0x00,
+ 0x5c,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,0x80,0x05,0x00,0x00,0x00,0x94,0x6b,0x00,
+ 0x96,0x4e,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x50,0x00,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x80,0x07,0x00,0x00,0x60,0x09,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t vcn_dec_destroy_msg[] = {
+ 0x28,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t feedback_msg[] = {
+ 0x2c,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t jpeg_bitstream[] = {
+ 0xFF, 0xD8, 0xFF, 0xDB, 0x01, 0x06, 0x00, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08,
+ 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0C, 0x0C, 0x0B,
+ 0x0B, 0x0E, 0x0E, 0x0E, 0x11, 0x11, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
+ 0x03, 0x00, 0x22, 0x00, 0x01, 0x11, 0x00, 0x02, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00,
+ 0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00, 0x9F, 0xC0, 0x07, 0xFF, 0xD9, 0xFF, 0xD9,
+};
+
+#endif /* _DECODE_MESSAGES_H_ */
diff --git a/tests/amdgpu/frame.h b/tests/amdgpu/frame.h
new file mode 100644
index 0000000..335401c
--- /dev/null
+++ b/tests/amdgpu/frame.h
@@ -0,0 +1,1949 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _frame_h_
+#define _frame_h_
+
+static const uint8_t frame[] = {
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
+ 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+ 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
+ 0x6a, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0xcd, 0x13, 0x67, 0xa2, 0x2b, 0xa5, 0x29,
+ 0x5d, 0xcb, 0xd5, 0xa4, 0x27, 0x2a, 0x62, 0x20, 0x70, 0x78, 0x6d, 0xe9, 0x1e, 0xeb, 0x25, 0xa6,
+ 0x62, 0x29, 0x13, 0xa4, 0xab, 0x29, 0x12, 0x35, 0x4c, 0x77, 0x73, 0x42, 0xe0, 0xd0, 0x62, 0xa5,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xad, 0x17, 0x5c, 0xc3, 0xdc, 0x41, 0x1e, 0xbe,
+ 0x4e, 0x90, 0xab, 0xbf, 0x86, 0x33, 0x1f, 0xeb, 0x15, 0xac, 0x64, 0x38, 0xd0, 0x44, 0xe6, 0x3e,
+ 0xe9, 0x50, 0x8f, 0x32, 0xbd, 0x18, 0x7a, 0x4a, 0xaa, 0x12, 0x61, 0x91, 0x62, 0xaa, 0xd9, 0x6e,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa4, 0xc6, 0x37, 0x7f, 0x6e, 0x6a, 0xa6, 0xd0,
+ 0xd6, 0x84, 0x51, 0x96, 0x13, 0xd6, 0xc4, 0x3e, 0x60, 0x36, 0x62, 0xbd, 0xd9, 0xe2, 0x78, 0xe3,
+ 0x83, 0x99, 0xda, 0x8e, 0x31, 0xd4, 0x64, 0x1f, 0xc7, 0x1b, 0xbe, 0xaa, 0x76, 0x22, 0x6b, 0x6b,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x69, 0xb0, 0x8a, 0xcc, 0x74, 0x17, 0x4c,
+ 0x98, 0xe1, 0xc1, 0xaa, 0x19, 0xe5, 0xc3, 0xce, 0x69, 0xb1, 0xe5, 0x62, 0xe7, 0x2f, 0xe0, 0xc4,
+ 0xe8, 0x25, 0x84, 0xe8, 0x5f, 0x84, 0xb0, 0xab, 0x40, 0x3b, 0x9e, 0x95, 0x27, 0x44, 0x1e, 0x7a,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe4, 0x77, 0xc8, 0x7d, 0xd2, 0x6e, 0xe5, 0x1f,
+ 0x8d, 0x33, 0x7c, 0x8e, 0x90, 0xbe, 0x1f, 0xb9, 0x5b, 0xc1, 0x5d, 0xdf, 0xc6, 0x23, 0x25, 0xc9,
+ 0x25, 0xb1, 0x13, 0x5e, 0x7c, 0x93, 0x67, 0xdf, 0x9b, 0x8f, 0x71, 0xb8, 0x34, 0xa4, 0x6b, 0xa1,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0xb8, 0x74, 0xbb, 0xa5, 0x3b, 0x40, 0x12,
+ 0x2b, 0x14, 0x43, 0x36, 0x93, 0x26, 0xe8, 0xda, 0x22, 0xcf, 0xc2, 0x69, 0xb0, 0xd0, 0x7a, 0xb1,
+ 0xc8, 0x2a, 0x92, 0x27, 0x94, 0x19, 0x97, 0xb3, 0x92, 0x65, 0xc5, 0x8d, 0xe8, 0xa6, 0xd0, 0x9b,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x88, 0x92, 0x2e, 0x4b, 0x64, 0xda, 0xce, 0x16,
+ 0x67, 0x70, 0xeb, 0x5c, 0x86, 0x6b, 0xc2, 0xe4, 0xbd, 0xdc, 0x46, 0x28, 0xd8, 0xd4, 0x19, 0x69,
+ 0xd5, 0xcf, 0x8e, 0x89, 0x40, 0x96, 0x7b, 0xb2, 0xc9, 0x5e, 0x18, 0xc6, 0xd6, 0xd2, 0x3c, 0x4a,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x50, 0x88, 0xb8, 0x9a, 0x8c, 0xc8, 0xae,
+ 0xae, 0xcd, 0x63, 0x62, 0xc3, 0x8a, 0x32, 0xb3, 0x5c, 0x1c, 0xa2, 0x55, 0x27, 0x55, 0x87, 0x6b,
+ 0x3e, 0x33, 0xd6, 0x70, 0xd0, 0x59, 0x76, 0xb0, 0xcd, 0x4a, 0x6e, 0x4a, 0xb1, 0xa1, 0x17, 0x24,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc8, 0xb5, 0xe3, 0x7a, 0x17, 0x63, 0x70, 0xca,
+ 0x37, 0xbd, 0x1f, 0x72, 0x5e, 0x2f, 0x7c, 0xb7, 0xd2, 0xcb, 0xa8, 0xa9, 0x13, 0x98, 0x2b, 0x7e,
+ 0x74, 0x3f, 0x94, 0x6f, 0x8c, 0x1a, 0xce, 0x38, 0x61, 0x72, 0xe2, 0x18, 0x4e, 0xac, 0x5c, 0xc3,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x92, 0xd8, 0xb7, 0x88, 0xa8, 0x6e, 0xc5, 0xce,
+ 0x1f, 0x4a, 0x64, 0x3b, 0x1a, 0x21, 0x9f, 0xa6, 0x46, 0xe7, 0x1a, 0xcf, 0xc8, 0x20, 0xc1, 0x20,
+ 0x83, 0xbe, 0x5b, 0x99, 0x4d, 0xd4, 0x5e, 0xb3, 0xc3, 0x4b, 0xab, 0x3e, 0xc7, 0x85, 0xea, 0xc4,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x48, 0xe0, 0x84, 0xa8, 0x1d, 0x81, 0x62,
+ 0x74, 0x67, 0xb0, 0x32, 0x4c, 0x23, 0x56, 0xd0, 0x85, 0x9b, 0x20, 0xca, 0xb4, 0x49, 0xdd, 0xad,
+ 0x1f, 0xab, 0xcf, 0x16, 0x7d, 0xbd, 0x78, 0xb0, 0xd3, 0xa0, 0x5c, 0x50, 0xa1, 0xd7, 0x37, 0xa0,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x55, 0x97, 0xd6, 0x93, 0x6c, 0xd2, 0xa1,
+ 0x94, 0xc2, 0x2c, 0x51, 0x68, 0x34, 0x88, 0xc7, 0x8c, 0x1f, 0x3f, 0x93, 0x68, 0x86, 0xb1, 0xa5,
+ 0xe1, 0x56, 0x89, 0x20, 0xa5, 0xe2, 0x28, 0x9a, 0x11, 0x8f, 0xa4, 0xa7, 0x81, 0x6d, 0xe2, 0x87,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe2, 0x34, 0x79, 0x8d, 0xe2, 0xe1, 0xa3, 0x38,
+ 0x83, 0x3b, 0xb0, 0x7f, 0x4b, 0x2b, 0x44, 0xb7, 0x68, 0x21, 0x85, 0x79, 0x74, 0x8c, 0xbc, 0x65,
+ 0xbb, 0x16, 0xd0, 0x2a, 0xb7, 0x70, 0x13, 0x94, 0xc3, 0x87, 0x23, 0x46, 0x2f, 0xe3, 0xb7, 0xcf,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0xdd, 0x60, 0x5d, 0xc3, 0xd6, 0x75, 0x20,
+ 0x78, 0xbd, 0x49, 0x23, 0xaf, 0x1e, 0xa2, 0x14, 0xca, 0x81, 0x39, 0xbb, 0x19, 0xc2, 0x82, 0xde,
+ 0x68, 0xbe, 0xdb, 0xdd, 0xa4, 0x86, 0x51, 0xe7, 0xad, 0x2b, 0x25, 0xb0, 0xb7, 0x3d, 0xd0, 0xac,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x50, 0xa9, 0x7e, 0x3b, 0xc0, 0x41, 0x9a,
+ 0x6e, 0xd0, 0x8f, 0x4a, 0x21, 0xd1, 0xe1, 0x9f, 0xdb, 0xb6, 0xe2, 0x41, 0x4a, 0x15, 0xb5, 0x95,
+ 0x64, 0x97, 0xd3, 0x42, 0xc5, 0x63, 0xdd, 0xb7, 0x57, 0x6c, 0xc3, 0x54, 0x91, 0x2b, 0xdc, 0x52,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xb2, 0xe1, 0x14, 0x37, 0x92, 0xea, 0xb8, 0xc3,
+ 0x95, 0x4b, 0x31, 0xab, 0x9b, 0xb8, 0x8f, 0xca, 0x66, 0x45, 0xae, 0x71, 0xaf, 0xb8, 0x2b, 0x57,
+ 0x87, 0x17, 0x90, 0x28, 0x98, 0x62, 0x47, 0x2c, 0xeb, 0x92, 0x79, 0x26, 0x52, 0x7d, 0x70, 0x88,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa3, 0x38, 0x7a, 0xe7, 0x7e, 0x27, 0x49, 0xbd,
+ 0xe2, 0xcc, 0x88, 0xe6, 0x36, 0xae, 0xd6, 0x7c, 0x48, 0xe3, 0xe6, 0x7d, 0x11, 0xd4, 0xa0, 0x3e,
+ 0x6e, 0x9d, 0xdb, 0x9b, 0xdc, 0xb0, 0x70, 0xdc, 0x58, 0x5b, 0xda, 0x99, 0x92, 0x65, 0x48, 0x86,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x52, 0x5c, 0x69, 0xd6, 0x8d, 0xb1, 0x5f,
+ 0xa3, 0x1c, 0xe1, 0x1e, 0x78, 0x15, 0x97, 0x9e, 0x44, 0xdf, 0x56, 0x60, 0x38, 0x18, 0x43, 0x1b,
+ 0xc1, 0x91, 0x6e, 0x48, 0x98, 0xe2, 0x19, 0x36, 0x9d, 0x6c, 0x23, 0x5a, 0x97, 0xa4, 0x26, 0x13,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x12, 0x33, 0x7a, 0x68, 0xb2, 0x29, 0x92, 0x81,
+ 0xa0, 0x5a, 0x9e, 0xd5, 0xbd, 0xb7, 0x4f, 0x13, 0x55, 0xb7, 0xe7, 0x73, 0x52, 0x32, 0x21, 0xbf,
+ 0x3a, 0x1b, 0xb1, 0x60, 0x19, 0x5f, 0x77, 0x8b, 0x7c, 0x2a, 0x87, 0x26, 0x82, 0x7f, 0x1d, 0xda,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd6, 0xa3, 0xcd, 0xc3, 0x76, 0x48, 0x21, 0xd8,
+ 0x21, 0xab, 0x86, 0xc2, 0x5f, 0x57, 0xca, 0x7f, 0x38, 0x19, 0x4a, 0x20, 0xd6, 0xe8, 0x51, 0x22,
+ 0x5b, 0xb9, 0x24, 0xb8, 0x85, 0x87, 0x7b, 0xe1, 0x38, 0xbc, 0xdd, 0xad, 0xdd, 0xca, 0x1f, 0xc7,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x4c, 0x1f, 0xdb, 0x80, 0xc3, 0xc0, 0x64,
+ 0xc3, 0x44, 0x9a, 0x1e, 0xd7, 0xd3, 0x1f, 0xa5, 0xba, 0xe3, 0x26, 0xe8, 0x7e, 0x8d, 0x5c, 0xaa,
+ 0xb1, 0x82, 0xc9, 0x3a, 0xd7, 0xd5, 0xb0, 0xd0, 0x45, 0x53, 0x8a, 0x65, 0x78, 0xe4, 0x6c, 0x86,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x7a, 0xc3, 0xdc, 0xbb, 0x6b, 0x44, 0x70,
+ 0x10, 0x86, 0x88, 0x5c, 0x2e, 0xdc, 0x25, 0x4b, 0xb7, 0xb1, 0x88, 0xca, 0x27, 0xb1, 0x83, 0x2c,
+ 0x21, 0x9c, 0xe2, 0xbf, 0xe4, 0x2a, 0x35, 0x19, 0xdc, 0x99, 0xbc, 0x4a, 0x44, 0xd6, 0x4d, 0x75,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x5b, 0x67, 0x73, 0x35, 0xe3, 0x3e, 0xb4,
+ 0x7a, 0x48, 0x13, 0x49, 0x47, 0xac, 0xdc, 0xa8, 0x1a, 0x2b, 0x44, 0xb4, 0xac, 0x99, 0x82, 0x13,
+ 0xc8, 0x7b, 0x7e, 0x9f, 0xeb, 0xab, 0xa2, 0xc8, 0xb2, 0x3e, 0x96, 0xd3, 0x53, 0x13, 0x33, 0x42,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0xdd, 0x42, 0x16, 0x1e, 0x35, 0x6a, 0xa0,
+ 0x5f, 0x93, 0x62, 0xc5, 0x6d, 0xc3, 0xde, 0x84, 0x4b, 0xdf, 0xde, 0xab, 0xbc, 0x31, 0xcd, 0xa1,
+ 0xa6, 0x10, 0x33, 0x48, 0x4c, 0x6f, 0x6a, 0xc0, 0xd8, 0x97, 0x2e, 0xb5, 0x48, 0x74, 0x70, 0x29,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0xd8, 0x5a, 0x9a, 0xc4, 0x1a, 0xd4, 0xa7,
+ 0x73, 0xc3, 0x1f, 0x10, 0x54, 0x95, 0x59, 0x16, 0x53, 0x88, 0x14, 0x30, 0xbd, 0x8c, 0x6f, 0x8d,
+ 0x19, 0x2f, 0xaf, 0x14, 0x88, 0xd6, 0x79, 0x33, 0xd6, 0xd6, 0x22, 0xb6, 0x9a, 0xa0, 0xcb, 0x90,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x93, 0xe1, 0xcc, 0x2f, 0x51, 0x67, 0x8a, 0x17,
+ 0xc3, 0xaa, 0x31, 0x31, 0x8c, 0xb3, 0xaa, 0x98, 0xb6, 0x5d, 0xe2, 0x6e, 0xa1, 0xcf, 0x10, 0xd4,
+ 0x8e, 0x6c, 0x93, 0xbd, 0x8b, 0xe9, 0x4f, 0x55, 0xdc, 0x3c, 0x4a, 0xad, 0x76, 0xcf, 0xea, 0xb7,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x50, 0x85, 0xcf, 0x57, 0x56, 0xa3, 0x1a,
+ 0x49, 0x25, 0xbe, 0x8d, 0x54, 0xa7, 0x78, 0x68, 0x76, 0x53, 0xc7, 0x59, 0x59, 0x66, 0xa1, 0xe4,
+ 0xa0, 0x68, 0x4d, 0x57, 0x85, 0x62, 0x2a, 0x56, 0x68, 0x38, 0x2b, 0xd3, 0xbd, 0x9a, 0xc4, 0xe0,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xb9, 0x40, 0x3e, 0x19, 0x40, 0xab, 0x60, 0xba,
+ 0xbf, 0x68, 0xb8, 0xe7, 0xa3, 0x3c, 0x73, 0x9b, 0x12, 0x68, 0xca, 0x89, 0x3f, 0x45, 0x67, 0xbd,
+ 0xd9, 0x3c, 0xd4, 0xc0, 0xa5, 0x15, 0x98, 0x6a, 0x81, 0x8b, 0x38, 0x6e, 0x27, 0x4c, 0x30, 0x29,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xbd, 0x8a, 0x61, 0x55, 0x4f, 0xb8, 0x2b, 0x6b,
+ 0x3b, 0x19, 0xe2, 0x10, 0x44, 0xc7, 0x51, 0x4a, 0x3a, 0x3b, 0xc3, 0x3e, 0xab, 0xca, 0x84, 0x86,
+ 0xab, 0xe4, 0xa3, 0x5a, 0xa7, 0xaf, 0x4e, 0x80, 0xa0, 0x95, 0x94, 0xde, 0xd6, 0x6e, 0x2f, 0x68,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x36, 0x8c, 0x49, 0x53, 0x7a, 0x50, 0xcb,
+ 0x75, 0x13, 0xcb, 0xab, 0x92, 0x70, 0x14, 0x6a, 0x8d, 0x4c, 0x9c, 0x5c, 0xa5, 0x69, 0x46, 0x1d,
+ 0x99, 0x68, 0x71, 0x72, 0x44, 0x87, 0xe7, 0xa8, 0xe6, 0x99, 0x9d, 0xdb, 0x31, 0x86, 0xc9, 0x9c,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x7d, 0xe8, 0xd0, 0x1c, 0x30, 0x8d, 0x2d,
+ 0x56, 0x5a, 0x1f, 0x1d, 0xc2, 0xa2, 0x7f, 0xcb, 0xd8, 0xbc, 0xcb, 0x6e, 0x12, 0x6e, 0x26, 0x62,
+ 0xeb, 0x48, 0x32, 0x91, 0x7b, 0x59, 0x6d, 0xac, 0xc7, 0x7a, 0x34, 0x55, 0xc3, 0x54, 0x9c, 0xbf,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0xea, 0xd9, 0x1f, 0xbd, 0xc9, 0x84, 0xe8,
+ 0xb1, 0x92, 0xc0, 0x7a, 0xde, 0x74, 0xe8, 0x87, 0xb1, 0xd6, 0x22, 0xc9, 0x19, 0x41, 0x7e, 0x36,
+ 0x62, 0xc6, 0x62, 0x99, 0x93, 0x4d, 0xa9, 0x7c, 0x5c, 0x23, 0x32, 0xe5, 0x5a, 0x4d, 0xbc, 0x87,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92,
+ 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x10, 0x92, 0x5b, 0x51, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22,
+ 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x36, 0x22, 0x80, 0x80, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0,
+ 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0x5a, 0xf0, 0xa5, 0xaf, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e,
+ 0xf0, 0x6e, 0xf0, 0x6e, 0xf0, 0x6e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa5, 0xaf, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde, 0xca, 0xde,
+ 0xca, 0xde, 0xca, 0xde, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x93, 0x48, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10, 0xa6, 0x10,
+ 0xa6, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15,
+ 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0xc6, 0x15, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0xb6, 0xa3, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6, 0xeb, 0xc6,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+};
+#endif
diff --git a/tests/amdgpu/hotunplug_tests.c b/tests/amdgpu/hotunplug_tests.c
new file mode 100644
index 0000000..2b26567
--- /dev/null
+++ b/tests/amdgpu/hotunplug_tests.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "xf86drm.h"
+#include <pthread.h>
+
+#define GFX_COMPUTE_NOP 0xffff1000
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static char *sysfs_remove = NULL;
+static bool do_cs;
+
+CU_BOOL suite_hotunplug_tests_enable(void)
+{
+ CU_BOOL enable = CU_TRUE;
+ drmDevicePtr device;
+
+ if (drmGetDevice2(drm_amdgpu[0], DRM_DEVICE_GET_PCI_REVISION, &device)) {
+ printf("\n\nGPU Failed to get DRM device PCI info!\n");
+ return CU_FALSE;
+ }
+
+ if (device->bustype != DRM_BUS_PCI) {
+ printf("\n\nGPU device is not on PCI bus!\n");
+ amdgpu_device_deinitialize(device_handle);
+ return CU_FALSE;
+ }
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ /* Latest tested amdgpu version to work with all the tests */
+ if (minor_version < 46)
+ enable = false;
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ return enable;
+}
+
+int suite_hotunplug_tests_init(void)
+{
+ /* We need to open/close device at each test manually */
+ amdgpu_close_devices();
+
+ return CUE_SUCCESS;
+}
+
+int suite_hotunplug_tests_clean(void)
+{
+
+
+ return CUE_SUCCESS;
+}
+
+static int amdgpu_hotunplug_trigger(const char *pathname)
+{
+ int fd, len;
+
+ fd = open(pathname, O_WRONLY);
+ if (fd < 0)
+ return -errno;
+
+ len = write(fd, "1", 1);
+ close(fd);
+
+ return len;
+}
+
+static int amdgpu_hotunplug_setup_test()
+{
+ int r;
+ char *tmp_str;
+
+ if (amdgpu_open_device_on_test_index(open_render_node) < 0) {
+ printf("\n\n Failed to reopen device file!\n");
+ return CUE_SINIT_FAILED;
+
+
+
+ }
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+ return CUE_SINIT_FAILED;
+ }
+
+ tmp_str = amdgpu_get_device_from_fd(drm_amdgpu[0]);
+ if (!tmp_str){
+ printf("\n\n Device path not found!\n");
+ return CUE_SINIT_FAILED;
+ }
+
+ sysfs_remove = realloc(tmp_str, strlen(tmp_str) * 2);
+ strcat(sysfs_remove, "/remove");
+
+ return 0;
+}
+
+static int amdgpu_hotunplug_teardown_test()
+{
+ if (amdgpu_device_deinitialize(device_handle))
+ return CUE_SCLEAN_FAILED;
+
+ amdgpu_close_devices();
+
+ if (sysfs_remove)
+ free(sysfs_remove);
+
+ return 0;
+}
+
+static inline int amdgpu_hotunplug_remove()
+{
+ return amdgpu_hotunplug_trigger(sysfs_remove);
+}
+
+static inline int amdgpu_hotunplug_rescan()
+{
+ return amdgpu_hotunplug_trigger("/sys/bus/pci/rescan");
+}
+
+static int amdgpu_cs_sync(amdgpu_context_handle context,
+ unsigned int ip_type,
+ int ring,
+ unsigned int seqno)
+{
+ struct amdgpu_cs_fence fence = {
+ .context = context,
+ .ip_type = ip_type,
+ .ring = ring,
+ .fence = seqno,
+ };
+ uint32_t expired;
+
+ return amdgpu_cs_query_fence_status(&fence,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+}
+
+static void *amdgpu_nop_cs()
+{
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ uint32_t *ptr;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ amdgpu_context_handle context;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ for (i = 0; i < 16; ++i)
+ ptr[i] = GFX_COMPUTE_NOP;
+
+ r = amdgpu_bo_list_create(device_handle, 1, &ib_result_handle, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+
+ while (do_cs)
+ amdgpu_cs_submit(context, 0, &ibs_request, 1);
+
+ amdgpu_cs_sync(context, AMDGPU_HW_IP_GFX, 0, ibs_request.seq_no);
+ amdgpu_bo_list_destroy(bo_list);
+ amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+
+ amdgpu_cs_ctx_free(context);
+
+ return (void *)0;
+}
+
+static pthread_t* amdgpu_create_cs_thread()
+{
+ int r;
+ pthread_t *thread = malloc(sizeof(*thread));
+ if (!thread)
+ return NULL;
+
+ do_cs = true;
+
+ r = pthread_create(thread, NULL, amdgpu_nop_cs, NULL);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Give thread enough time to start*/
+ usleep(100000);
+ return thread;
+}
+
+static void amdgpu_destroy_cs_thread(pthread_t *thread)
+{
+ void *status;
+
+ do_cs = false;
+
+ pthread_join(*thread, &status);
+ CU_ASSERT_EQUAL(status, 0);
+
+ free(thread);
+}
+
+
+static void amdgpu_hotunplug_test(bool with_cs)
+{
+ int r;
+ pthread_t *thread = NULL;
+
+ r = amdgpu_hotunplug_setup_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ if (with_cs) {
+ thread = amdgpu_create_cs_thread();
+ CU_ASSERT_NOT_EQUAL(thread, NULL);
+ }
+
+ r = amdgpu_hotunplug_remove();
+ CU_ASSERT_EQUAL(r > 0, 1);
+
+ if (with_cs)
+ amdgpu_destroy_cs_thread(thread);
+
+ r = amdgpu_hotunplug_teardown_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ r = amdgpu_hotunplug_rescan();
+ CU_ASSERT_EQUAL(r > 0, 1);
+}
+
+static void amdgpu_hotunplug_simple(void)
+{
+ amdgpu_hotunplug_test(false);
+}
+
+static void amdgpu_hotunplug_with_cs(void)
+{
+ amdgpu_hotunplug_test(true);
+}
+
+static void amdgpu_hotunplug_with_exported_bo(void)
+{
+ int r;
+ uint32_t dma_buf_fd;
+ unsigned int *ptr;
+ amdgpu_bo_handle bo_handle;
+
+ struct amdgpu_bo_alloc_request request = {
+ .alloc_size = 4096,
+ .phys_alignment = 4096,
+ .preferred_heap = AMDGPU_GEM_DOMAIN_GTT,
+ .flags = 0,
+ };
+
+ r = amdgpu_hotunplug_setup_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ amdgpu_bo_alloc(device_handle, &request, &bo_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_export(bo_handle, amdgpu_bo_handle_type_dma_buf_fd, &dma_buf_fd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd, 0);
+ CU_ASSERT_NOT_EQUAL(ptr, MAP_FAILED);
+
+ r = amdgpu_hotunplug_remove();
+ CU_ASSERT_EQUAL(r > 0, 1);
+
+ amdgpu_bo_free(bo_handle);
+
+ r = amdgpu_hotunplug_teardown_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ *ptr = 0xdeafbeef;
+
+ munmap(ptr, 4096);
+ close (dma_buf_fd);
+
+ r = amdgpu_hotunplug_rescan();
+ CU_ASSERT_EQUAL(r > 0, 1);
+}
+
+static void amdgpu_hotunplug_with_exported_fence(void)
+{
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ uint32_t *ptr, sync_obj_handle, sync_obj_handle2;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ uint32_t major2, minor2;
+ amdgpu_device_handle device2;
+ amdgpu_context_handle context;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status = {0};
+ int shared_fd;
+
+ r = amdgpu_hotunplug_setup_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ r = amdgpu_device_initialize(drm_amdgpu[1], &major2, &minor2, &device2);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_create(device_handle, &context);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+ for (i = 0; i < 16; ++i)
+ ptr[i] = GFX_COMPUTE_NOP;
+
+ r = amdgpu_bo_list_create(device_handle, 1, &ib_result_handle, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+
+ CU_ASSERT_EQUAL(amdgpu_cs_submit(context, 0, &ibs_request, 1), 0);
+
+ fence_status.context = context;
+ fence_status.ip_type = AMDGPU_HW_IP_GFX;
+ fence_status.ip_instance = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ CU_ASSERT_EQUAL(amdgpu_cs_fence_to_handle(device_handle, &fence_status,
+ AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ,
+ &sync_obj_handle),
+ 0);
+
+ CU_ASSERT_EQUAL(amdgpu_cs_export_syncobj(device_handle, sync_obj_handle, &shared_fd), 0);
+
+ CU_ASSERT_EQUAL(amdgpu_cs_import_syncobj(device2, shared_fd, &sync_obj_handle2), 0);
+
+ CU_ASSERT_EQUAL(amdgpu_cs_destroy_syncobj(device_handle, sync_obj_handle), 0);
+
+ CU_ASSERT_EQUAL(amdgpu_bo_list_destroy(bo_list), 0);
+ CU_ASSERT_EQUAL(amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096), 0);
+ CU_ASSERT_EQUAL(amdgpu_cs_ctx_free(context), 0);
+
+ r = amdgpu_hotunplug_remove();
+ CU_ASSERT_EQUAL(r > 0, 1);
+
+ CU_ASSERT_EQUAL(amdgpu_cs_syncobj_wait(device2, &sync_obj_handle2, 1, 100000000, 0, NULL), 0);
+
+ CU_ASSERT_EQUAL(amdgpu_cs_destroy_syncobj(device2, sync_obj_handle2), 0);
+
+ amdgpu_device_deinitialize(device2);
+
+ r = amdgpu_hotunplug_teardown_test();
+ CU_ASSERT_EQUAL(r , 0);
+
+ r = amdgpu_hotunplug_rescan();
+ CU_ASSERT_EQUAL(r > 0, 1);
+}
+
+
+CU_TestInfo hotunplug_tests[] = {
+ { "Unplug card and rescan the bus to plug it back", amdgpu_hotunplug_simple },
+ { "Same as first test but with command submission", amdgpu_hotunplug_with_cs },
+ { "Unplug with exported bo", amdgpu_hotunplug_with_exported_bo },
+ { "Unplug with exported fence", amdgpu_hotunplug_with_exported_fence },
+ CU_TEST_INFO_NULL,
+};
diff --git a/tests/amdgpu/jpeg_tests.c b/tests/amdgpu/jpeg_tests.c
new file mode 100644
index 0000000..772a4fe
--- /dev/null
+++ b/tests/amdgpu/jpeg_tests.c
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "amdgpu_test.h"
+#include "decode_messages.h"
+
+/* jpeg registers */
+#define mmUVD_JPEG_CNTL 0x0200
+#define mmUVD_JPEG_RB_BASE 0x0201
+#define mmUVD_JPEG_RB_WPTR 0x0202
+#define mmUVD_JPEG_RB_RPTR 0x0203
+#define mmUVD_JPEG_RB_SIZE 0x0204
+#define mmUVD_JPEG_TIER_CNTL2 0x021a
+#define mmUVD_JPEG_UV_TILING_CTRL 0x021c
+#define mmUVD_JPEG_TILING_CTRL 0x021e
+#define mmUVD_JPEG_OUTBUF_RPTR 0x0220
+#define mmUVD_JPEG_OUTBUF_WPTR 0x0221
+#define mmUVD_JPEG_PITCH 0x0222
+#define mmUVD_JPEG_INT_EN 0x0229
+#define mmUVD_JPEG_UV_PITCH 0x022b
+#define mmUVD_JPEG_INDEX 0x023e
+#define mmUVD_JPEG_DATA 0x023f
+#define mmUVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0438
+#define mmUVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0439
+#define mmUVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x045a
+#define mmUVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x045b
+#define mmUVD_CTX_INDEX 0x0528
+#define mmUVD_CTX_DATA 0x0529
+#define mmUVD_SOFT_RESET 0x05a0
+
+#define vcnipUVD_JPEG_DEC_SOFT_RST 0x402f
+#define vcnipUVD_JRBC_IB_COND_RD_TIMER 0x408e
+#define vcnipUVD_JRBC_IB_REF_DATA 0x408f
+#define vcnipUVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x40e1
+#define vcnipUVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x40e0
+#define vcnipUVD_JPEG_RB_BASE 0x4001
+#define vcnipUVD_JPEG_RB_SIZE 0x4004
+#define vcnipUVD_JPEG_RB_WPTR 0x4002
+#define vcnipUVD_JPEG_PITCH 0x401f
+#define vcnipUVD_JPEG_UV_PITCH 0x4020
+#define vcnipJPEG_DEC_ADDR_MODE 0x4027
+#define vcnipJPEG_DEC_Y_GFX10_TILING_SURFACE 0x4024
+#define vcnipJPEG_DEC_UV_GFX10_TILING_SURFACE 0x4025
+#define vcnipUVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x40e3
+#define vcnipUVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x40e2
+#define vcnipUVD_JPEG_INDEX 0x402c
+#define vcnipUVD_JPEG_DATA 0x402d
+#define vcnipUVD_JPEG_TIER_CNTL2 0x400f
+#define vcnipUVD_JPEG_OUTBUF_RPTR 0x401e
+#define vcnipUVD_JPEG_OUTBUF_CNTL 0x401c
+#define vcnipUVD_JPEG_INT_EN 0x400a
+#define vcnipUVD_JPEG_CNTL 0x4000
+#define vcnipUVD_JPEG_RB_RPTR 0x4003
+#define vcnipUVD_JPEG_OUTBUF_WPTR 0x401d
+
+
+#define RDECODE_PKT_REG_J(x) ((unsigned)(x)&0x3FFFF)
+#define RDECODE_PKT_RES_J(x) (((unsigned)(x)&0x3F) << 18)
+#define RDECODE_PKT_COND_J(x) (((unsigned)(x)&0xF) << 24)
+#define RDECODE_PKT_TYPE_J(x) (((unsigned)(x)&0xF) << 28)
+#define RDECODE_PKTJ(reg, cond, type) (RDECODE_PKT_REG_J(reg) | \
+ RDECODE_PKT_RES_J(0) | \
+ RDECODE_PKT_COND_J(cond) | \
+ RDECODE_PKT_TYPE_J(type))
+
+#define UVD_BASE_INST0_SEG1 0x00007E00
+#define SOC15_REG_ADDR(reg) (UVD_BASE_INST0_SEG1 + reg)
+
+#define COND0 0
+#define COND1 1
+#define COND3 3
+#define TYPE0 0
+#define TYPE1 1
+#define TYPE3 3
+#define JPEG_DEC_DT_PITCH 0x100
+#define JPEG_DEC_BSD_SIZE 0x180
+#define JPEG_DEC_LUMA_OFFSET 0
+#define JPEG_DEC_CHROMA_OFFSET 0x1000
+#define JPEG_DEC_SUM 4096
+#define IB_SIZE 4096
+#define MAX_RESOURCES 16
+
+struct amdgpu_jpeg_bo {
+ amdgpu_bo_handle handle;
+ amdgpu_va_handle va_handle;
+ uint64_t addr;
+ uint64_t size;
+ uint8_t *ptr;
+};
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+static uint32_t asic_id;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+static uint32_t len;
+
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+bool jpeg_direct_reg;
+
+static void set_reg_jpeg(unsigned reg, unsigned cond, unsigned type,
+ uint32_t val);
+static void send_cmd_bitstream(uint64_t addr);
+static void send_cmd_target(uint64_t addr);
+static void send_cmd_bitstream_direct(uint64_t addr);
+static void send_cmd_target_direct(uint64_t addr);
+
+static void amdgpu_cs_jpeg_decode(void);
+
+CU_TestInfo jpeg_tests[] = {
+ {"JPEG decode", amdgpu_cs_jpeg_decode},
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_jpeg_tests_enable(void)
+{
+ struct drm_amdgpu_info_hw_ip info;
+ int r;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, &minor_version,
+ &device_handle))
+ return CU_FALSE;
+
+ family_id = device_handle->info.family_id;
+ asic_id = device_handle->info.asic_id;
+ chip_rev = device_handle->info.chip_rev;
+ chip_id = device_handle->info.chip_external_rev;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_VCN_JPEG, 0, &info);
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ if (r != 0 || !info.available_rings ||
+ (family_id < AMDGPU_FAMILY_RV &&
+ (family_id == AMDGPU_FAMILY_AI &&
+ (chip_id - chip_rev) < 0x32))) { /* Arcturus */
+ printf("\n\nThe ASIC NOT support JPEG, suite disabled\n");
+ return CU_FALSE;
+ }
+
+ if (info.hw_ip_version_major == 1)
+ jpeg_direct_reg = false;
+ else if (info.hw_ip_version_major > 1 && info.hw_ip_version_major <= 3)
+ jpeg_direct_reg = true;
+ else
+ return CU_FALSE;
+
+ return CU_TRUE;
+}
+
+int suite_jpeg_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, &minor_version,
+ &device_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ family_id = device_handle->info.family_id;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0, &ib_handle,
+ (void **)&ib_cpu, &ib_mc_address, &ib_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+int suite_jpeg_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ int r;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = ndw;
+
+ ibs_request.ip_type = ip;
+
+ r = amdgpu_bo_list_create(device_handle, num_resources, resources, NULL,
+ &ibs_request.resources);
+ if (r)
+ return r;
+
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status, AMDGPU_TIMEOUT_INFINITE, 0,
+ &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void alloc_resource(struct amdgpu_jpeg_bo *jpeg_bo, unsigned size,
+ unsigned domain)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ int r;
+
+ req.alloc_size = ALIGN(size, 4096);
+ req.preferred_heap = domain;
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_va_range_alloc(device_handle, amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va, &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ jpeg_bo->addr = va;
+ jpeg_bo->handle = buf_handle;
+ jpeg_bo->size = req.alloc_size;
+ jpeg_bo->va_handle = va_handle;
+ r = amdgpu_bo_cpu_map(jpeg_bo->handle, (void **)&jpeg_bo->ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(jpeg_bo->ptr, 0, size);
+ r = amdgpu_bo_cpu_unmap(jpeg_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_jpeg_bo *jpeg_bo)
+{
+ int r;
+
+ r = amdgpu_bo_va_op(jpeg_bo->handle, 0, jpeg_bo->size, jpeg_bo->addr, 0,
+ AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(jpeg_bo->va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(jpeg_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(jpeg_bo, 0, sizeof(*jpeg_bo));
+}
+
+static void set_reg_jpeg(unsigned reg, unsigned cond, unsigned type,
+ uint32_t val)
+{
+ ib_cpu[len++] = RDECODE_PKTJ(reg, cond, type);
+ ib_cpu[len++] = val;
+}
+
+/* send a bitstream buffer command */
+static void send_cmd_bitstream(uint64_t addr)
+{
+
+ /* jpeg soft reset */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 1);
+
+ /* ensuring the Reset is asserted in SCLK domain */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C2);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, 0x01400200);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, (1 << 9));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_SOFT_RESET), COND0, TYPE3, (1 << 9));
+
+ /* wait mem */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 0);
+
+ /* ensuring the Reset is de-asserted in SCLK domain */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, (0 << 9));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_SOFT_RESET), COND0, TYPE3, (1 << 9));
+
+ /* set UVD_LMI_JPEG_READ_64BIT_BAR_LOW/HIGH based on bitstream buffer address */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_LMI_JPEG_READ_64BIT_BAR_HIGH), COND0, TYPE0,
+ (addr >> 32));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_LMI_JPEG_READ_64BIT_BAR_LOW), COND0, TYPE0,
+ (unsigned int)addr);
+
+ /* set jpeg_rb_base */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_RB_BASE), COND0, TYPE0, 0);
+
+ /* set jpeg_rb_base */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_RB_SIZE), COND0, TYPE0, 0xFFFFFFF0);
+
+ /* set jpeg_rb_wptr */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_RB_WPTR), COND0, TYPE0,
+ (JPEG_DEC_BSD_SIZE >> 2));
+}
+
+/* send a target buffer command */
+static void send_cmd_target(uint64_t addr)
+{
+
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_PITCH), COND0, TYPE0,
+ (JPEG_DEC_DT_PITCH >> 4));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_UV_PITCH), COND0, TYPE0,
+ (JPEG_DEC_DT_PITCH >> 4));
+
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_TILING_CTRL), COND0, TYPE0, 0);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_UV_TILING_CTRL), COND0, TYPE0, 0);
+
+ /* set UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW/HIGH based on target buffer address */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH), COND0,
+ TYPE0, (addr >> 32));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_LMI_JPEG_WRITE_64BIT_BAR_LOW), COND0, TYPE0,
+ (unsigned int)addr);
+
+ /* set output buffer data address */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_INDEX), COND0, TYPE0, 0);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_DATA), COND0, TYPE0,
+ JPEG_DEC_LUMA_OFFSET);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_INDEX), COND0, TYPE0, 1);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_DATA), COND0, TYPE0,
+ JPEG_DEC_CHROMA_OFFSET);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_TIER_CNTL2), COND0, TYPE3, 0);
+
+ /* set output buffer read pointer */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_OUTBUF_RPTR), COND0, TYPE0, 0);
+
+ /* enable error interrupts */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_INT_EN), COND0, TYPE0, 0xFFFFFFFE);
+
+ /* start engine command */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 0x6);
+
+ /* wait for job completion, wait for job JBSI fetch done */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0,
+ (JPEG_DEC_BSD_SIZE >> 2));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C2);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, 0x01400200);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_RB_RPTR), COND0, TYPE3, 0xFFFFFFFF);
+
+ /* wait for job jpeg outbuf idle */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, 0xFFFFFFFF);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_OUTBUF_WPTR), COND0, TYPE3,
+ 0x00000001);
+
+ /* stop engine */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 0x4);
+
+ /* asserting jpeg lmi drop */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x0005);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0,
+ (1 << 23 | 1 << 0));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE1, 0);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, 0);
+
+ /* asserting jpeg reset */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 1);
+
+ /* ensure reset is asserted in sclk domain */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, (1 << 9));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_SOFT_RESET), COND0, TYPE3, (1 << 9));
+
+ /* de-assert jpeg reset */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_JPEG_CNTL), COND0, TYPE0, 0);
+
+ /* ensure reset is de-asserted in sclk domain */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x01C3);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, (0 << 9));
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_SOFT_RESET), COND0, TYPE3, (1 << 9));
+
+ /* de-asserting jpeg lmi drop */
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_INDEX), COND0, TYPE0, 0x0005);
+ set_reg_jpeg(SOC15_REG_ADDR(mmUVD_CTX_DATA), COND0, TYPE0, 0);
+}
+
+/* send a bitstream buffer command */
+static void send_cmd_bitstream_direct(uint64_t addr)
+{
+
+ /* jpeg soft reset */
+ set_reg_jpeg(vcnipUVD_JPEG_DEC_SOFT_RST, COND0, TYPE0, 1);
+
+ /* ensuring the Reset is asserted in SCLK domain */
+ set_reg_jpeg(vcnipUVD_JRBC_IB_COND_RD_TIMER, COND0, TYPE0, 0x01400200);
+ set_reg_jpeg(vcnipUVD_JRBC_IB_REF_DATA, COND0, TYPE0, (0x1 << 0x10));
+ set_reg_jpeg(vcnipUVD_JPEG_DEC_SOFT_RST, COND3, TYPE3, (0x1 << 0x10));
+
+ /* wait mem */
+ set_reg_jpeg(vcnipUVD_JPEG_DEC_SOFT_RST, COND0, TYPE0, 0);
+
+ /* ensuring the Reset is de-asserted in SCLK domain */
+ set_reg_jpeg(vcnipUVD_JRBC_IB_REF_DATA, COND0, TYPE0, (0 << 0x10));
+ set_reg_jpeg(vcnipUVD_JPEG_DEC_SOFT_RST, COND3, TYPE3, (0x1 << 0x10));
+
+ /* set UVD_LMI_JPEG_READ_64BIT_BAR_LOW/HIGH based on bitstream buffer address */
+ set_reg_jpeg(vcnipUVD_LMI_JPEG_READ_64BIT_BAR_HIGH, COND0, TYPE0,
+ (addr >> 32));
+ set_reg_jpeg(vcnipUVD_LMI_JPEG_READ_64BIT_BAR_LOW, COND0, TYPE0, addr);
+
+ /* set jpeg_rb_base */
+ set_reg_jpeg(vcnipUVD_JPEG_RB_BASE, COND0, TYPE0, 0);
+
+ /* set jpeg_rb_base */
+ set_reg_jpeg(vcnipUVD_JPEG_RB_SIZE, COND0, TYPE0, 0xFFFFFFF0);
+
+ /* set jpeg_rb_wptr */
+ set_reg_jpeg(vcnipUVD_JPEG_RB_WPTR, COND0, TYPE0, (JPEG_DEC_BSD_SIZE >> 2));
+}
+
+/* send a target buffer command */
+static void send_cmd_target_direct(uint64_t addr)
+{
+
+ set_reg_jpeg(vcnipUVD_JPEG_PITCH, COND0, TYPE0, (JPEG_DEC_DT_PITCH >> 4));
+ set_reg_jpeg(vcnipUVD_JPEG_UV_PITCH, COND0, TYPE0, (JPEG_DEC_DT_PITCH >> 4));
+
+ set_reg_jpeg(vcnipJPEG_DEC_ADDR_MODE, COND0, TYPE0, 0);
+ set_reg_jpeg(vcnipJPEG_DEC_Y_GFX10_TILING_SURFACE, COND0, TYPE0, 0);
+ set_reg_jpeg(vcnipJPEG_DEC_UV_GFX10_TILING_SURFACE, COND0, TYPE0, 0);
+
+ /* set UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW/HIGH based on target buffer address */
+ set_reg_jpeg(vcnipUVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH, COND0, TYPE0,
+ (addr >> 32));
+ set_reg_jpeg(vcnipUVD_LMI_JPEG_WRITE_64BIT_BAR_LOW, COND0, TYPE0, addr);
+
+ /* set output buffer data address */
+ set_reg_jpeg(vcnipUVD_JPEG_INDEX, COND0, TYPE0, 0);
+ set_reg_jpeg(vcnipUVD_JPEG_DATA, COND0, TYPE0, JPEG_DEC_LUMA_OFFSET);
+ set_reg_jpeg(vcnipUVD_JPEG_INDEX, COND0, TYPE0, 1);
+ set_reg_jpeg(vcnipUVD_JPEG_DATA, COND0, TYPE0, JPEG_DEC_CHROMA_OFFSET);
+ set_reg_jpeg(vcnipUVD_JPEG_TIER_CNTL2, COND0, 0, 0);
+
+ /* set output buffer read pointer */
+ set_reg_jpeg(vcnipUVD_JPEG_OUTBUF_RPTR, COND0, TYPE0, 0);
+ set_reg_jpeg(vcnipUVD_JPEG_OUTBUF_CNTL, COND0, TYPE0,
+ ((0x00001587 & (~0x00000180L)) | (0x1 << 0x7) | (0x1 << 0x6)));
+
+ /* enable error interrupts */
+ set_reg_jpeg(vcnipUVD_JPEG_INT_EN, COND0, TYPE0, 0xFFFFFFFE);
+
+ /* start engine command */
+ set_reg_jpeg(vcnipUVD_JPEG_CNTL, COND0, TYPE0, 0xE);
+
+ /* wait for job completion, wait for job JBSI fetch done */
+ set_reg_jpeg(vcnipUVD_JRBC_IB_REF_DATA, COND0, TYPE0,
+ (JPEG_DEC_BSD_SIZE >> 2));
+ set_reg_jpeg(vcnipUVD_JRBC_IB_COND_RD_TIMER, COND0, TYPE0, 0x01400200);
+ set_reg_jpeg(vcnipUVD_JPEG_RB_RPTR, COND3, TYPE3, 0xFFFFFFFF);
+
+ /* wait for job jpeg outbuf idle */
+ set_reg_jpeg(vcnipUVD_JRBC_IB_REF_DATA, COND0, TYPE0, 0xFFFFFFFF);
+ set_reg_jpeg(vcnipUVD_JPEG_OUTBUF_WPTR, COND3, TYPE3, 0x00000001);
+
+ /* stop engine */
+ set_reg_jpeg(vcnipUVD_JPEG_CNTL, COND0, TYPE0, 0x4);
+}
+
+static void amdgpu_cs_jpeg_decode(void)
+{
+
+ struct amdgpu_jpeg_bo dec_buf;
+ int size, r;
+ uint8_t *dec;
+ int sum = 0, i, j;
+
+ size = 16 * 1024; /* 8K bitstream + 8K output */
+ num_resources = 0;
+ alloc_resource(&dec_buf, size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = dec_buf.handle;
+ resources[num_resources++] = ib_handle;
+ r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ memcpy(dec_buf.ptr, jpeg_bitstream, sizeof(jpeg_bitstream));
+
+ len = 0;
+
+ if (jpeg_direct_reg == true) {
+ send_cmd_bitstream_direct(dec_buf.addr);
+ send_cmd_target_direct(dec_buf.addr + (size / 2));
+ } else {
+ send_cmd_bitstream(dec_buf.addr);
+ send_cmd_target(dec_buf.addr + (size / 2));
+ }
+
+ amdgpu_bo_cpu_unmap(dec_buf.handle);
+ r = submit(len, AMDGPU_HW_IP_VCN_JPEG);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ dec = dec_buf.ptr + (size / 2);
+
+ /* calculate result checksum */
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ sum += *((dec + JPEG_DEC_LUMA_OFFSET + i * JPEG_DEC_DT_PITCH) + j);
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 8; j++)
+ sum += *((dec + JPEG_DEC_CHROMA_OFFSET + i * JPEG_DEC_DT_PITCH) + j);
+
+ amdgpu_bo_cpu_unmap(dec_buf.handle);
+ CU_ASSERT_EQUAL(sum, JPEG_DEC_SUM);
+
+ free_resource(&dec_buf);
+}
diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
new file mode 100644
index 0000000..8618f6a
--- /dev/null
+++ b/tests/amdgpu/meson.build
@@ -0,0 +1,46 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+if dep_cunit.found()
+ amdgpu_test = executable(
+ 'amdgpu_test',
+ files(
+ 'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c',
+ 'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c',
+ 'vm_tests.c', 'ras_tests.c', 'syncobj_tests.c', 'security_tests.c',
+ 'hotunplug_tests.c', 'jpeg_tests.c', 'cp_dma_tests.c', 'shader_test_util.c'
+ ),
+ dependencies : [dep_cunit, dep_threads, dep_atomic_ops],
+ include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')],
+ link_with : [libdrm, libdrm_amdgpu],
+ install : with_install_tests,
+ )
+endif
+
+amdgpu_stress = executable(
+ 'amdgpu_stress',
+ files(
+ 'amdgpu_stress.c'
+ ),
+ dependencies : [dep_threads, dep_atomic_ops],
+ include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')],
+ link_with : [libdrm, libdrm_amdgpu],
+ install : with_install_tests,
+)
diff --git a/tests/amdgpu/ras_tests.c b/tests/amdgpu/ras_tests.c
new file mode 100644
index 0000000..810bf17
--- /dev/null
+++ b/tests/amdgpu/ras_tests.c
@@ -0,0 +1,1003 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "xf86drm.h"
+#include <limits.h>
+
+#define PATH_SIZE PATH_MAX
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+const char *ras_block_string[] = {
+ "umc",
+ "sdma",
+ "gfx",
+ "mmhub",
+ "athub",
+ "pcie_bif",
+ "hdp",
+ "xgmi_wafl",
+ "df",
+ "smn",
+ "sem",
+ "mp0",
+ "mp1",
+ "fuse",
+};
+
+#define ras_block_str(i) (ras_block_string[i])
+
+enum amdgpu_ras_block {
+ AMDGPU_RAS_BLOCK__UMC = 0,
+ AMDGPU_RAS_BLOCK__SDMA,
+ AMDGPU_RAS_BLOCK__GFX,
+ AMDGPU_RAS_BLOCK__MMHUB,
+ AMDGPU_RAS_BLOCK__ATHUB,
+ AMDGPU_RAS_BLOCK__PCIE_BIF,
+ AMDGPU_RAS_BLOCK__HDP,
+ AMDGPU_RAS_BLOCK__XGMI_WAFL,
+ AMDGPU_RAS_BLOCK__DF,
+ AMDGPU_RAS_BLOCK__SMN,
+ AMDGPU_RAS_BLOCK__SEM,
+ AMDGPU_RAS_BLOCK__MP0,
+ AMDGPU_RAS_BLOCK__MP1,
+ AMDGPU_RAS_BLOCK__FUSE,
+
+ AMDGPU_RAS_BLOCK__LAST
+};
+
+#define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST
+#define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1)
+
+enum amdgpu_ras_gfx_subblock {
+ /* CPC */
+ AMDGPU_RAS_BLOCK__GFX_CPC_INDEX_START = 0,
+ AMDGPU_RAS_BLOCK__GFX_CPC_SCRATCH =
+ AMDGPU_RAS_BLOCK__GFX_CPC_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_CPC_UCODE,
+ AMDGPU_RAS_BLOCK__GFX_DC_STATE_ME1,
+ AMDGPU_RAS_BLOCK__GFX_DC_CSINVOC_ME1,
+ AMDGPU_RAS_BLOCK__GFX_DC_RESTORE_ME1,
+ AMDGPU_RAS_BLOCK__GFX_DC_STATE_ME2,
+ AMDGPU_RAS_BLOCK__GFX_DC_CSINVOC_ME2,
+ AMDGPU_RAS_BLOCK__GFX_DC_RESTORE_ME2,
+ AMDGPU_RAS_BLOCK__GFX_CPC_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_DC_RESTORE_ME2,
+ /* CPF */
+ AMDGPU_RAS_BLOCK__GFX_CPF_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_CPF_ROQ_ME2 =
+ AMDGPU_RAS_BLOCK__GFX_CPF_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_CPF_ROQ_ME1,
+ AMDGPU_RAS_BLOCK__GFX_CPF_TAG,
+ AMDGPU_RAS_BLOCK__GFX_CPF_INDEX_END = AMDGPU_RAS_BLOCK__GFX_CPF_TAG,
+ /* CPG */
+ AMDGPU_RAS_BLOCK__GFX_CPG_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_CPG_DMA_ROQ =
+ AMDGPU_RAS_BLOCK__GFX_CPG_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_CPG_DMA_TAG,
+ AMDGPU_RAS_BLOCK__GFX_CPG_TAG,
+ AMDGPU_RAS_BLOCK__GFX_CPG_INDEX_END = AMDGPU_RAS_BLOCK__GFX_CPG_TAG,
+ /* GDS */
+ AMDGPU_RAS_BLOCK__GFX_GDS_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_GDS_MEM = AMDGPU_RAS_BLOCK__GFX_GDS_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_GDS_INPUT_QUEUE,
+ AMDGPU_RAS_BLOCK__GFX_GDS_OA_PHY_CMD_RAM_MEM,
+ AMDGPU_RAS_BLOCK__GFX_GDS_OA_PHY_DATA_RAM_MEM,
+ AMDGPU_RAS_BLOCK__GFX_GDS_OA_PIPE_MEM,
+ AMDGPU_RAS_BLOCK__GFX_GDS_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_GDS_OA_PIPE_MEM,
+ /* SPI */
+ AMDGPU_RAS_BLOCK__GFX_SPI_SR_MEM,
+ /* SQ */
+ AMDGPU_RAS_BLOCK__GFX_SQ_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_SQ_SGPR = AMDGPU_RAS_BLOCK__GFX_SQ_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_SQ_LDS_D,
+ AMDGPU_RAS_BLOCK__GFX_SQ_LDS_I,
+ AMDGPU_RAS_BLOCK__GFX_SQ_VGPR,
+ AMDGPU_RAS_BLOCK__GFX_SQ_INDEX_END = AMDGPU_RAS_BLOCK__GFX_SQ_VGPR,
+ /* SQC (3 ranges) */
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX_START,
+ /* SQC range 0 */
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX0_START =
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_UTCL1_LFIFO =
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX0_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU0_WRITE_DATA_BUF,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU0_UTCL1_LFIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU1_WRITE_DATA_BUF,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU1_UTCL1_LFIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU2_WRITE_DATA_BUF,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU2_UTCL1_LFIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX0_END =
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU2_UTCL1_LFIFO,
+ /* SQC range 1 */
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKA_TAG_RAM =
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKA_UTCL1_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKA_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKA_BANK_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_TAG_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_HIT_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_DIRTY_BIT_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_BANK_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX1_END =
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKA_BANK_RAM,
+ /* SQC range 2 */
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKB_TAG_RAM =
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKB_UTCL1_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKB_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKB_BANK_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_TAG_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_HIT_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_MISS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_DIRTY_BIT_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_BANK_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX2_END =
+ AMDGPU_RAS_BLOCK__GFX_SQC_DATA_BANKB_BANK_RAM,
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_SQC_INDEX2_END,
+ /* TA */
+ AMDGPU_RAS_BLOCK__GFX_TA_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TA_FS_DFIFO =
+ AMDGPU_RAS_BLOCK__GFX_TA_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TA_FS_AFIFO,
+ AMDGPU_RAS_BLOCK__GFX_TA_FL_LFIFO,
+ AMDGPU_RAS_BLOCK__GFX_TA_FX_LFIFO,
+ AMDGPU_RAS_BLOCK__GFX_TA_FS_CFIFO,
+ AMDGPU_RAS_BLOCK__GFX_TA_INDEX_END = AMDGPU_RAS_BLOCK__GFX_TA_FS_CFIFO,
+ /* TCA */
+ AMDGPU_RAS_BLOCK__GFX_TCA_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TCA_HOLE_FIFO =
+ AMDGPU_RAS_BLOCK__GFX_TCA_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TCA_REQ_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCA_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_TCA_REQ_FIFO,
+ /* TCC (5 sub-ranges) */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX_START,
+ /* TCC range 0 */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX0_START =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX0_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_0_1,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_1_0,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_1_1,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DIRTY_BANK_0,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DIRTY_BANK_1,
+ AMDGPU_RAS_BLOCK__GFX_TCC_HIGH_RATE_TAG,
+ AMDGPU_RAS_BLOCK__GFX_TCC_LOW_RATE_TAG,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX0_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_LOW_RATE_TAG,
+ /* TCC range 1 */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_IN_USE_DEC =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_IN_USE_TRANSFER,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX1_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_IN_USE_TRANSFER,
+ /* TCC range 2 */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_RETURN_DATA =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_RETURN_CONTROL,
+ AMDGPU_RAS_BLOCK__GFX_TCC_UC_ATOMIC_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCC_WRITE_RETURN,
+ AMDGPU_RAS_BLOCK__GFX_TCC_WRITE_CACHE_READ,
+ AMDGPU_RAS_BLOCK__GFX_TCC_SRC_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCC_SRC_FIFO_NEXT_RAM,
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_TAG_PROBE_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX2_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_TAG_PROBE_FIFO,
+ /* TCC range 3 */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX3_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_LATENCY_FIFO =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX3_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_LATENCY_FIFO_NEXT_RAM,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX3_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_LATENCY_FIFO_NEXT_RAM,
+ /* TCC range 4 */
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX4_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_WRRET_TAG_WRITE_RETURN =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX4_START,
+ AMDGPU_RAS_BLOCK__GFX_TCC_ATOMIC_RETURN_BUFFER,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX4_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_ATOMIC_RETURN_BUFFER,
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_TCC_INDEX4_END,
+ /* TCI */
+ AMDGPU_RAS_BLOCK__GFX_TCI_WRITE_RAM,
+ /* TCP */
+ AMDGPU_RAS_BLOCK__GFX_TCP_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TCP_CACHE_RAM =
+ AMDGPU_RAS_BLOCK__GFX_TCP_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TCP_LFIFO_RAM,
+ AMDGPU_RAS_BLOCK__GFX_TCP_CMD_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCP_VM_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TCP_DB_RAM,
+ AMDGPU_RAS_BLOCK__GFX_TCP_UTCL1_LFIFO0,
+ AMDGPU_RAS_BLOCK__GFX_TCP_UTCL1_LFIFO1,
+ AMDGPU_RAS_BLOCK__GFX_TCP_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_TCP_UTCL1_LFIFO1,
+ /* TD */
+ AMDGPU_RAS_BLOCK__GFX_TD_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TD_SS_FIFO_LO =
+ AMDGPU_RAS_BLOCK__GFX_TD_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_TD_SS_FIFO_HI,
+ AMDGPU_RAS_BLOCK__GFX_TD_CS_FIFO,
+ AMDGPU_RAS_BLOCK__GFX_TD_INDEX_END = AMDGPU_RAS_BLOCK__GFX_TD_CS_FIFO,
+ /* EA (3 sub-ranges) */
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX_START,
+ /* EA range 0 */
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX0_START =
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_DRAMRD_CMDMEM =
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX0_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_DRAMWR_CMDMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_DRAMWR_DATAMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_RRET_TAGMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_WRET_TAGMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIRD_CMDMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIWR_CMDMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIWR_DATAMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX0_END =
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIWR_DATAMEM,
+ /* EA range 1 */
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_DRAMRD_PAGEMEM =
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX1_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_DRAMWR_PAGEMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_IORD_CMDMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_IOWR_CMDMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_IOWR_DATAMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIRD_PAGEMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIWR_PAGEMEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX1_END =
+ AMDGPU_RAS_BLOCK__GFX_EA_GMIWR_PAGEMEM,
+ /* EA range 2 */
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_MAM_D0MEM =
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX2_START,
+ AMDGPU_RAS_BLOCK__GFX_EA_MAM_D1MEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_MAM_D2MEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_MAM_D3MEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX2_END =
+ AMDGPU_RAS_BLOCK__GFX_EA_MAM_D3MEM,
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX_END =
+ AMDGPU_RAS_BLOCK__GFX_EA_INDEX2_END,
+ /* UTC VM L2 bank */
+ AMDGPU_RAS_BLOCK__UTC_VML2_BANK_CACHE,
+ /* UTC VM walker */
+ AMDGPU_RAS_BLOCK__UTC_VML2_WALKER,
+ /* UTC ATC L2 2MB cache */
+ AMDGPU_RAS_BLOCK__UTC_ATCL2_CACHE_2M_BANK,
+ /* UTC ATC L2 4KB cache */
+ AMDGPU_RAS_BLOCK__UTC_ATCL2_CACHE_4K_BANK,
+ AMDGPU_RAS_BLOCK__GFX_MAX
+};
+
+enum amdgpu_ras_error_type {
+ AMDGPU_RAS_ERROR__NONE = 0,
+ AMDGPU_RAS_ERROR__PARITY = 1,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE = 2,
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE = 4,
+ AMDGPU_RAS_ERROR__POISON = 8,
+};
+
+struct ras_inject_test_config {
+ char name[64];
+ char block[32];
+ int sub_block;
+ enum amdgpu_ras_error_type type;
+ uint64_t address;
+ uint64_t value;
+};
+
+struct ras_common_if {
+ enum amdgpu_ras_block block;
+ enum amdgpu_ras_error_type type;
+ uint32_t sub_block_index;
+ char name[32];
+};
+
+struct ras_inject_if {
+ struct ras_common_if head;
+ uint64_t address;
+ uint64_t value;
+};
+
+struct ras_debug_if {
+ union {
+ struct ras_common_if head;
+ struct ras_inject_if inject;
+ };
+ int op;
+};
+/* for now, only umc, gfx, sdma has implemented. */
+#define DEFAULT_RAS_BLOCK_MASK_INJECT ((1 << AMDGPU_RAS_BLOCK__UMC) |\
+ (1 << AMDGPU_RAS_BLOCK__GFX))
+#define DEFAULT_RAS_BLOCK_MASK_QUERY ((1 << AMDGPU_RAS_BLOCK__UMC) |\
+ (1 << AMDGPU_RAS_BLOCK__GFX))
+#define DEFAULT_RAS_BLOCK_MASK_BASIC (1 << AMDGPU_RAS_BLOCK__UMC |\
+ (1 << AMDGPU_RAS_BLOCK__SDMA) |\
+ (1 << AMDGPU_RAS_BLOCK__GFX))
+
+static uint32_t ras_block_mask_inject = DEFAULT_RAS_BLOCK_MASK_INJECT;
+static uint32_t ras_block_mask_query = DEFAULT_RAS_BLOCK_MASK_INJECT;
+static uint32_t ras_block_mask_basic = DEFAULT_RAS_BLOCK_MASK_BASIC;
+
+struct ras_test_mask {
+ uint32_t inject_mask;
+ uint32_t query_mask;
+ uint32_t basic_mask;
+};
+
+struct amdgpu_ras_data {
+ amdgpu_device_handle device_handle;
+ uint32_t id;
+ uint32_t capability;
+ struct ras_test_mask test_mask;
+};
+
+/* all devices who has ras supported */
+static struct amdgpu_ras_data devices[MAX_CARDS_SUPPORTED];
+static int devices_count;
+
+struct ras_DID_test_mask{
+ uint16_t device_id;
+ uint16_t revision_id;
+ struct ras_test_mask test_mask;
+};
+
+/* white list for inject test. */
+#define RAS_BLOCK_MASK_ALL {\
+ DEFAULT_RAS_BLOCK_MASK_INJECT,\
+ DEFAULT_RAS_BLOCK_MASK_QUERY,\
+ DEFAULT_RAS_BLOCK_MASK_BASIC\
+}
+
+#define RAS_BLOCK_MASK_QUERY_BASIC {\
+ 0,\
+ DEFAULT_RAS_BLOCK_MASK_QUERY,\
+ DEFAULT_RAS_BLOCK_MASK_BASIC\
+}
+
+static const struct ras_inject_test_config umc_ras_inject_test[] = {
+ {"ras_umc.1.0", "umc", 0, AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+};
+
+static const struct ras_inject_test_config gfx_ras_inject_test[] = {
+ {"ras_gfx.2.0", "gfx", AMDGPU_RAS_BLOCK__GFX_CPC_UCODE,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.1", "gfx", AMDGPU_RAS_BLOCK__GFX_CPF_TAG,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.2", "gfx", AMDGPU_RAS_BLOCK__GFX_CPG_TAG,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.3", "gfx", AMDGPU_RAS_BLOCK__GFX_SQ_LDS_D,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.4", "gfx", AMDGPU_RAS_BLOCK__GFX_SQC_DATA_CU1_UTCL1_LFIFO,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.5", "gfx", AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKA_TAG_RAM,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.6", "gfx", AMDGPU_RAS_BLOCK__GFX_SQC_INST_BANKB_TAG_RAM,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.7", "gfx", AMDGPU_RAS_BLOCK__GFX_TA_FS_DFIFO,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.8", "gfx", AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.9", "gfx", AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_0_1,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.10", "gfx", AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_1_0,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.11", "gfx", AMDGPU_RAS_BLOCK__GFX_TCC_CACHE_DATA_BANK_1_1,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.12", "gfx", AMDGPU_RAS_BLOCK__GFX_TCP_CACHE_RAM,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.13", "gfx", AMDGPU_RAS_BLOCK__GFX_TD_SS_FIFO_LO,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+ {"ras_gfx.2.14", "gfx", AMDGPU_RAS_BLOCK__GFX_EA_DRAMRD_CMDMEM,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE, 0, 0},
+};
+
+static const struct ras_DID_test_mask ras_DID_array[] = {
+ {0x66a1, 0x00, RAS_BLOCK_MASK_ALL},
+ {0x66a1, 0x01, RAS_BLOCK_MASK_ALL},
+ {0x66a1, 0x04, RAS_BLOCK_MASK_ALL},
+};
+
+static uint32_t amdgpu_ras_find_block_id_by_name(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ras_block_string); i++) {
+ if (strcmp(name, ras_block_string[i]) == 0)
+ return i;
+ }
+
+ return ARRAY_SIZE(ras_block_string);
+}
+
+static char *amdgpu_ras_get_error_type_id(enum amdgpu_ras_error_type type)
+{
+ switch (type) {
+ case AMDGPU_RAS_ERROR__PARITY:
+ return "parity";
+ case AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE:
+ return "single_correctable";
+ case AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE:
+ return "multi_uncorrectable";
+ case AMDGPU_RAS_ERROR__POISON:
+ return "poison";
+ case AMDGPU_RAS_ERROR__NONE:
+ default:
+ return NULL;
+ }
+}
+
+static struct ras_test_mask amdgpu_ras_get_test_mask(drmDevicePtr device)
+{
+ int i;
+ static struct ras_test_mask default_test_mask = RAS_BLOCK_MASK_QUERY_BASIC;
+
+ for (i = 0; i < sizeof(ras_DID_array) / sizeof(ras_DID_array[0]); i++) {
+ if (ras_DID_array[i].device_id == device->deviceinfo.pci->device_id &&
+ ras_DID_array[i].revision_id == device->deviceinfo.pci->revision_id)
+ return ras_DID_array[i].test_mask;
+ }
+ return default_test_mask;
+}
+
+static uint32_t amdgpu_ras_lookup_capability(amdgpu_device_handle device_handle)
+{
+ union {
+ uint64_t feature_mask;
+ struct {
+ uint32_t enabled_features;
+ uint32_t supported_features;
+ };
+ } features = { 0 };
+ int ret;
+
+ ret = amdgpu_query_info(device_handle, AMDGPU_INFO_RAS_ENABLED_FEATURES,
+ sizeof(features), &features);
+ if (ret)
+ return 0;
+
+ return features.supported_features;
+}
+
+static int get_file_contents(char *file, char *buf, int size);
+
+static int amdgpu_ras_lookup_id(drmDevicePtr device)
+{
+ char path[PATH_SIZE];
+ char str[128];
+ drmPciBusInfo info;
+ int i;
+ int ret;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED; i++) {
+ memset(str, 0, sizeof(str));
+ memset(&info, 0, sizeof(info));
+ snprintf(path, PATH_SIZE, "/sys/kernel/debug/dri/%d/name", i);
+ if (get_file_contents(path, str, sizeof(str)) <= 0)
+ continue;
+
+ ret = sscanf(str, "amdgpu dev=%04hx:%02hhx:%02hhx.%01hhx",
+ &info.domain, &info.bus, &info.dev, &info.func);
+ if (ret != 4)
+ continue;
+
+ if (memcmp(&info, device->businfo.pci, sizeof(info)) == 0)
+ return i;
+ }
+ return -1;
+}
+
+//helpers
+
+static int test_card;
+static char sysfs_path[PATH_SIZE];
+static char debugfs_path[PATH_SIZE];
+static uint32_t ras_mask;
+static amdgpu_device_handle device_handle;
+
+static void set_test_card(int card)
+{
+ test_card = card;
+ snprintf(sysfs_path, PATH_SIZE, "/sys/class/drm/card%d/device/ras/", devices[card].id);
+ snprintf(debugfs_path, PATH_SIZE, "/sys/kernel/debug/dri/%d/ras/", devices[card].id);
+ ras_mask = devices[card].capability;
+ device_handle = devices[card].device_handle;
+ ras_block_mask_inject = devices[card].test_mask.inject_mask;
+ ras_block_mask_query = devices[card].test_mask.query_mask;
+ ras_block_mask_basic = devices[card].test_mask.basic_mask;
+}
+
+static const char *get_ras_sysfs_root(void)
+{
+ return sysfs_path;
+}
+
+static const char *get_ras_debugfs_root(void)
+{
+ return debugfs_path;
+}
+
+static int set_file_contents(char *file, char *buf, int size)
+{
+ int n, fd;
+ fd = open(file, O_WRONLY);
+ if (fd == -1)
+ return -1;
+ n = write(fd, buf, size);
+ close(fd);
+ return n;
+}
+
+static int get_file_contents(char *file, char *buf, int size)
+{
+ int n, fd;
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ n = read(fd, buf, size);
+ close(fd);
+ return n;
+}
+
+static int is_file_ok(char *file, int flags)
+{
+ int fd;
+
+ fd = open(file, flags);
+ if (fd == -1)
+ return -1;
+ close(fd);
+ return 0;
+}
+
+static int amdgpu_ras_is_feature_enabled(enum amdgpu_ras_block block)
+{
+ uint32_t feature_mask;
+ int ret;
+
+ ret = amdgpu_query_info(device_handle, AMDGPU_INFO_RAS_ENABLED_FEATURES,
+ sizeof(feature_mask), &feature_mask);
+ if (ret)
+ return -1;
+
+ return (1 << block) & feature_mask;
+}
+
+static int amdgpu_ras_is_feature_supported(enum amdgpu_ras_block block)
+{
+ return (1 << block) & ras_mask;
+}
+
+static int amdgpu_ras_invoke(struct ras_debug_if *data)
+{
+ char path[PATH_SIZE];
+ int ret;
+
+ snprintf(path, sizeof(path), "%s", get_ras_debugfs_root());
+ strncat(path, "ras_ctrl", sizeof(path) - strlen(path));
+
+ ret = set_file_contents(path, (char *)data, sizeof(*data))
+ - sizeof(*data);
+ return ret;
+}
+
+static int amdgpu_ras_query_err_count(enum amdgpu_ras_block block,
+ unsigned long *ue, unsigned long *ce)
+{
+ char buf[64];
+ char name[PATH_SIZE];
+
+ *ue = *ce = 0;
+
+ if (amdgpu_ras_is_feature_supported(block) <= 0)
+ return -1;
+
+ snprintf(name, sizeof(name), "%s", get_ras_sysfs_root());
+ strncat(name, ras_block_str(block), sizeof(name) - strlen(name));
+ strncat(name, "_err_count", sizeof(name) - strlen(name));
+
+ if (is_file_ok(name, O_RDONLY))
+ return 0;
+
+ if (get_file_contents(name, buf, sizeof(buf)) <= 0)
+ return -1;
+
+ if (sscanf(buf, "ue: %lu\nce: %lu", ue, ce) != 2)
+ return -1;
+
+ return 0;
+}
+
+static int amdgpu_ras_inject(enum amdgpu_ras_block block,
+ uint32_t sub_block, enum amdgpu_ras_error_type type,
+ uint64_t address, uint64_t value)
+{
+ struct ras_debug_if data = { .op = 2, };
+ struct ras_inject_if *inject = &data.inject;
+ int ret;
+
+ if (amdgpu_ras_is_feature_enabled(block) <= 0) {
+ fprintf(stderr, "block id(%d) is not valid\n", block);
+ return -1;
+ }
+
+ inject->head.block = block;
+ inject->head.type = type;
+ inject->head.sub_block_index = sub_block;
+ strncpy(inject->head.name, ras_block_str(block), sizeof(inject->head.name)-1);
+ inject->address = address;
+ inject->value = value;
+
+ ret = amdgpu_ras_invoke(&data);
+ CU_ASSERT_EQUAL(ret, 0);
+ if (ret)
+ return -1;
+
+ return 0;
+}
+
+//tests
+static void amdgpu_ras_features_test(int enable)
+{
+ struct ras_debug_if data;
+ int ret;
+ int i;
+
+ data.op = enable;
+ for (i = 0; i < AMDGPU_RAS_BLOCK__LAST; i++) {
+ struct ras_common_if head = {
+ .block = i,
+ .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ .sub_block_index = 0,
+ .name = "",
+ };
+
+ if (amdgpu_ras_is_feature_supported(i) <= 0)
+ continue;
+
+ data.head = head;
+
+ ret = amdgpu_ras_invoke(&data);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ if (ret)
+ continue;
+
+ ret = enable ^ amdgpu_ras_is_feature_enabled(i);
+ CU_ASSERT_EQUAL(ret, 0);
+ }
+}
+
+static void amdgpu_ras_disable_test(void)
+{
+ int i;
+ for (i = 0; i < devices_count; i++) {
+ set_test_card(i);
+ amdgpu_ras_features_test(0);
+ }
+}
+
+static void amdgpu_ras_enable_test(void)
+{
+ int i;
+ for (i = 0; i < devices_count; i++) {
+ set_test_card(i);
+ amdgpu_ras_features_test(1);
+ }
+}
+
+static void __amdgpu_ras_ip_inject_test(const struct ras_inject_test_config *ip_test,
+ uint32_t size)
+{
+ int i, ret;
+ unsigned long old_ue, old_ce;
+ unsigned long ue, ce;
+ uint32_t block;
+ int timeout;
+ bool pass;
+
+ for (i = 0; i < size; i++) {
+ timeout = 3;
+ pass = false;
+
+ block = amdgpu_ras_find_block_id_by_name(ip_test[i].block);
+
+ /* Ensure one valid ip block */
+ if (block == ARRAY_SIZE(ras_block_string))
+ break;
+
+ /* Ensure RAS feature for the IP block is enabled by kernel */
+ if (amdgpu_ras_is_feature_supported(block) <= 0)
+ break;
+
+ ret = amdgpu_ras_query_err_count(block, &old_ue, &old_ce);
+ CU_ASSERT_EQUAL(ret, 0);
+ if (ret)
+ break;
+
+ ret = amdgpu_ras_inject(block,
+ ip_test[i].sub_block,
+ ip_test[i].type,
+ ip_test[i].address,
+ ip_test[i].value);
+ CU_ASSERT_EQUAL(ret, 0);
+ if (ret)
+ break;
+
+ while (timeout > 0) {
+ sleep(5);
+
+ ret = amdgpu_ras_query_err_count(block, &ue, &ce);
+ CU_ASSERT_EQUAL(ret, 0);
+ if (ret)
+ break;
+
+ if (old_ue != ue || old_ce != ce) {
+ pass = true;
+ sleep(20);
+ break;
+ }
+ timeout -= 1;
+ }
+ printf("\t Test %s@block %s, subblock %d, error_type %s, address %ld, value %ld: %s\n",
+ ip_test[i].name,
+ ip_test[i].block,
+ ip_test[i].sub_block,
+ amdgpu_ras_get_error_type_id(ip_test[i].type),
+ ip_test[i].address,
+ ip_test[i].value,
+ pass ? "Pass" : "Fail");
+ }
+}
+
+static void __amdgpu_ras_inject_test(void)
+{
+ printf("...\n");
+
+ /* run UMC ras inject test */
+ __amdgpu_ras_ip_inject_test(umc_ras_inject_test,
+ ARRAY_SIZE(umc_ras_inject_test));
+
+ /* run GFX ras inject test */
+ __amdgpu_ras_ip_inject_test(gfx_ras_inject_test,
+ ARRAY_SIZE(gfx_ras_inject_test));
+}
+
+static void amdgpu_ras_inject_test(void)
+{
+ int i;
+ for (i = 0; i < devices_count; i++) {
+ set_test_card(i);
+ __amdgpu_ras_inject_test();
+ }
+}
+
+static void __amdgpu_ras_query_test(void)
+{
+ unsigned long ue, ce;
+ int ret;
+ int i;
+
+ for (i = 0; i < AMDGPU_RAS_BLOCK__LAST; i++) {
+ if (amdgpu_ras_is_feature_supported(i) <= 0)
+ continue;
+
+ if (!((1 << i) & ras_block_mask_query))
+ continue;
+
+ ret = amdgpu_ras_query_err_count(i, &ue, &ce);
+ CU_ASSERT_EQUAL(ret, 0);
+ }
+}
+
+static void amdgpu_ras_query_test(void)
+{
+ int i;
+ for (i = 0; i < devices_count; i++) {
+ set_test_card(i);
+ __amdgpu_ras_query_test();
+ }
+}
+
+static void amdgpu_ras_basic_test(void)
+{
+ int ret;
+ int i;
+ int j;
+ uint32_t features;
+ char path[PATH_SIZE];
+
+ ret = is_file_ok("/sys/module/amdgpu/parameters/ras_mask", O_RDONLY);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ for (i = 0; i < devices_count; i++) {
+ set_test_card(i);
+
+ ret = amdgpu_query_info(device_handle, AMDGPU_INFO_RAS_ENABLED_FEATURES,
+ sizeof(features), &features);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ snprintf(path, sizeof(path), "%s", get_ras_debugfs_root());
+ strncat(path, "ras_ctrl", sizeof(path) - strlen(path));
+
+ ret = is_file_ok(path, O_WRONLY);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ snprintf(path, sizeof(path), "%s", get_ras_sysfs_root());
+ strncat(path, "features", sizeof(path) - strlen(path));
+
+ ret = is_file_ok(path, O_RDONLY);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ for (j = 0; j < AMDGPU_RAS_BLOCK__LAST; j++) {
+ ret = amdgpu_ras_is_feature_supported(j);
+ if (ret <= 0)
+ continue;
+
+ if (!((1 << j) & ras_block_mask_basic))
+ continue;
+
+ snprintf(path, sizeof(path), "%s", get_ras_sysfs_root());
+ strncat(path, ras_block_str(j), sizeof(path) - strlen(path));
+ strncat(path, "_err_count", sizeof(path) - strlen(path));
+
+ ret = is_file_ok(path, O_RDONLY);
+ CU_ASSERT_EQUAL(ret, 0);
+
+ snprintf(path, sizeof(path), "%s", get_ras_debugfs_root());
+ strncat(path, ras_block_str(j), sizeof(path) - strlen(path));
+ strncat(path, "_err_inject", sizeof(path) - strlen(path));
+
+ ret = is_file_ok(path, O_WRONLY);
+ CU_ASSERT_EQUAL(ret, 0);
+ }
+ }
+}
+
+CU_TestInfo ras_tests[] = {
+ { "ras basic test", amdgpu_ras_basic_test },
+ { "ras query test", amdgpu_ras_query_test },
+ { "ras inject test", amdgpu_ras_inject_test },
+ { "ras disable test", amdgpu_ras_disable_test },
+ { "ras enable test", amdgpu_ras_enable_test },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_ras_tests_enable(void)
+{
+ amdgpu_device_handle device_handle;
+ uint32_t major_version;
+ uint32_t minor_version;
+ int i;
+ drmDevicePtr device;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
+ if (amdgpu_device_initialize(drm_amdgpu[i], &major_version,
+ &minor_version, &device_handle))
+ continue;
+
+ if (drmGetDevice2(drm_amdgpu[i],
+ DRM_DEVICE_GET_PCI_REVISION,
+ &device))
+ continue;
+
+ if (device->bustype == DRM_BUS_PCI &&
+ amdgpu_ras_lookup_capability(device_handle)) {
+ amdgpu_device_deinitialize(device_handle);
+ return CU_TRUE;
+ }
+
+ if (amdgpu_device_deinitialize(device_handle))
+ continue;
+ }
+
+ return CU_FALSE;
+}
+
+int suite_ras_tests_init(void)
+{
+ drmDevicePtr device;
+ amdgpu_device_handle device_handle;
+ uint32_t major_version;
+ uint32_t minor_version;
+ uint32_t capability;
+ struct ras_test_mask test_mask;
+ int id;
+ int i;
+ int r;
+
+ for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
+ r = amdgpu_device_initialize(drm_amdgpu[i], &major_version,
+ &minor_version, &device_handle);
+ if (r)
+ continue;
+
+ if (drmGetDevice2(drm_amdgpu[i],
+ DRM_DEVICE_GET_PCI_REVISION,
+ &device)) {
+ amdgpu_device_deinitialize(device_handle);
+ continue;
+ }
+
+ if (device->bustype != DRM_BUS_PCI) {
+ amdgpu_device_deinitialize(device_handle);
+ continue;
+ }
+
+ capability = amdgpu_ras_lookup_capability(device_handle);
+ if (capability == 0) {
+ amdgpu_device_deinitialize(device_handle);
+ continue;
+
+ }
+
+ id = amdgpu_ras_lookup_id(device);
+ if (id == -1) {
+ amdgpu_device_deinitialize(device_handle);
+ continue;
+ }
+
+ test_mask = amdgpu_ras_get_test_mask(device);
+
+ devices[devices_count++] = (struct amdgpu_ras_data) {
+ device_handle, id, capability, test_mask,
+ };
+ }
+
+ if (devices_count == 0)
+ return CUE_SINIT_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+int suite_ras_tests_clean(void)
+{
+ int r;
+ int i;
+ int ret = CUE_SUCCESS;
+
+ for (i = 0; i < devices_count; i++) {
+ r = amdgpu_device_deinitialize(devices[i].device_handle);
+ if (r)
+ ret = CUE_SCLEAN_FAILED;
+ }
+ return ret;
+}
diff --git a/tests/amdgpu/security_tests.c b/tests/amdgpu/security_tests.c
new file mode 100644
index 0000000..e6c9f9a
--- /dev/null
+++ b/tests/amdgpu/security_tests.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#include <string.h>
+#include <unistd.h>
+#ifdef __FreeBSD__
+#include <sys/endian.h>
+#else
+#include <endian.h>
+#endif
+#include <strings.h>
+#include <xf86drm.h>
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+
+static struct drm_amdgpu_info_hw_ip sdma_info;
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(_Arr) (sizeof(_Arr)/sizeof((_Arr)[0]))
+#endif
+
+
+/* --------------------- Secure bounce test ------------------------ *
+ *
+ * The secure bounce test tests that we can evict a TMZ buffer,
+ * and page it back in, via a bounce buffer, as it encryption/decryption
+ * depends on its physical address, and have the same data, i.e. data
+ * integrity is preserved.
+ *
+ * The steps are as follows (from Christian K.):
+ *
+ * Buffer A which is TMZ protected and filled by the CPU with a
+ * certain pattern. That the GPU is reading only random nonsense from
+ * that pattern is irrelevant for the test.
+ *
+ * This buffer A is then secure copied into buffer B which is also
+ * TMZ protected.
+ *
+ * Buffer B is moved around, from VRAM to GTT, GTT to SYSTEM,
+ * etc.
+ *
+ * Then, we use another secure copy of buffer B back to buffer A.
+ *
+ * And lastly we check with the CPU the pattern.
+ *
+ * Assuming that we don't have memory contention and buffer A stayed
+ * at the same place, we should still see the same pattern when read
+ * by the CPU.
+ *
+ * If we don't see the same pattern then something in the buffer
+ * migration code is not working as expected.
+ */
+
+#define SECURE_BOUNCE_TEST_STR "secure bounce"
+#define SECURE_BOUNCE_FAILED_STR SECURE_BOUNCE_TEST_STR " failed"
+
+#define PRINT_ERROR(_Res) fprintf(stderr, "%s:%d: %s (%d)\n", \
+ __func__, __LINE__, strerror(-(_Res)), _Res)
+
+#define PACKET_LCOPY_SIZE 7
+#define PACKET_NOP_SIZE 12
+
+struct sec_amdgpu_bo {
+ struct amdgpu_bo *bo;
+ struct amdgpu_va *va;
+};
+
+struct command_ctx {
+ struct amdgpu_device *dev;
+ struct amdgpu_cs_ib_info cs_ibinfo;
+ struct amdgpu_cs_request cs_req;
+ struct amdgpu_context *context;
+ int ring_id;
+};
+
+/**
+ * amdgpu_bo_alloc_map -- Allocate and map a buffer object (BO)
+ * @dev: The AMDGPU device this BO belongs to.
+ * @size: The size of the BO.
+ * @alignment: Alignment of the BO.
+ * @gem_domain: One of AMDGPU_GEM_DOMAIN_xyz.
+ * @alloc_flags: One of AMDGPU_GEM_CREATE_xyz.
+ * @sbo: the result
+ *
+ * Allocate a buffer object (BO) with the desired attributes
+ * as specified by the argument list and write out the result
+ * into @sbo.
+ *
+ * Return 0 on success and @sbo->bo and @sbo->va are set,
+ * or -errno on error.
+ */
+static int amdgpu_bo_alloc_map(struct amdgpu_device *dev,
+ unsigned size,
+ unsigned alignment,
+ unsigned gem_domain,
+ uint64_t alloc_flags,
+ struct sec_amdgpu_bo *sbo)
+{
+ void *cpu;
+ uint64_t mc_addr;
+
+ return amdgpu_bo_alloc_and_map_raw(dev,
+ size,
+ alignment,
+ gem_domain,
+ alloc_flags,
+ 0,
+ &sbo->bo,
+ &cpu, &mc_addr,
+ &sbo->va);
+}
+
+static void amdgpu_bo_unmap_free(struct sec_amdgpu_bo *sbo,
+ const uint64_t size)
+{
+ (void) amdgpu_bo_unmap_and_free(sbo->bo,
+ sbo->va,
+ sbo->va->address,
+ size);
+ sbo->bo = NULL;
+ sbo->va = NULL;
+}
+
+static void amdgpu_sdma_lcopy(uint32_t *packet,
+ const uint64_t dst,
+ const uint64_t src,
+ const uint32_t size,
+ const int secure)
+{
+ /* Set the packet to Linear copy with TMZ set.
+ */
+ packet[0] = htole32(secure << 18 | 1);
+ packet[1] = htole32(size-1);
+ packet[2] = htole32(0);
+ packet[3] = htole32((uint32_t)(src & 0xFFFFFFFFU));
+ packet[4] = htole32((uint32_t)(src >> 32));
+ packet[5] = htole32((uint32_t)(dst & 0xFFFFFFFFU));
+ packet[6] = htole32((uint32_t)(dst >> 32));
+}
+
+static void amdgpu_sdma_nop(uint32_t *packet, uint32_t nop_count)
+{
+ /* A packet of the desired number of NOPs.
+ */
+ packet[0] = htole32(nop_count << 16);
+ for ( ; nop_count > 0; nop_count--)
+ packet[nop_count-1] = 0;
+}
+
+/**
+ * amdgpu_bo_lcopy -- linear copy with TMZ set, using sDMA
+ * @dev: AMDGPU device to which both buffer objects belong to
+ * @dst: destination buffer object
+ * @src: source buffer object
+ * @size: size of memory to move, in bytes.
+ * @secure: Set to 1 to perform secure copy, 0 for clear
+ *
+ * Issues and waits for completion of a Linear Copy with TMZ
+ * set, to the sDMA engine. @size should be a multiple of
+ * at least 16 bytes.
+ */
+static void amdgpu_bo_lcopy(struct command_ctx *ctx,
+ struct sec_amdgpu_bo *dst,
+ struct sec_amdgpu_bo *src,
+ const uint32_t size,
+ int secure)
+{
+ struct amdgpu_bo *bos[] = { dst->bo, src->bo };
+ uint32_t packet[PACKET_LCOPY_SIZE];
+
+ amdgpu_sdma_lcopy(packet,
+ dst->va->address,
+ src->va->address,
+ size, secure);
+ amdgpu_test_exec_cs_helper_raw(ctx->dev, ctx->context,
+ AMDGPU_HW_IP_DMA, ctx->ring_id,
+ ARRAY_SIZE(packet), packet,
+ ARRAY_SIZE(bos), bos,
+ &ctx->cs_ibinfo, &ctx->cs_req,
+ secure == 1);
+}
+
+/**
+ * amdgpu_bo_move -- Evoke a move of the buffer object (BO)
+ * @dev: device to which this buffer object belongs to
+ * @bo: the buffer object to be moved
+ * @whereto: one of AMDGPU_GEM_DOMAIN_xyz
+ * @secure: set to 1 to submit secure IBs
+ *
+ * Evokes a move of the buffer object @bo to the GEM domain
+ * descibed by @whereto.
+ *
+ * Returns 0 on sucess; -errno on error.
+ */
+static int amdgpu_bo_move(struct command_ctx *ctx,
+ struct amdgpu_bo *bo,
+ uint64_t whereto,
+ int secure)
+{
+ struct amdgpu_bo *bos[] = { bo };
+ struct drm_amdgpu_gem_op gop = {
+ .handle = bo->handle,
+ .op = AMDGPU_GEM_OP_SET_PLACEMENT,
+ .value = whereto,
+ };
+ uint32_t packet[PACKET_NOP_SIZE];
+ int res;
+
+ /* Change the buffer's placement.
+ */
+ res = drmIoctl(ctx->dev->fd, DRM_IOCTL_AMDGPU_GEM_OP, &gop);
+ if (res)
+ return -errno;
+
+ /* Now issue a NOP to actually evoke the MM to move
+ * it to the desired location.
+ */
+ amdgpu_sdma_nop(packet, PACKET_NOP_SIZE);
+ amdgpu_test_exec_cs_helper_raw(ctx->dev, ctx->context,
+ AMDGPU_HW_IP_DMA, ctx->ring_id,
+ ARRAY_SIZE(packet), packet,
+ ARRAY_SIZE(bos), bos,
+ &ctx->cs_ibinfo, &ctx->cs_req,
+ secure == 1);
+ return 0;
+}
+
+/* Safe, O Sec!
+ */
+static const uint8_t secure_pattern[] = { 0x5A, 0xFE, 0x05, 0xEC };
+
+#define SECURE_BUFFER_SIZE (4 * 1024 * sizeof(secure_pattern))
+
+static void amdgpu_secure_bounce(void)
+{
+ struct sec_amdgpu_bo alice, bob;
+ struct command_ctx sb_ctx;
+ long page_size;
+ uint8_t *pp;
+ int res;
+
+ page_size = sysconf(_SC_PAGESIZE);
+
+ memset(&sb_ctx, 0, sizeof(sb_ctx));
+ sb_ctx.dev = device_handle;
+ res = amdgpu_cs_ctx_create(sb_ctx.dev, &sb_ctx.context);
+ if (res) {
+ PRINT_ERROR(res);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ return;
+ }
+
+ /* Use the first present ring.
+ */
+ res = ffs(sdma_info.available_rings) - 1;
+ if (res == -1) {
+ PRINT_ERROR(-ENOENT);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ goto Out_free_ctx;
+ }
+ sb_ctx.ring_id = res;
+
+ /* Allocate a buffer named Alice in VRAM.
+ */
+ res = amdgpu_bo_alloc_map(device_handle,
+ SECURE_BUFFER_SIZE,
+ page_size,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_CREATE_ENCRYPTED,
+ &alice);
+ if (res) {
+ PRINT_ERROR(res);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ return;
+ }
+
+ /* Fill Alice with a pattern.
+ */
+ for (pp = alice.bo->cpu_ptr;
+ pp < (__typeof__(pp)) alice.bo->cpu_ptr + SECURE_BUFFER_SIZE;
+ pp += sizeof(secure_pattern))
+ memcpy(pp, secure_pattern, sizeof(secure_pattern));
+
+ /* Allocate a buffer named Bob in VRAM.
+ */
+ res = amdgpu_bo_alloc_map(device_handle,
+ SECURE_BUFFER_SIZE,
+ page_size,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_CREATE_ENCRYPTED,
+ &bob);
+ if (res) {
+ PRINT_ERROR(res);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ goto Out_free_Alice;
+ }
+
+ /* sDMA TMZ copy from Alice to Bob.
+ */
+ amdgpu_bo_lcopy(&sb_ctx, &bob, &alice, SECURE_BUFFER_SIZE, 1);
+
+ /* Move Bob to the GTT domain.
+ */
+ res = amdgpu_bo_move(&sb_ctx, bob.bo, AMDGPU_GEM_DOMAIN_GTT, 0);
+ if (res) {
+ PRINT_ERROR(res);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ goto Out_free_all;
+ }
+
+ /* sDMA TMZ copy from Bob to Alice.
+ */
+ amdgpu_bo_lcopy(&sb_ctx, &alice, &bob, SECURE_BUFFER_SIZE, 1);
+
+ /* Verify the contents of Alice.
+ */
+ for (pp = alice.bo->cpu_ptr;
+ pp < (__typeof__(pp)) alice.bo->cpu_ptr + SECURE_BUFFER_SIZE;
+ pp += sizeof(secure_pattern)) {
+ res = memcmp(pp, secure_pattern, sizeof(secure_pattern));
+ if (res) {
+ fprintf(stderr, SECURE_BOUNCE_FAILED_STR);
+ CU_FAIL(SECURE_BOUNCE_FAILED_STR);
+ break;
+ }
+ }
+
+Out_free_all:
+ amdgpu_bo_unmap_free(&bob, SECURE_BUFFER_SIZE);
+Out_free_Alice:
+ amdgpu_bo_unmap_free(&alice, SECURE_BUFFER_SIZE);
+Out_free_ctx:
+ res = amdgpu_cs_ctx_free(sb_ctx.context);
+ CU_ASSERT_EQUAL(res, 0);
+}
+
+/* ----------------------------------------------------------------- */
+
+static void amdgpu_security_alloc_buf_test(void)
+{
+ amdgpu_bo_handle bo;
+ amdgpu_va_handle va_handle;
+ uint64_t bo_mc;
+ int r;
+
+ /* Test secure buffer allocation in VRAM */
+ bo = gpu_mem_alloc(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_CREATE_ENCRYPTED,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test secure buffer allocation in system memory */
+ bo = gpu_mem_alloc(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ AMDGPU_GEM_CREATE_ENCRYPTED,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* Test secure buffer allocation in invisible VRAM */
+ bo = gpu_mem_alloc(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT,
+ AMDGPU_GEM_CREATE_ENCRYPTED |
+ AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
+ &bo_mc, &va_handle);
+
+ r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_security_gfx_submission_test(void)
+{
+ amdgpu_command_submission_write_linear_helper_with_secure(device_handle,
+ AMDGPU_HW_IP_GFX,
+ true);
+}
+
+static void amdgpu_security_sdma_submission_test(void)
+{
+ amdgpu_command_submission_write_linear_helper_with_secure(device_handle,
+ AMDGPU_HW_IP_DMA,
+ true);
+}
+
+/* ----------------------------------------------------------------- */
+
+CU_TestInfo security_tests[] = {
+ { "allocate secure buffer test", amdgpu_security_alloc_buf_test },
+ { "graphics secure command submission", amdgpu_security_gfx_submission_test },
+ { "sDMA secure command submission", amdgpu_security_sdma_submission_test },
+ { SECURE_BOUNCE_TEST_STR, amdgpu_secure_bounce },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_security_tests_enable(void)
+{
+ CU_BOOL enable = CU_TRUE;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+
+ if (!(device_handle->dev_info.ids_flags & AMDGPU_IDS_FLAGS_TMZ)) {
+ printf("\n\nDon't support TMZ (trust memory zone), security suite disabled\n");
+ enable = CU_FALSE;
+ }
+
+ if ((major_version < 3) ||
+ ((major_version == 3) && (minor_version < 37))) {
+ printf("\n\nDon't support TMZ (trust memory zone), kernel DRM version (%d.%d)\n",
+ major_version, minor_version);
+ printf("is older, security suite disabled\n");
+ enable = CU_FALSE;
+ }
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ return enable;
+}
+
+int suite_security_tests_init(void)
+{
+ int res;
+
+ res = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (res) {
+ PRINT_ERROR(res);
+ return CUE_SINIT_FAILED;
+ }
+
+ res = amdgpu_query_hw_ip_info(device_handle,
+ AMDGPU_HW_IP_DMA,
+ 0, &sdma_info);
+ if (res) {
+ PRINT_ERROR(res);
+ return CUE_SINIT_FAILED;
+ }
+
+ return CUE_SUCCESS;
+}
+
+int suite_security_tests_clean(void)
+{
+ int res;
+
+ res = amdgpu_device_deinitialize(device_handle);
+ if (res)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
diff --git a/tests/amdgpu/shader_code.h b/tests/amdgpu/shader_code.h
new file mode 100644
index 0000000..74d32bb
--- /dev/null
+++ b/tests/amdgpu/shader_code.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _shader_code_h_
+#define _shader_code_h_
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+enum amdgpu_test_gfx_version {
+ AMDGPU_TEST_GFX_V9 = 0,
+ AMDGPU_TEST_GFX_V10,
+ AMDGPU_TEST_GFX_V11,
+ AMDGPU_TEST_GFX_MAX,
+};
+
+enum cs_type {
+ CS_BUFFERCLEAR = 0,
+ CS_BUFFERCOPY,
+ CS_HANG,
+ CS_HANG_SLOW,
+};
+
+enum ps_type {
+ PS_CONST,
+ PS_TEX,
+ PS_HANG,
+ PS_HANG_SLOW
+};
+
+enum vs_type {
+ VS_RECTPOSTEXFAST,
+};
+
+struct reg_info {
+ uint32_t reg_offset; ///< Memory mapped register offset
+ uint32_t reg_value; ///< register value
+};
+
+#include "shader_code_hang.h"
+#include "shader_code_gfx9.h"
+#include "shader_code_gfx10.h"
+#include "shader_code_gfx11.h"
+
+struct shader_test_cs_shader {
+ const uint32_t *shader;
+ uint32_t shader_size;
+ const struct reg_info *sh_reg;
+ uint32_t num_sh_reg;
+ const struct reg_info *context_reg;
+ uint32_t num_context_reg;
+};
+
+struct shader_test_ps_shader {
+ const uint32_t *shader;
+ unsigned shader_size;
+ const uint32_t patchinfo_code_size;
+ const uint32_t *patchinfo_code;
+ const uint32_t *patchinfo_code_offset;
+ const struct reg_info *sh_reg;
+ const uint32_t num_sh_reg;
+ const struct reg_info *context_reg;
+ const uint32_t num_context_reg;
+};
+
+struct shader_test_vs_shader {
+ const uint32_t *shader;
+ uint32_t shader_size;
+ const struct reg_info *sh_reg;
+ uint32_t num_sh_reg;
+ const struct reg_info *context_reg;
+ uint32_t num_context_reg;
+};
+
+static const struct shader_test_cs_shader shader_test_cs[AMDGPU_TEST_GFX_MAX][2] = {
+ // gfx9, cs_bufferclear
+ {{bufferclear_cs_shader_gfx9, sizeof(bufferclear_cs_shader_gfx9), bufferclear_cs_shader_registers_gfx9, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx9)},
+ // gfx9, cs_buffercopy
+ {buffercopy_cs_shader_gfx9, sizeof(buffercopy_cs_shader_gfx9), bufferclear_cs_shader_registers_gfx9, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx9)}},
+ // gfx10, cs_bufferclear
+ {{bufferclear_cs_shader_gfx10, sizeof(bufferclear_cs_shader_gfx10), bufferclear_cs_shader_registers_gfx9, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx9)},
+ // gfx10, cs_buffercopy
+ {buffercopy_cs_shader_gfx10, sizeof(bufferclear_cs_shader_gfx10), bufferclear_cs_shader_registers_gfx9, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx9)}},
+ // gfx11, cs_bufferclear
+ {{bufferclear_cs_shader_gfx11, sizeof(bufferclear_cs_shader_gfx11), bufferclear_cs_shader_registers_gfx11, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx11)},
+ // gfx11, cs_buffercopy
+ {buffercopy_cs_shader_gfx11, sizeof(bufferclear_cs_shader_gfx11), bufferclear_cs_shader_registers_gfx11, ARRAY_SIZE(bufferclear_cs_shader_registers_gfx11)}},
+};
+
+#define SHADER_PS_INFO(_ps, _n) \
+ {ps_##_ps##_shader_gfx##_n, sizeof(ps_##_ps##_shader_gfx##_n), \
+ ps_##_ps##_shader_patchinfo_code_size_gfx##_n, \
+ ps_##_ps##_shader_patchinfo_code_gfx##_n, \
+ ps_##_ps##_shader_patchinfo_offset_gfx##_n, \
+ ps_##_ps##_sh_registers_gfx##_n, ps_##_ps##_num_sh_registers_gfx##_n, \
+ ps_##_ps##_context_registers_gfx##_n, ps_##_ps##_num_context_registers_gfx##_n}
+static const struct shader_test_ps_shader shader_test_ps[AMDGPU_TEST_GFX_MAX][2] = {
+ {SHADER_PS_INFO(const, 9), SHADER_PS_INFO(tex, 9)},
+ {SHADER_PS_INFO(const, 10), SHADER_PS_INFO(tex, 10)},
+ {SHADER_PS_INFO(const, 11), SHADER_PS_INFO(tex, 11)},
+};
+
+#define SHADER_VS_INFO(_vs, _n) \
+ {vs_##_vs##_shader_gfx##_n, sizeof(vs_##_vs##_shader_gfx##_n), \
+ vs_##_vs##_sh_registers_gfx##_n, vs_##_vs##_num_sh_registers_gfx##_n, \
+ vs_##_vs##_context_registers_gfx##_n, vs_##_vs##_num_context_registers_gfx##_n}
+static const struct shader_test_vs_shader shader_test_vs[AMDGPU_TEST_GFX_MAX][1] = {
+ {SHADER_VS_INFO(RectPosTexFast, 9)},
+ {SHADER_VS_INFO(RectPosTexFast, 10)},
+ {SHADER_VS_INFO(RectPosTexFast, 11)},
+};
+
+struct shader_test_gfx_info {
+ const uint32_t *preamble_cache;
+ uint32_t size_preamble_cache;
+ const uint32_t *cached_cmd;
+ uint32_t size_cached_cmd;
+ uint32_t sh_reg_base;
+ uint32_t context_reg_base;
+};
+
+#define SHADER_TEST_GFX_INFO(_n) \
+ preamblecache_gfx##_n, sizeof(preamblecache_gfx##_n), \
+ cached_cmd_gfx##_n, sizeof(cached_cmd_gfx##_n), \
+ sh_reg_base_gfx##_n, context_reg_base_gfx##_n
+
+static struct shader_test_gfx_info shader_test_gfx_info[AMDGPU_TEST_GFX_MAX] = {
+ {SHADER_TEST_GFX_INFO(9),},
+ {SHADER_TEST_GFX_INFO(10),},
+ {SHADER_TEST_GFX_INFO(11),},
+};
+#endif
diff --git a/tests/amdgpu/shader_code_gfx10.h b/tests/amdgpu/shader_code_gfx10.h
new file mode 100644
index 0000000..4849bbc
--- /dev/null
+++ b/tests/amdgpu/shader_code_gfx10.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _shader_code_gfx10_h_
+#define _shader_code_gfx10_h_
+
+static const uint32_t bufferclear_cs_shader_gfx10[] = {
+ 0xD7460004, 0x04010C08, 0x7E000204, 0x7E020205,
+ 0x7E040206, 0x7E060207, 0xE01C2000, 0x80000004,
+ 0xBF810000
+};
+
+static const uint32_t buffercopy_cs_shader_gfx10[] = {
+ 0xD7460001, 0x04010C08, 0xE00C2000, 0x80000201,
+ 0xBF8C3F70, 0xE01C2000, 0x80010201, 0xBF810000
+};
+
+static const uint32_t ps_const_shader_gfx10[] = {
+ 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203,
+ 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000,
+ 0xF8001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_const_shader_patchinfo_code_size_gfx10 = 6;
+
+static const uint32_t ps_const_shader_patchinfo_code_gfx10[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000300 },
+ { 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 },
+ { 0xD7690000, 0x00020300, 0xD7690001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD7680000, 0x00020300, 0xD7680001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD76A0000, 0x00020300, 0xD76A0001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xD76B0000, 0x00020300, 0xD76B0001, 0x00020702, 0xF8001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x03020100 }
+ }
+};
+
+static const uint32_t ps_const_shader_patchinfo_offset_gfx10[] = {
+ 0x00000004
+};
+
+static const uint32_t ps_const_num_sh_registers_gfx10 = 2;
+
+static const struct reg_info ps_const_sh_registers_gfx10[] = {
+ {0x2C0A, 0x000C0000},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0000 },
+ {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 }
+};
+
+static const struct reg_info ps_const_context_registers_gfx10[] =
+{
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000000}, //{ mmSPI_PS_IN_CONTROL, 0x00000000 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 /* SI_EXPORT_FMT_FP16_ABGR */ }
+};
+
+static const uint32_t ps_const_num_context_registers_gfx10 = 7;
+
+static const uint32_t ps_tex_shader_gfx10[] = {
+ 0xBEFC030C, 0xBE8E047E, 0xBEFE0A7E, 0xC8080000,
+ 0xC80C0100, 0xC8090001, 0xC80D0101, 0xF0800F0A,
+ 0x00400402, 0x00000003, 0xBEFE040E, 0xBF8C0F70,
+ 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000,
+ 0xF8001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_tex_shader_patchinfo_offset_gfx10[] = {
+ 0x0000000C
+};
+
+static const uint32_t ps_tex_shader_patchinfo_code_size_gfx10 = 6;
+
+static const uint32_t ps_tex_shader_patchinfo_code_gfx10[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000004 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000504 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000704 },
+ { 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 },
+ { 0xD7690000, 0x00020B04, 0xD7690001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD7680000, 0x00020B04, 0xD7680001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD76A0000, 0x00020B04, 0xD76A0001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xD76B0000, 0x00020B04, 0xD76B0001, 0x00020F06, 0xF8001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x07060504 }
+ }
+};
+
+static const struct reg_info ps_tex_sh_registers_gfx10[] =
+{
+ {0x2C0A, 0xc0081}, //0x020C0080 }, //{ mmSPI_SHADER_PGM_RSRC1_PS, 0x020C0080 },
+ {0x2C0B, 0x00000018 }, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000018 }
+};
+
+static const uint32_t ps_tex_num_sh_registers_gfx10 = 2;
+
+// Holds Context Register Information
+static const struct reg_info ps_tex_context_registers_gfx10[] =
+{
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000001}, //{ mmSPI_PS_IN_CONTROL, 0x00000001 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 /* SI_EXPORT_FMT_FP16_ABGR */ }
+};
+
+static const uint32_t ps_tex_num_context_registers_gfx10 = 7;
+
+static const uint32_t vs_RectPosTexFast_shader_gfx10[] = {
+ 0x7E000B00, 0x060000F3, 0x7E020202, 0x7E040206,
+ 0x7C040080, 0x060000F3, 0xD5010001, 0x01AA0200,
+ 0x7E060203, 0xD5010002, 0x01AA0404, 0x7E080207,
+ 0x7C040080, 0xD5010000, 0x01A80101, 0xD5010001,
+ 0x01AA0601, 0x7E060208, 0x7E0A02F2, 0xD5010002,
+ 0x01A80902, 0xD5010004, 0x01AA0805, 0x7E0C0209,
+ 0xF80008CF, 0x05030100, 0xF800020F, 0x05060402,
+ 0xBF810000
+};
+
+static const struct reg_info vs_RectPosTexFast_sh_registers_gfx10[] =
+{
+ {0x2C4A, 0x080C0041 }, //{ mmSPI_SHADER_PGM_RSRC1_VS, 0x080C0041 },
+ {0x2C4B, 0x00000018 }, //{ mmSPI_SHADER_PGM_RSRC2_VS, 0x00000018 }
+};
+
+static const uint32_t vs_RectPosTexFast_num_sh_registers_gfx10 = 2;
+
+// Holds Context Register Information
+static const struct reg_info vs_RectPosTexFast_context_registers_gfx10[] =
+{
+ {0xA1B1, 0x00000000}, //{ mmSPI_VS_OUT_CONFIG, 0x00000000 },
+ {0xA1C3, 0x00000000}, //{ mmSPI_SHADER_POS_FORMAT, 0x00000000 /* Always 0 for now */}
+};
+
+static const uint32_t vs_RectPosTexFast_num_context_registers_gfx10 = 2;
+
+static const uint32_t preamblecache_gfx10[] = {
+ 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0,
+ 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000,
+ 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0,
+ 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0,
+ 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0,
+ 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0,
+ 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0,
+ 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xc0046900, 0x310, 0, 0x3, 0, 0x100000, 0xc0026900, 0x316, 0xe, 0x20,
+ 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0,
+ 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x6, 0x0,
+ 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0,
+ 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff,
+ 0xc0016900, 0x314, 0x0, 0xc0016900, 0x10a, 0, 0xc0016900, 0x2a6, 0, 0xc0016900, 0x210, 0,
+ 0xc0016900, 0x2db, 0, 0xc0016900, 0x1d4, 0, 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1, 0xc0016900, 0xe, 0x2,
+ 0xc0016900, 0x206, 0x300, 0xc0016900, 0x212, 0x200, 0xc0017900, 0x7b, 0x20, 0xc0017a00, 0x20000243, 0x0,
+ 0xc0017900, 0x249, 0, 0xc0017900, 0x24a, 0, 0xc0017900, 0x24b, 0, 0xc0017900, 0x259, 0xffffffff,
+ 0xc0017900, 0x25f, 0, 0xc0017900, 0x260, 0, 0xc0017900, 0x262, 0,
+ 0xc0017600, 0x45, 0x0, 0xc0017600, 0x6, 0x0,
+ 0xc0067600, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0067600, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+static const uint32_t cached_cmd_gfx10[] = {
+ 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0,
+ 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020,
+ 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf,
+ 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x18,
+ 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0,
+ 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011,
+ 0xc0026900, 0x292, 0x20, 0x6020000,
+ 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0
+};
+
+static const uint32_t sh_reg_base_gfx10 = 0x2C00;
+static const uint32_t context_reg_base_gfx10 = 0xA000;
+
+#endif
diff --git a/tests/amdgpu/shader_code_gfx11.h b/tests/amdgpu/shader_code_gfx11.h
new file mode 100644
index 0000000..d9ee0a7
--- /dev/null
+++ b/tests/amdgpu/shader_code_gfx11.h
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _shader_code_gfx11_h_
+#define _shader_code_gfx11_h_
+
+static const uint32_t bufferclear_cs_shader_gfx11[] = {
+ 0xB0802006, 0xBF840003, 0x360000FF, 0x000003FF,
+ 0x7E020205, 0x7E040206, 0x7E060207, 0xBF870004,
+ 0xD6460004, 0x04010C08, 0x7E000204, 0xE01C0000,
+ 0x80800004, 0xBFB60003, 0xBFB00000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000
+};
+
+static const struct reg_info bufferclear_cs_shader_registers_gfx11[] = {
+ {0x2e12, 0x600C0041}, //{ mmCOMPUTE_PGM_RSRC1, 0x600C0041 },
+ {0x2e13, 0x00000090}, //{ mmCOMPUTE_PGM_RSRC2, 0x00000090 },
+ {0x2e07, 0x00000040}, //{ mmCOMPUTE_NUM_THREAD_X, 0x00000040 },
+ {0x2e08, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Y, 0x00000001 },
+ {0x2e09, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Z, 0x00000001 }
+};
+
+static const uint32_t buffercopy_cs_shader_gfx11[] = {
+ 0xB0802006, 0xBF840003, 0x360000FF, 0x000003FF,
+ 0xBF870001, 0xD6460001, 0x04010C08, 0xE00C0000,
+ 0x80800201, 0xBF8903F7, 0xE01C0000, 0x80810201,
+ 0xBFB60003, 0xBFB00000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000
+};
+
+static const uint32_t ps_const_shader_gfx11[] = {
+ 0xB0802006, 0xBF840003, 0x7E000200, 0x7E020201,
+ 0x7E040202, 0x7E060203, 0x5E000300, 0x5E020702,
+ 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100,
+ 0xBFB00000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000
+};
+
+static const uint32_t ps_const_shader_patchinfo_code_size_gfx11 = 6;
+
+static const uint32_t ps_const_shader_patchinfo_code_gfx11[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000890, 0x00000000 }, // SI_EXPORT_FMT_ZERO
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000801, 0x00000000 }, // SI_EXPORT_FMT_32_R
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_32_GR
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000300 }, // SI_EXPORT_FMT_32_AR
+ { 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_FP16_ABGR
+ { 0xD7220000, 0x00020300, 0xD7220001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_UNORM16_ABGR
+ { 0xD7210000, 0x00020300, 0xD7210001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_SNORM16_ABGR
+ { 0xD7230000, 0x00020300, 0xD7230001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_uint32_t16_ABGR
+ { 0xD7240000, 0x00020300, 0xD7240001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_SINT16_ABGR
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800080F, 0x03020100 } // SI_EXPORT_FMT_32_ABGR
+ }
+};
+
+static const uint32_t ps_const_shader_patchinfo_offset_gfx11[] = {
+ 0x00000006
+};
+
+static const uint32_t ps_const_num_sh_registers_gfx11 = 2;
+
+static const struct reg_info ps_const_sh_registers_gfx11[] = {
+ {0x2C0A, 0x020C0000}, //{ mmSPI_SHADER_PGM_RSRC1_PS, 0x020C0000 },
+ {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 }
+};
+
+static const struct reg_info ps_const_context_registers_gfx11[] = {
+ {0xA1B4, 0x00000002 }, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000000 }, //{ mmSPI_PS_IN_CONTROL, 0x00000000 },
+ {0xA08F, 0x0000000F }, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010 }, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000 }, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000 }, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004 }, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 /* SI_EXPORT_FMT_FP16_ABGR */ }
+};
+
+static const uint32_t ps_const_num_context_registers_gfx11 = 7;
+
+static const uint32_t ps_tex_shader_gfx11[] =
+{
+ 0xB0802006, 0xBF840003, 0xBEFD000C, 0xBE8E017E,
+ 0xBEFE1D7E, 0xCE000003, 0xCE000102, 0xCD000104,
+ 0x040E0103, 0xCD000000, 0x040A0102, 0xBF870112,
+ 0xCD010703, 0x04120303, 0xCD010700, 0x04020302,
+ 0x8BFE0E7E, 0xF06C0F05, 0x08000003, 0x00000000,
+ 0xBEFE010E, 0xBF8903F7, 0x5E000300, 0x5E020702,
+ 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100,
+ 0xBFB00000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000
+};
+
+static const uint32_t ps_tex_shader_patchinfo_offset_gfx11[] =
+{
+ 0x00000016
+};
+
+// Denotes the Patch Info Code Length
+static const uint32_t ps_tex_shader_patchinfo_code_size_gfx11 = 6;
+
+static const uint32_t ps_tex_shader_patchinfo_code_gfx11[][10][6] =
+{
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000890, 0x00000000 }, // SI_EXPORT_FMT_ZERO
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000801, 0x00000000 }, // SI_EXPORT_FMT_32_R
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_32_GR
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000300 }, // SI_EXPORT_FMT_32_AR
+ { 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_FP16_ABGR
+ { 0xD7220000, 0x00020300, 0xD7220001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_UNORM16_ABGR
+ { 0xD7210000, 0x00020300, 0xD7210001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_SNORM16_ABGR
+ { 0xD7230000, 0x00020300, 0xD7230001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_uint32_t16_ABGR
+ { 0xD7240000, 0x00020300, 0xD7240001, 0x00020702, 0xF8000803, 0x00000100 }, // SI_EXPORT_FMT_SINT16_ABGR
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800080F, 0x03020100 } // SI_EXPORT_FMT_32_ABGR
+ }
+};
+// Holds Sh Register Information
+static const struct reg_info ps_tex_sh_registers_gfx11[] =
+{
+ {0x2C0A, 0x020C0081 }, //{ mmSPI_SHADER_PGM_RSRC1_PS, 0x020C0081 },
+ {0x2C0B, 0x00000018 } //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000018 }
+};
+
+static const uint32_t ps_tex_num_sh_registers_gfx11 = 2;
+
+// Holds Context Register Information
+static const struct reg_info ps_tex_context_registers_gfx11[] =
+{
+ {0xA1B4, 0x00000002 }, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000001 }, //{ mmSPI_PS_IN_CONTROL, 0x00000001 },
+ {0xA08F, 0x0000000F }, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010 }, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000 }, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000 }, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004 } //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 /* SI_EXPORT_FMT_FP16_ABGR */ }
+};
+
+static const uint32_t ps_tex_num_context_registers_gfx11 = 7;
+
+
+static const uint32_t vs_RectPosTexFast_shader_gfx11[] =
+{
+ 0xB0802006, 0xBEFE01C1, 0xBF840003, 0xF408050A,
+ 0xF80000B0, 0xD71F0001, 0x000100C1, 0x9300FF03,
+ 0x00040018, 0x9301FF02, 0x0009000C, 0xBF870091,
+ 0xD7200001, 0x000202C1, 0xD60B0001, 0x04058000,
+ 0xBF870001, 0xD4490000, 0x00000301, 0xBE862100,
+ 0x7E040B05, 0xBFA5001C, 0x7E06020A, 0x7E08020E,
+ 0x7E0A020F, 0xBF8701B4, 0x060404F3, 0x7E140211,
+ 0x7E0E0210, 0x7C240480, 0x060404F3, 0xD5010003,
+ 0x01AA0608, 0xD5010004, 0x01AA080C, 0xBF870003,
+ 0xD4120012, 0x00010102, 0x7E04020B, 0xBEEA1F12,
+ 0xBF870483, 0xD5010008, 0x01AA080C, 0xD5010006,
+ 0x01AA0608, 0xBF870003, 0xD5010004, 0x004A0409,
+ 0xD5010009, 0x004A0A0D, 0xBEFE0106, 0x9302FF02,
+ 0x00090016, 0xBF870009, 0xD4C9007E, 0x00000501,
+ 0xBFA50002, 0xF8000941, 0x00000000, 0xBF89FFF0,
+ 0x8BFE0006, 0xD71F0000, 0x000100C1, 0xBFA50013,
+ 0x7E1602F2, 0x9300FF03, 0x00040018, 0x8B01FF05,
+ 0x00007FFF, 0xBF8704B2, 0xD7200000, 0x000200C1,
+ 0x7E0202F2, 0x84018901, 0x80018001, 0xBF870002,
+ 0xD60B0000, 0x04018000, 0xF80008CF, 0x01070406,
+ 0xBF89FC07, 0xE0744000, 0x01850800, 0xBFB00000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000,
+ 0xBF9F0000, 0xBF9F0000, 0xBF9F0000, 0xBF9F0000
+};
+
+static const struct reg_info vs_RectPosTexFast_sh_registers_gfx11[] =
+{
+ {0x2C8A, 0x020C00C2}, //{ mmSPI_SHADER_PGM_RSRC1_GS, 0x020C00C2 },
+ {0x2C8B, 0x0008001C}, //{ mmSPI_SHADER_PGM_RSRC2_GS, 0x0008001C }
+};
+
+static const uint32_t vs_RectPosTexFast_num_sh_registers_gfx11 = 2;
+
+// Holds Context Register Information
+static const struct reg_info vs_RectPosTexFast_context_registers_gfx11[] =
+{
+ {0xA1B1, 0x00000000}, //{ mmSPI_VS_OUT_CONFIG, 0x00000000 },
+ {0xA1C2, 0x00000001}, //{ mmSPI_SHADER_IDX_FORMAT, 0x00000001 },
+ {0xA1C3, 0x00000000}, //{ mmSPI_SHADER_POS_FORMAT, 0x00000000 /* Always 0 for now */},
+ {0xA2E4, 0x00000000}, //{ mmVGT_GS_INSTANCE_CNT, 0x00000000 },
+ {0xA2AB, 0x00000004}, //{ mmVGT_ESGS_RING_ITEMSIZE, 0x00000004 },
+ {0xA2CE, 0x00000001}, //{ mmVGT_GS_MAX_VERT_OUT, 0x00000001 }
+};
+
+static const uint32_t vs_RectPosTexFast_num_context_registers_gfx11 = 6;
+
+static const uint32_t preamblecache_gfx11[] = {
+ 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0,
+ 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000,
+ 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0, 0xc0016900, 0x208, 0x0,
+ 0xc0016900, 0x2a1, 0x0, 0xc0016900, 0x2ad, 0x0, 0xc0016900, 0x2dc, 0x0,
+ 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xc0046900, 0x310, 0x0, 0x3, 0x0, 0x100000, 0xc0016900, 0x349, 0x0,
+ 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0, 0xc0016900, 0x376, 0x0,
+ 0xc0016900, 0x385, 0x0, 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x204, 0x90000, 0x4, 0xc0016900, 0x20c, 0x0, 0xc0026900, 0x20e, 0x0, 0x0,
+ 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff,
+ 0xc0016900, 0x314, 0x0, 0xc0016900, 0x10a, 0x0, 0xc0016900, 0x2a6, 0x0,
+ 0xc0016900, 0x210, 0x0, 0xc0016900, 0x2db, 0x0, 0xc0016900, 0x2e4, 0x0,
+ 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x0, 0xc0016900, 0x206, 0x300,
+ 0xc0016900, 0x212, 0x200, 0xc0016900, 0xf4, 0x0, 0xc0016900, 0x18, 0x0,
+ 0xc0016900, 0x1d4, 0xff, 0xc0016900, 0x2ce, 0x1, 0xc0016900, 0x2d3, 0x20001,
+ 0xc0016900, 0x1ff, 0x80, 0xc0016900, 0x2d5, 0x6012010, 0xc0017a00, 0x20000243, 0x0,
+ 0xc0017900, 0x249, 0x0, 0xc0017900, 0x24a, 0x0, 0xc0017900, 0x24b, 0x0,
+ 0xc0017900, 0x259, 0xffffffff, 0xc0017900, 0x25f, 0x0, 0xc0017900, 0x260, 0x0,
+ 0xc0017900, 0x262, 0x0, 0xc0017900, 0x444, 0x0, 0xc0017900, 0x445, 0x0,
+ 0xc0017600, 0x6, 0x0, 0xc0017600, 0x80, 0x0, 0xc0017600, 0xb0, 0x0,
+ 0xc0047600, 0xb2, 0x0, 0x0, 0x0, 0x0, 0xc0017600, 0x30, 0x0,
+ 0xc0047600, 0x32, 0x0, 0x0, 0x0, 0x0
+};
+
+static const uint32_t cached_cmd_gfx11[] = {
+ 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0,
+ 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020,
+ 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf,
+ 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0,
+ 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011,
+ 0xc0026900, 0x292, 0x20, 0x6020000,
+ 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0,
+ 0xc0046900, 0x1d5, 0x0, 0x0, 0x0, 0x0, 0xc0016900, 0x104, 0x4a00005,
+ 0xc0016900, 0x1f, 0xf2a0055, 0xc0017900, 0x266, 0x4
+};
+static const uint32_t sh_reg_base_gfx11 = 0x2C00;
+static const uint32_t context_reg_base_gfx11 = 0xA000;
+
+#endif
diff --git a/tests/amdgpu/shader_code_gfx9.h b/tests/amdgpu/shader_code_gfx9.h
new file mode 100644
index 0000000..3ad1ca8
--- /dev/null
+++ b/tests/amdgpu/shader_code_gfx9.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _shader_code_gfx9_h_
+#define _shader_code_gfx9_h_
+
+static const uint32_t bufferclear_cs_shader_gfx9[] = {
+ 0x260000ff, 0x000003ff, 0xd1fd0000, 0x04010c08,
+ 0x7e020280, 0x7e040204, 0x7e060205, 0x7e080206,
+ 0x7e0a0207, 0xe01c2000, 0x80000200, 0xbf8c0000,
+ 0xbf810000
+};
+
+static const struct reg_info bufferclear_cs_shader_registers_gfx9[] = {
+ {0x2e12, 0x000C0041}, //{ mmCOMPUTE_PGM_RSRC1, 0x000C0041 },
+ {0x2e13, 0x00000090}, //{ mmCOMPUTE_PGM_RSRC2, 0x00000090 },
+ {0x2e07, 0x00000040}, //{ mmCOMPUTE_NUM_THREAD_X, 0x00000040 },
+ {0x2e08, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Y, 0x00000001 },
+ {0x2e09, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Z, 0x00000001 }
+};
+
+static const uint32_t buffercopy_cs_shader_gfx9[] = {
+ 0x260000ff, 0x000003ff, 0xd1fd0000, 0x04010c08,
+ 0x7e020280, 0xe00c2000, 0x80000200, 0xbf8c0f70,
+ 0xe01c2000, 0x80010200, 0xbf810000
+};
+
+static const uint32_t ps_const_shader_gfx9[] = {
+ 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203,
+ 0xD2960000, 0x00020300, 0xD2960001, 0x00020702,
+ 0xC4001C0F, 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_const_shader_patchinfo_code_size_gfx9 = 6;
+
+static const uint32_t ps_const_shader_patchinfo_code_gfx9[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000300 },
+ { 0xD2960000, 0x00020300, 0xD2960001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2950000, 0x00020300, 0xD2950001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2940000, 0x00020300, 0xD2940001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2970000, 0x00020300, 0xD2970001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xD2980000, 0x00020300, 0xD2980001, 0x00020702, 0xC4001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x03020100 }
+ }
+};
+
+static const uint32_t ps_const_shader_patchinfo_offset_gfx9[] = {
+ 0x00000004
+};
+
+static const uint32_t ps_const_num_sh_registers_gfx9 = 2;
+
+static const struct reg_info ps_const_sh_registers_gfx9[] = {
+ {0x2C0A, 0x000C0040},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0040 },
+ {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 }
+};
+
+static const uint32_t ps_const_num_context_registers_gfx9 = 7;
+
+static const struct reg_info ps_const_context_registers_gfx9[] = {
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000000}, //{ mmSPI_PS_IN_CONTROL, 0x00000000 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 }
+};
+
+static const uint32_t ps_tex_shader_gfx9[] = {
+ 0xBEFC000C, 0xBE8E017E, 0xBEFE077E, 0xD4180000,
+ 0xD4190001, 0xD41C0100, 0xD41D0101, 0xF0800F00,
+ 0x00400206, 0xBEFE010E, 0xBF8C0F70, 0xD2960000,
+ 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F,
+ 0x00000100, 0xBF810000
+};
+
+static const uint32_t ps_tex_shader_patchinfo_offset_gfx9[] = {
+ 0x0000000B
+};
+
+static const uint32_t ps_tex_shader_patchinfo_code_size_gfx9 = 6;
+
+static const uint32_t ps_tex_shader_patchinfo_code_gfx9[][10][6] = {
+ {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000002 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000302 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000502 },
+ { 0xD2960000, 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2950000, 0x00020702, 0xD2950001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2940000, 0x00020702, 0xD2940001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2970000, 0x00020702, 0xD2970001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xD2980000, 0x00020702, 0xD2980001, 0x00020B04, 0xC4001C0F, 0x00000100 },
+ { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x05040302 }
+ }
+};
+
+static const uint32_t ps_tex_num_sh_registers_gfx9 = 2;
+static const struct reg_info ps_tex_sh_registers_gfx9[] = {
+ {0x2C0A, 0x000C0081},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0081 },
+ {0x2C0B, 0x00000018}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000018 }
+};
+
+static const uint32_t ps_tex_num_context_registers_gfx9 = 7;
+
+static const struct reg_info ps_tex_context_registers_gfx9[] = {
+ {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 },
+ {0xA1B6, 0x00000001}, //{ mmSPI_PS_IN_CONTROL, 0x00000001 },
+ {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F },
+ {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 },
+ {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 },
+ {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */},
+ {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 }
+};
+
+static const uint32_t vs_RectPosTexFast_shader_gfx9[] = {
+ 0x7E000B00, 0x020000F3, 0xD042000A, 0x00010100,
+ 0x7E020202, 0x7E040200, 0x020000F3, 0x7E060206,
+ 0x7E080204, 0xD1000001, 0x002A0302, 0x7C840080,
+ 0x7E000200, 0x7E040203, 0x7E0A0201, 0xD1000003,
+ 0x002A0704, 0x7E0C0207, 0x7E0E0205, 0x00000101,
+ 0x00020505, 0x7E040208, 0x7E0A02F2, 0x00060903,
+ 0x00080D07, 0x7E0C0209, 0xC40008CF, 0x05020100,
+ 0xC400020F, 0x05060403, 0xBF810000
+};
+
+static const struct reg_info vs_RectPosTexFast_sh_registers_gfx9[] =
+{
+ {0x2C4A, 0x000C0081}, //{ mmSPI_SHADER_PGM_RSRC1_VS, 0x000C0081 },
+ {0x2C4B, 0x00000018}, //{ mmSPI_SHADER_PGM_RSRC2_VS, 0x00000018 }
+};
+
+static const uint32_t vs_RectPosTexFast_num_sh_registers_gfx9 = 2;
+
+// Holds Context Register Information
+static const struct reg_info vs_RectPosTexFast_context_registers_gfx9[] =
+{
+ {0xA1B1, 0x00000000}, //{ mmSPI_VS_OUT_CONFIG, 0x00000000 },
+ {0xA1C3, 0x00000000}, //{ mmSPI_SHADER_POS_FORMAT, 0x00000000 /* Always 0 for now */}
+};
+
+static const uint32_t vs_RectPosTexFast_num_context_registers_gfx9 = 2;
+
+static const uint32_t preamblecache_gfx9[] = {
+ 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0,
+ 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000,
+ 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0,
+ 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0,
+ 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0,
+ 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0,
+ 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0,
+ 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xc0036900, 0x311, 0x3, 0, 0x100000, 0xc0026900, 0x316, 0x1e, 0x20,
+ 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0,
+ 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x19, 0x0,
+ 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0,
+ 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff,
+ 0xc0016900, 0x314, 0x0, 0xc0016900, 0x2a6, 0, 0xc0016900, 0x210, 0,
+ 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1,
+ 0xc0016900, 0x18, 0x2, 0xc0016900, 0x206, 0x300, 0xc0017900, 0x20000243, 0x0,
+ 0xc0017900, 0x248, 0xffffffff, 0xc0017900, 0x249, 0x0, 0xc0017900, 0x24a, 0x0,
+ 0xc0017900, 0x24b, 0x0
+};
+
+static const uint32_t cached_cmd_gfx9[] = {
+ 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0,
+ 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020,
+ 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf,
+ 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x12,
+ 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0,
+ 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011,
+ 0xc0026900, 0x292, 0x20, 0x60201b8,
+ 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0
+};
+
+static const uint32_t sh_reg_base_gfx9 = 0x2C00;
+static const uint32_t context_reg_base_gfx9 = 0xA000;
+
+#endif
diff --git a/tests/amdgpu/shader_code_hang.h b/tests/amdgpu/shader_code_hang.h
new file mode 100644
index 0000000..070bd71
--- /dev/null
+++ b/tests/amdgpu/shader_code_hang.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _shader_code_hang_h_
+#define _shader_code_hang_h_
+
+static const unsigned int memcpy_shader_hang[] = {
+ 0xFFFFFFFF, 0xBEFE0A7E, 0xBEFC0304, 0xC0C20100,
+ 0xC0800300, 0xC8080000, 0xC80C0100, 0xC8090001,
+ 0xC80D0101, 0xBF8C007F, 0xF0800F00, 0x00010002,
+ 0xBEFE040C, 0xBF8C0F70, 0xBF800000, 0xBF800000,
+ 0xF800180F, 0x03020100, 0xBF810000
+};
+
+struct shader_test_shader_bin {
+ const uint32_t *shader;
+ uint32_t header_length;
+ uint32_t body_length;
+ uint32_t foot_length;
+};
+
+static const unsigned int memcpy_cs_hang_slow_ai_codes[] = {
+ 0xd1fd0000, 0x04010c08, 0xe00c2000, 0x80000100,
+ 0xbf8c0f70, 0xe01c2000, 0x80010100, 0xbf810000
+};
+
+static struct shader_test_shader_bin memcpy_cs_hang_slow_ai = {
+ memcpy_cs_hang_slow_ai_codes, 4, 3, 1
+};
+
+static const unsigned int memcpy_cs_hang_slow_rv_codes[] = {
+ 0x8e00860c, 0x32000000, 0xe00c2000, 0x80010100,
+ 0xbf8c0f70, 0xe01c2000, 0x80020100, 0xbf810000
+};
+
+static struct shader_test_shader_bin memcpy_cs_hang_slow_rv = {
+ memcpy_cs_hang_slow_rv_codes, 4, 3, 1
+};
+
+static const unsigned int memcpy_cs_hang_slow_nv_codes[] = {
+ 0xd7460000, 0x04010c08, 0xe00c2000, 0x80000100,
+ 0xbf8c0f70, 0xe01ca000, 0x80010100, 0xbf810000
+};
+
+static struct shader_test_shader_bin memcpy_cs_hang_slow_nv = {
+ memcpy_cs_hang_slow_nv_codes, 4, 3, 1
+};
+
+
+static const unsigned int memcpy_ps_hang_slow_ai_codes[] = {
+ 0xbefc000c, 0xbe8e017e, 0xbefe077e, 0xd4080000,
+ 0xd4090001, 0xd40c0100, 0xd40d0101, 0xf0800f00,
+ 0x00400002, 0xbefe010e, 0xbf8c0f70, 0xbf800000,
+ 0xbf800000, 0xbf800000, 0xbf800000, 0xc400180f,
+ 0x03020100, 0xbf810000
+};
+
+static struct shader_test_shader_bin memcpy_ps_hang_slow_ai = {
+ memcpy_ps_hang_slow_ai_codes, 7, 2, 9
+};
+
+static const unsigned int memcpy_ps_hang_slow_navi10_codes[] = {
+ 0xBEFC030C,0xBE8E047E,0xBEFE0A7E,0xC8080000,
+ 0xC80C0100,0xC8090001,0xC80D0101,0xF0800F0A,
+ 0x00400402,0x00000003,0xBEFE040E,0xBF8C0F70,
+ 0xBF800000,0xBF800000,0xBF800000,0xBF800000,
+ 0xF800180F,0x07060504,0xBF810000
+};
+
+static struct shader_test_shader_bin memcpy_ps_hang_slow_navi10 = {
+ memcpy_ps_hang_slow_navi10_codes, 7, 3, 9
+};
+
+static const unsigned int memcpy_ps_hang_slow_navi21_codes[] = {
+ 0xBEFC030C, 0xBE8E047E, 0xBEFE0A7E, 0xC8080000, 0xC8000100, 0xC8090001, 0xC8010101, 0x87FE0E7E, // header
+ 0xF0800F0A, 0x00400002, 0x00000000, // body - image_sample instruction
+ 0xBFA3FFE3, 0xBEFE040E, 0xBF8C3F70, 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x03020100, 0xBF810000 // footer
+};
+
+static struct shader_test_shader_bin memcpy_ps_hang_slow_navi21 = {
+ memcpy_ps_hang_slow_navi21_codes, 8, 3, 10
+};
+
+#endif
diff --git a/tests/amdgpu/shader_test_util.c b/tests/amdgpu/shader_test_util.c
new file mode 100644
index 0000000..60148fb
--- /dev/null
+++ b/tests/amdgpu/shader_test_util.c
@@ -0,0 +1,2156 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include "CUnit/Basic.h"
+#include "amdgpu_test.h"
+#include "shader_code.h"
+
+#define PACKET3_DISPATCH_DIRECT 0x15
+#define PACKET3_CONTEXT_CONTROL 0x28
+#define PACKET3_DRAW_INDEX_AUTO 0x2D
+#define PACKET3_SET_CONTEXT_REG 0x69
+#define PACKET3_SET_SH_REG 0x76
+#define PACKET3_SET_SH_REG_OFFSET 0x77
+#define PACKET3_SET_UCONFIG_REG 0x79
+#define PACKET3_SET_SH_REG_INDEX 0x9B
+
+#define PACKET_TYPE3 3
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
+ (((op) & 0xFF) << 8) | \
+ ((n) & 0x3FFF) << 16)
+#define PACKET3_COMPUTE(op, n) PACKET3(op, n) | (1 << 1)
+
+
+struct shader_test_bo {
+ amdgpu_bo_handle bo;
+ unsigned size;
+ unsigned heap;
+ void *ptr;
+ uint64_t mc_address;
+ amdgpu_va_handle va;
+};
+
+struct shader_test_draw {
+ struct shader_test_bo ps_bo;
+ enum ps_type ps_type;
+ struct shader_test_bo vs_bo;
+ enum vs_type vs_type;
+};
+struct shader_test_dispatch {
+ struct shader_test_bo cs_bo;
+ enum cs_type cs_type;
+};
+
+struct shader_test_info {
+ amdgpu_device_handle device_handle;
+ enum amdgpu_test_gfx_version version;
+ unsigned ip;
+ unsigned ring;
+ int hang;
+ int hang_slow;
+};
+
+struct shader_test_priv {
+ const struct shader_test_info *info;
+ unsigned cmd_curr;
+
+ union {
+ struct shader_test_draw shader_draw;
+ struct shader_test_dispatch shader_dispatch;
+ };
+ struct shader_test_bo vtx_attributes_mem;
+ struct shader_test_bo cmd;
+ struct shader_test_bo src;
+ struct shader_test_bo dst;
+};
+
+static int shader_test_bo_alloc(amdgpu_device_handle device_handle,
+ struct shader_test_bo *shader_test_bo)
+{
+ return amdgpu_bo_alloc_and_map(device_handle, shader_test_bo->size, 4096,
+ shader_test_bo->heap, 0,
+ &(shader_test_bo->bo), (void **)&(shader_test_bo->ptr),
+ &(shader_test_bo->mc_address), &(shader_test_bo->va));
+}
+
+static int shader_test_bo_free(struct shader_test_bo *shader_test_bo)
+{
+ return amdgpu_bo_unmap_and_free(shader_test_bo->bo, shader_test_bo->va,
+ shader_test_bo->mc_address,
+ shader_test_bo->size);
+}
+
+void shader_test_for_each(amdgpu_device_handle device_handle, unsigned ip,
+ void (*fn)(struct shader_test_info *test_info))
+{
+ int r;
+ uint32_t ring_id;
+ struct shader_test_info test_info = {0};
+ struct drm_amdgpu_info_hw_ip info = {0};
+
+ r = amdgpu_query_hw_ip_info(device_handle, ip, 0, &info);
+ CU_ASSERT_EQUAL(r, 0);
+ if (!info.available_rings) {
+ printf("SKIP ... as there's no %s ring\n",
+ (ip == AMDGPU_HW_IP_GFX) ? "graphics": "compute");
+ return;
+ }
+
+ switch (info.hw_ip_version_major) {
+ case 9:
+ test_info.version = AMDGPU_TEST_GFX_V9;
+ break;
+ case 10:
+ test_info.version = AMDGPU_TEST_GFX_V10;
+ break;
+ case 11:
+ test_info.version = AMDGPU_TEST_GFX_V11;
+ break;
+ default:
+ printf("SKIP ... unsupported gfx version %d\n", info.hw_ip_version_major);
+ return;
+ }
+
+ test_info.device_handle = device_handle;
+ test_info.ip = ip;
+
+ printf("\n");
+ for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) {
+ printf("%s ring %d\n", (ip == AMDGPU_HW_IP_GFX) ? "graphics": "compute",
+ ring_id);
+ test_info.ring = ring_id;
+ fn(&test_info);
+ }
+}
+
+static void write_context_control(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ if (test_priv->info->ip == AMDGPU_HW_IP_GFX) {
+ ptr[i++] = PACKET3(PACKET3_CONTEXT_CONTROL, 1);
+ ptr[i++] = 0x80000000;
+ ptr[i++] = 0x80000000;
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void shader_test_load_shader_hang_slow(struct shader_test_bo *shader_bo,
+ struct shader_test_shader_bin *shader_bin)
+{
+ int i, j, loop;
+
+ loop = (shader_bo->size / sizeof(uint32_t) - shader_bin->header_length
+ - shader_bin->foot_length) / shader_bin->body_length;
+
+ memcpy(shader_bo->ptr, shader_bin->shader, shader_bin->header_length * sizeof(uint32_t));
+
+ j = shader_bin->header_length;
+ for (i = 0; i < loop; i++) {
+ memcpy(shader_bo->ptr + j,
+ shader_bin->shader + shader_bin->header_length,
+ shader_bin->body_length * sizeof(uint32_t));
+ j += shader_bin->body_length;
+ }
+
+ memcpy(shader_bo->ptr + j,
+ shader_bin->shader + shader_bin->header_length + shader_bin->body_length,
+ shader_bin->foot_length * sizeof(uint32_t));
+}
+
+static void amdgpu_dispatch_load_cs_shader_hang_slow(struct shader_test_priv *test_priv)
+{
+ struct amdgpu_gpu_info gpu_info = {0};
+ struct shader_test_shader_bin *cs_shader_bin;
+ int r;
+
+ r = amdgpu_query_gpu_info(test_priv->info->device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ switch (gpu_info.family_id) {
+ case AMDGPU_FAMILY_AI:
+ cs_shader_bin = &memcpy_cs_hang_slow_ai;
+ break;
+ case AMDGPU_FAMILY_RV:
+ cs_shader_bin = &memcpy_cs_hang_slow_rv;
+ break;
+ default:
+ cs_shader_bin = &memcpy_cs_hang_slow_nv;
+ break;
+ }
+
+ shader_test_load_shader_hang_slow(&test_priv->shader_dispatch.cs_bo, cs_shader_bin);
+}
+
+static void amdgpu_dispatch_load_cs_shader(struct shader_test_priv *test_priv)
+{
+ if (test_priv->info->hang) {
+ if (test_priv->info->hang_slow)
+ amdgpu_dispatch_load_cs_shader_hang_slow(test_priv);
+ else
+ memcpy(test_priv->shader_dispatch.cs_bo.ptr, memcpy_shader_hang,
+ sizeof(memcpy_shader_hang));
+ } else {
+ memcpy(test_priv->shader_dispatch.cs_bo.ptr,
+ shader_test_cs[test_priv->info->version][test_priv->shader_dispatch.cs_type].shader,
+ shader_test_cs[test_priv->info->version][test_priv->shader_dispatch.cs_type].shader_size);
+ }
+}
+
+static void amdgpu_dispatch_init_gfx9(struct shader_test_priv *test_priv)
+{
+ int i;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* Write context control and load shadowing register if necessary */
+ write_context_control(test_priv);
+
+ i = test_priv->cmd_curr;
+
+ /* Issue commands to set default compute state. */
+ /* clear mmCOMPUTE_START_Z - mmCOMPUTE_START_X */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 3);
+ ptr[i++] = 0x204;
+ i += 3;
+
+ /* clear mmCOMPUTE_TMPRING_SIZE */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x218;
+ ptr[i++] = 0;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_init_gfx10(struct shader_test_priv *test_priv)
+{
+ int i;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ amdgpu_dispatch_init_gfx9(test_priv);
+
+ i = test_priv->cmd_curr;
+
+ /* mmCOMPUTE_SHADER_CHKSUM */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x22a;
+ ptr[i++] = 0;
+ /* mmCOMPUTE_REQ_CTRL */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 6);
+ ptr[i++] = 0x222;
+ i += 6;
+ /* mmCP_COHER_START_DELAY */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x7b;
+ ptr[i++] = 0x20;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_init_gfx11(struct shader_test_priv *test_priv)
+{
+ int i;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* Write context control and load shadowing register if necessary */
+ write_context_control(test_priv);
+
+ i = test_priv->cmd_curr;
+
+ /* Issue commands to set default compute state. */
+ /* clear mmCOMPUTE_START_Z - mmCOMPUTE_START_X */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 3);
+ ptr[i++] = 0x204;
+ i += 3;
+
+ /* clear mmCOMPUTE_TMPRING_SIZE */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x218;
+ ptr[i++] = 0;
+
+ /* mmCOMPUTE_REQ_CTRL */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x222;
+ ptr[i++] = 0;
+
+ /* mmCOMPUTE_USER_ACCUM_0 .. 3*/
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x224;
+ i += 4;
+
+ /* mmCOMPUTE_SHADER_CHKSUM */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x22a;
+ ptr[i++] = 0;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_init(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ amdgpu_dispatch_init_gfx9(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_dispatch_init_gfx10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_dispatch_init_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_dispatch_write_cumask(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* Issue commands to set cu mask used in current dispatch */
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x216;
+ ptr[i++] = 0xffffffff;
+ ptr[i++] = 0xffffffff;
+ /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x219;
+ ptr[i++] = 0xffffffff;
+ ptr[i++] = 0xffffffff;
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ case AMDGPU_TEST_GFX_V11:
+ /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG_INDEX, 2);
+ ptr[i++] = 0x30000216;
+ ptr[i++] = 0xffffffff;
+ ptr[i++] = 0xffffffff;
+ /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG_INDEX, 2);
+ ptr[i++] = 0x30000219;
+ ptr[i++] = 0xffffffff;
+ ptr[i++] = 0xffffffff;
+ break;
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_write2hw_gfx9(struct shader_test_priv *test_priv)
+{
+ const struct shader_test_cs_shader *cs_shader = &shader_test_cs[test_priv->info->version][test_priv->shader_dispatch.cs_type];
+ int j, i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ uint64_t shader_addr = test_priv->shader_dispatch.cs_bo.mc_address;
+
+ /* Writes shader state to HW */
+ /* set mmCOMPUTE_PGM_HI - mmCOMPUTE_PGM_LO */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x20c;
+ ptr[i++] = (shader_addr >> 8);
+ ptr[i++] = (shader_addr >> 40);
+ /* write sh regs*/
+ for (j = 0; j < cs_shader->num_sh_reg; j++) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ /* - Gfx9ShRegBase */
+ ptr[i++] = cs_shader->sh_reg[j].reg_offset - shader_test_gfx_info[test_priv->info->version].sh_reg_base;
+ ptr[i++] = cs_shader->sh_reg[j].reg_value;
+ }
+
+ /* Write constant data */
+ if (CS_BUFFERCLEAR == test_priv->shader_dispatch.cs_type) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x74fac;
+
+ /* Sets a range of pixel shader constants */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ } else {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->src.mc_address;
+ ptr[i++] = (test_priv->src.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->src.size / 16;
+ ptr[i++] = 0x74fac;
+
+ /* Writes the UAV constant data to the SGPRs. */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x74fac;
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_write2hw_gfx10(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_cs_shader *cs_shader = &shader_test_cs[test_priv->info->version][test_priv->shader_dispatch.cs_type];
+ int j;
+ uint64_t shader_addr = test_priv->shader_dispatch.cs_bo.mc_address;
+
+ /* Writes shader state to HW */
+ /* set mmCOMPUTE_PGM_HI - mmCOMPUTE_PGM_LO */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x20c;
+ ptr[i++] = (shader_addr >> 8);
+ ptr[i++] = (shader_addr >> 40);
+ /* write sh regs*/
+ for (j = 0; j < cs_shader->num_sh_reg; j++) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ /* - Gfx9ShRegBase */
+ ptr[i++] = cs_shader->sh_reg[j].reg_offset - shader_test_gfx_info[test_priv->info->version].sh_reg_base;
+ ptr[i++] = cs_shader->sh_reg[j].reg_value;
+ }
+
+ /* mmCOMPUTE_PGM_RSRC3 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x228;
+ ptr[i++] = 0;
+
+ if (CS_BUFFERCLEAR == test_priv->shader_dispatch.cs_type) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x1104bfac;
+
+ /* Sets a range of pixel shader constants */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ } else {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->src.mc_address;
+ ptr[i++] = (test_priv->src.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->src.size / 16;
+ ptr[i++] = 0x1104bfac;
+
+ /* Writes the UAV constant data to the SGPRs. */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address>> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x1104bfac;
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_write2hw_gfx11(struct shader_test_priv *test_priv)
+{
+ enum amdgpu_test_gfx_version version = test_priv->info->version;
+ const struct shader_test_cs_shader *cs_shader = &shader_test_cs[version][test_priv->shader_dispatch.cs_type];
+ int j, i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ uint64_t shader_addr = test_priv->shader_dispatch.cs_bo.mc_address;
+
+ /* Writes shader state to HW */
+ /* set mmCOMPUTE_PGM_HI - mmCOMPUTE_PGM_LO */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x20c;
+ ptr[i++] = (shader_addr >> 8);
+ ptr[i++] = (shader_addr >> 40);
+
+ /* write sh regs*/
+ for (j = 0; j < cs_shader->num_sh_reg; j++) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ /* - Gfx9ShRegBase */
+ ptr[i++] = cs_shader->sh_reg[j].reg_offset - shader_test_gfx_info[version].sh_reg_base;
+ ptr[i++] = cs_shader->sh_reg[j].reg_value;
+ if (cs_shader->sh_reg[j].reg_offset == 0x2E12)
+ ptr[i-1] &= ~(1<<29);
+ }
+
+ /* mmCOMPUTE_PGM_RSRC3 */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x228;
+ ptr[i++] = 0x3f0;
+
+ /* Write constant data */
+ /* Writes the texture resource constants data to the SGPRs */
+ if (CS_BUFFERCLEAR == test_priv->shader_dispatch.cs_type) {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x1003dfac;
+
+ /* Sets a range of pixel shader constants */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ ptr[i++] = 0x22222222;
+ } else {
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x240;
+ ptr[i++] = test_priv->src.mc_address;
+ ptr[i++] = (test_priv->src.mc_address >> 32) | 0x100000;
+ ptr[i++] = test_priv->src.size / 16;
+ ptr[i++] = 0x1003dfac;
+
+ /* Writes the UAV constant data to the SGPRs. */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x244;
+ ptr[i++] = test_priv->dst.mc_address;
+ ptr[i++] = (test_priv->dst.mc_address>> 32) | 0x100000;
+ ptr[i++] = test_priv->dst.size / 16;
+ ptr[i++] = 0x1003dfac;
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_dispatch_write2hw(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ amdgpu_dispatch_write2hw_gfx9(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_dispatch_write2hw_gfx10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_dispatch_write2hw_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_dispatch_write_dispatch_cmd(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* clear mmCOMPUTE_RESOURCE_LIMITS */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x215;
+ ptr[i++] = 0;
+
+ /* dispatch direct command */
+ ptr[i++] = PACKET3_COMPUTE(PACKET3_DISPATCH_DIRECT, 3);
+ ptr[i++] = (test_priv->dst.size / 16 + 0x40 - 1 ) / 0x40;//0x10;
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+ ptr[i++] = 1;
+
+ test_priv->cmd_curr = i;
+}
+static void amdgpu_test_dispatch_memset(struct shader_test_info *test_info)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle resources[3];
+ struct shader_test_priv test_priv;
+ struct shader_test_bo *cmd = &(test_priv.cmd);
+ struct shader_test_bo *dst = &(test_priv.dst);
+ struct shader_test_bo *shader = &(test_priv.shader_dispatch.cs_bo);
+ uint32_t *ptr_cmd;
+ uint8_t *ptr_dst;
+ int i, r;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info= {0};
+ amdgpu_bo_list_handle bo_list;
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ uint8_t cptr[16];
+
+ memset(&test_priv, 0, sizeof(test_priv));
+ test_priv.info = test_info;
+ test_priv.shader_dispatch.cs_type = CS_BUFFERCLEAR;
+ r = amdgpu_cs_ctx_create(test_info->device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ cmd->size = 4096;
+ cmd->heap = AMDGPU_GEM_DOMAIN_GTT;
+ r = shader_test_bo_alloc(test_info->device_handle, cmd);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_cmd = cmd->ptr;
+ memset(ptr_cmd, 0, cmd->size);
+
+ shader->size = 4096;
+ shader->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ r = shader_test_bo_alloc(test_info->device_handle, shader);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(shader->ptr, 0, shader->size);
+ amdgpu_dispatch_load_cs_shader(&test_priv);
+
+ dst->size = 0x4000;
+ dst->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ r = shader_test_bo_alloc(test_info->device_handle, dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ amdgpu_dispatch_init(&test_priv);
+
+ /* Issue commands to set cu mask used in current dispatch */
+ amdgpu_dispatch_write_cumask(&test_priv);
+
+ /* Writes shader state to HW */
+ amdgpu_dispatch_write2hw(&test_priv);
+
+ amdgpu_dispatch_write_dispatch_cmd(&test_priv);
+
+ i = test_priv.cmd_curr;
+ while (i & 7)
+ ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */
+ test_priv.cmd_curr = i;
+
+ resources[0] = dst->bo;
+ resources[1] = shader->bo;
+ resources[2] = cmd->bo;
+ r = amdgpu_bo_list_create(test_info->device_handle, 3, resources, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ib_info.ib_mc_address = cmd->mc_address;
+ ib_info.size = test_priv.cmd_curr;
+ ibs_request.ip_type = test_info->ip;
+ ibs_request.ring = test_info->ring;
+ ibs_request.resources = bo_list;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ /* submit CS */
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.ip_type = test_info->ip;
+ fence_status.ip_instance = 0;
+ fence_status.ring = test_info->ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request.seq_no;
+
+ /* wait for IB accomplished */
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ /* verify if memset test result meets with expected */
+ i = 0;
+ ptr_dst = (uint8_t *)(dst->ptr);
+ memset(cptr, 0x22, 16);
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+ i = dst->size - 16;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+ i = dst->size / 2;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+
+ r = shader_test_bo_free(dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(shader);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(cmd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static
+void amdgpu_test_dispatch_memcpy(struct shader_test_info *test_info)
+{
+ struct shader_test_priv test_priv;
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle resources[4];
+ struct shader_test_bo *cmd = &(test_priv.cmd);
+ struct shader_test_bo *src = &(test_priv.src);
+ struct shader_test_bo *dst = &(test_priv.dst);
+ struct shader_test_bo *shader = &(test_priv.shader_dispatch.cs_bo);
+ uint32_t *ptr_cmd;
+ uint8_t *ptr_src;
+ uint8_t *ptr_dst;
+ int i, r;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info= {0};
+ uint32_t expired, hang_state, hangs;
+ amdgpu_bo_list_handle bo_list;
+ struct amdgpu_cs_fence fence_status = {0};
+
+ memset(&test_priv, 0, sizeof(test_priv));
+ test_priv.info = test_info;
+ test_priv.cmd.size = 4096;
+ test_priv.cmd.heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ test_priv.shader_dispatch.cs_bo.heap = AMDGPU_GEM_DOMAIN_VRAM;
+ test_priv.shader_dispatch.cs_type = CS_BUFFERCOPY;
+ test_priv.src.heap = AMDGPU_GEM_DOMAIN_VRAM;
+ test_priv.dst.heap = AMDGPU_GEM_DOMAIN_VRAM;
+ if (test_info->hang_slow) {
+ test_priv.shader_dispatch.cs_bo.size = 0x4000000;
+ test_priv.src.size = 0x4000000;
+ test_priv.dst.size = 0x4000000;
+ } else {
+ test_priv.shader_dispatch.cs_bo.size = 4096;
+ test_priv.src.size = 0x4000;
+ test_priv.dst.size = 0x4000;
+ }
+
+ r = amdgpu_cs_ctx_create(test_info->device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_alloc(test_info->device_handle, cmd);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_cmd = cmd->ptr;
+ memset(ptr_cmd, 0, cmd->size);
+
+ r = shader_test_bo_alloc(test_info->device_handle, shader);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(shader->ptr, 0, shader->size);
+ amdgpu_dispatch_load_cs_shader(&test_priv);
+
+ r = shader_test_bo_alloc(test_info->device_handle, src);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_src = (uint8_t *)(src->ptr);
+ memset(ptr_src, 0x55, src->size);
+
+ r = shader_test_bo_alloc(test_info->device_handle, dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ amdgpu_dispatch_init(&test_priv);
+
+ /* Issue commands to set cu mask used in current dispatch */
+ amdgpu_dispatch_write_cumask(&test_priv);
+
+ /* Writes shader state to HW */
+ amdgpu_dispatch_write2hw(&test_priv);
+
+ amdgpu_dispatch_write_dispatch_cmd(&test_priv);
+
+ i = test_priv.cmd_curr;
+ while (i & 7)
+ ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */
+ test_priv.cmd_curr = i;
+
+ resources[0] = shader->bo;
+ resources[1] = src->bo;
+ resources[2] = dst->bo;
+ resources[3] = cmd->bo;
+ r = amdgpu_bo_list_create(test_info->device_handle, 4, resources, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ib_info.ib_mc_address = cmd->mc_address;
+ ib_info.size = test_priv.cmd_curr;
+ ibs_request.ip_type = test_info->ip;
+ ibs_request.ring = test_info->ring;
+ ibs_request.resources = bo_list;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.ip_type = test_info->ip;
+ fence_status.ip_instance = 0;
+ fence_status.ring = test_info->ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request.seq_no;
+
+ /* wait for IB accomplished */
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+
+ if (!test_info->hang) {
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ /* verify if memcpy test result meets with expected */
+ i = 0;
+ ptr_dst = (uint8_t *)dst->ptr;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ i = dst->size - 16;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ i = dst->size / 2;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ } else {
+ r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET);
+ }
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(src);
+ CU_ASSERT_EQUAL(r, 0);
+ r = shader_test_bo_free(dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(shader);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(cmd);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void shader_test_dispatch_cb(struct shader_test_info *test_info)
+{
+ amdgpu_test_dispatch_memset(test_info);
+ amdgpu_test_dispatch_memcpy(test_info);
+}
+static void shader_test_dispatch_hang_cb(struct shader_test_info *test_info)
+{
+ test_info->hang = 0;
+ amdgpu_test_dispatch_memcpy(test_info);
+
+ test_info->hang = 1;
+ amdgpu_test_dispatch_memcpy(test_info);
+
+ test_info->hang = 0;
+ amdgpu_test_dispatch_memcpy(test_info);
+}
+
+static void shader_test_dispatch_hang_slow_cb(struct shader_test_info *test_info)
+{
+ test_info->hang = 0;
+ test_info->hang_slow = 0;
+ amdgpu_test_dispatch_memcpy(test_info);
+
+ test_info->hang = 1;
+ test_info->hang_slow = 1;
+ amdgpu_test_dispatch_memcpy(test_info);
+
+ test_info->hang = 0;
+ test_info->hang_slow = 0;
+ amdgpu_test_dispatch_memcpy(test_info);
+}
+
+void amdgpu_test_dispatch_helper(amdgpu_device_handle device_handle, unsigned ip)
+{
+ shader_test_for_each(device_handle, ip, shader_test_dispatch_cb);
+}
+
+void amdgpu_test_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip)
+{
+ shader_test_for_each(device_handle, ip, shader_test_dispatch_hang_cb);
+}
+
+void amdgpu_test_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip)
+{
+ shader_test_for_each(device_handle, ip, shader_test_dispatch_hang_slow_cb);
+}
+
+static void amdgpu_draw_load_ps_shader_hang_slow(struct shader_test_priv *test_priv)
+{
+ struct amdgpu_gpu_info gpu_info = {0};
+ struct shader_test_shader_bin *ps_shader_bin = &memcpy_ps_hang_slow_navi21;
+ int r;
+
+ r = amdgpu_query_gpu_info(test_priv->info->device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ switch (gpu_info.family_id) {
+ case AMDGPU_FAMILY_AI:
+ case AMDGPU_FAMILY_RV:
+ ps_shader_bin = &memcpy_ps_hang_slow_ai;
+ break;
+ case AMDGPU_FAMILY_NV:
+ if (gpu_info.chip_external_rev < 40)
+ ps_shader_bin = &memcpy_ps_hang_slow_navi10;
+ break;
+ }
+
+ shader_test_load_shader_hang_slow(&test_priv->shader_draw.ps_bo, ps_shader_bin);
+}
+
+static uint32_t round_up_size(uint32_t size)
+{
+ return (size + 255) & ~255;
+}
+static void amdgpu_draw_load_ps_shader(struct shader_test_priv *test_priv)
+{
+ uint8_t *ptr_shader = test_priv->shader_draw.ps_bo.ptr;
+ const struct shader_test_ps_shader *shader;
+ uint32_t shader_offset, num_export_fmt;
+ uint32_t mem_offset, patch_code_offset;
+ int i;
+
+ if (test_priv->info->hang) {
+ if (test_priv->info->hang_slow)
+ amdgpu_draw_load_ps_shader_hang_slow(test_priv);
+ else
+ memcpy(ptr_shader, memcpy_shader_hang, sizeof(memcpy_shader_hang));
+
+ return;
+ }
+
+ shader = &shader_test_ps[test_priv->info->version][test_priv->shader_draw.ps_type];
+ num_export_fmt = 10;
+ shader_offset = round_up_size(shader->shader_size);
+ /* write main shader program */
+ for (i = 0 ; i < num_export_fmt; i++) {
+ mem_offset = i * shader_offset;
+ memcpy(ptr_shader + mem_offset, shader->shader, shader->shader_size);
+ }
+
+ /* overwrite patch codes */
+ for (i = 0 ; i < num_export_fmt; i++) {
+ mem_offset = i * shader_offset + shader->patchinfo_code_offset[0] * sizeof(uint32_t);
+ patch_code_offset = i * shader->patchinfo_code_size;
+ memcpy(ptr_shader + mem_offset,
+ shader->patchinfo_code + patch_code_offset,
+ shader->patchinfo_code_size * sizeof(uint32_t));
+ }
+}
+
+/* load RectPosTexFast_VS */
+static void amdgpu_draw_load_vs_shader(struct shader_test_priv *test_priv)
+{
+ uint8_t *ptr_shader = test_priv->shader_draw.vs_bo.ptr;
+ const struct shader_test_vs_shader *shader = &shader_test_vs[test_priv->info->version][test_priv->shader_draw.vs_type];
+
+ memcpy(ptr_shader, shader->shader, shader->shader_size);
+}
+
+static void amdgpu_draw_init(struct shader_test_priv *test_priv)
+{
+ int i;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_gfx_info *gfx_info = &shader_test_gfx_info[test_priv->info->version];
+
+ /* Write context control and load shadowing register if necessary */
+ write_context_control(test_priv);
+ i = test_priv->cmd_curr;
+
+ if (test_priv->info->version == AMDGPU_TEST_GFX_V11) {
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x446;
+ ptr[i++] = (test_priv->vtx_attributes_mem.mc_address >> 16);
+ // mmSPI_ATTRIBUTE_RING_SIZE
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x447;
+ ptr[i++] = 0x20001;
+ }
+ memcpy(ptr + i, gfx_info->preamble_cache, gfx_info->size_preamble_cache);
+
+ test_priv->cmd_curr = i + gfx_info->size_preamble_cache/sizeof(uint32_t);
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_surf_info_gfx9(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* setup color buffer */
+ /* offset reg
+ 0xA318 CB_COLOR0_BASE
+ 0xA319 CB_COLOR0_BASE_EXT
+ 0xA31A CB_COLOR0_ATTRIB2
+ 0xA31B CB_COLOR0_VIEW
+ 0xA31C CB_COLOR0_INFO
+ 0xA31D CB_COLOR0_ATTRIB
+ 0xA31E CB_COLOR0_DCC_CONTROL
+ 0xA31F CB_COLOR0_CMASK
+ 0xA320 CB_COLOR0_CMASK_BASE_EXT
+ 0xA321 CB_COLOR0_FMASK
+ 0xA322 CB_COLOR0_FMASK_BASE_EXT
+ 0xA323 CB_COLOR0_CLEAR_WORD0
+ 0xA324 CB_COLOR0_CLEAR_WORD1
+ 0xA325 CB_COLOR0_DCC_BASE
+ 0xA326 CB_COLOR0_DCC_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 15);
+ ptr[i++] = 0x318;
+ ptr[i++] = test_priv->dst.mc_address >> 8;
+ ptr[i++] = test_priv->dst.mc_address >> 40;
+ ptr[i++] = test_priv->info->hang_slow ? 0x3ffc7ff : 0x7c01f;
+ ptr[i++] = 0;
+ ptr[i++] = 0x50438;
+ ptr[i++] = 0x10140000;
+ i += 9;
+
+ /* mmCB_MRT0_EPITCH */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1e8;
+ ptr[i++] = test_priv->info->hang_slow ? 0xfff : 0x1f;
+
+ /* 0xA32B CB_COLOR1_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x32b;
+ ptr[i++] = 0;
+
+ /* 0xA33A CB_COLOR1_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x33a;
+ ptr[i++] = 0;
+
+ /* SPI_SHADER_COL_FORMAT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1c5;
+ ptr[i++] = 9;
+
+ /* Setup depth buffer */
+ /* mmDB_Z_INFO */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0xe;
+ i += 2;
+
+ test_priv->cmd_curr = i;
+}
+static void amdgpu_draw_setup_and_write_drawblt_surf_info_gfx10(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* setup color buffer */
+ /* 0xA318 CB_COLOR0_BASE
+ 0xA319 CB_COLOR0_PITCH
+ 0xA31A CB_COLOR0_SLICE
+ 0xA31B CB_COLOR0_VIEW
+ 0xA31C CB_COLOR0_INFO
+ 0xA31D CB_COLOR0_ATTRIB
+ 0xA31E CB_COLOR0_DCC_CONTROL
+ 0xA31F CB_COLOR0_CMASK
+ 0xA320 CB_COLOR0_CMASK_SLICE
+ 0xA321 CB_COLOR0_FMASK
+ 0xA322 CB_COLOR0_FMASK_SLICE
+ 0xA323 CB_COLOR0_CLEAR_WORD0
+ 0xA324 CB_COLOR0_CLEAR_WORD1
+ 0xA325 CB_COLOR0_DCC_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 14);
+ ptr[i++] = 0x318;
+ ptr[i++] = test_priv->dst.mc_address >> 8;
+ i += 3;
+ ptr[i++] = 0x50438;
+ i += 9;
+
+ /* 0xA390 CB_COLOR0_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x390;
+ ptr[i++] = test_priv->dst.mc_address >> 40;
+
+ /* 0xA398 CB_COLOR0_CMASK_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x398;
+ ptr[i++] = 0;
+
+ /* 0xA3A0 CB_COLOR0_FMASK_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3a0;
+ ptr[i++] = 0;
+
+ /* 0xA3A8 CB_COLOR0_DCC_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3a8;
+ ptr[i++] = 0;
+
+ /* 0xA3B0 CB_COLOR0_ATTRIB2 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3b0;
+ ptr[i++] = test_priv->info->hang_slow ? 0x3ffc7ff : 0x7c01f;
+
+ /* 0xA3B8 CB_COLOR0_ATTRIB3 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3b8;
+ ptr[i++] = 0x9014000;
+
+ /* 0xA32B CB_COLOR1_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x32b;
+ ptr[i++] = 0;
+
+ /* 0xA33A CB_COLOR1_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x33a;
+ ptr[i++] = 0;
+
+ /* SPI_SHADER_COL_FORMAT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1c5;
+ ptr[i++] = 9;
+
+ /* Setup depth buffer */
+ /* mmDB_Z_INFO */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0x10;
+ i += 2;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_surf_info_gfx11(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ /* mmCB_COLOR0_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x318;
+ ptr[i++] = test_priv->dst.mc_address >> 8;
+ /* mmCB_COLOR0_VIEW .. mmCB_COLOR0_DCC_CONTROL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 4);
+ ptr[i++] = 0x31b;
+ i++;
+ ptr[i++] = 0x5040e;
+ i += 2;
+ /* mmCB_COLOR0_DCC_BASE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x325;
+ ptr[i++] = 0;
+ /* mmCB_COLOR0_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x390;
+ ptr[i++] = (test_priv->dst.mc_address >> 40) & 0xFF;
+ /* mmCB_COLOR0_DCC_BASE_EXT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3a8;
+ ptr[i++] = 0;
+ /* mmCB_COLOR0_ATTRIB2 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3b0;
+ ptr[i++] = test_priv->info->hang_slow ? 0x1ffc7ff : 0x7c01f;
+ /* mmCB_COLOR0_ATTRIB3 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x3b8;
+ ptr[i++] = test_priv->info->hang_slow ? 0x1028000 : 0x1018000;
+ /* mmCB_COLOR0_INFO */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x32b;
+ ptr[i++] = 0;
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x33a;
+ ptr[i++] = 0;
+ /* mmSPI_SHADER_COL_FORMAT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1c5;
+ ptr[i++] = 0x9;
+ /* mmDB_Z_INFO */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0x10;
+ i += 2;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_surf_info(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ amdgpu_draw_setup_and_write_drawblt_surf_info_gfx9(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_draw_setup_and_write_drawblt_surf_info_gfx10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_draw_setup_and_write_drawblt_surf_info_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_state_gfx9(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_gfx_info *gfx_info = &shader_test_gfx_info[test_priv->info->version];
+
+ /* mmPA_SC_TILE_STEERING_OVERRIDE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ ptr[i++] = 0;
+
+ ptr[i++] = 0xffff1000;
+ ptr[i++] = 0xc0021000;
+
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ ptr[i++] = 1;
+
+ /* mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 16);
+ ptr[i++] = 0x2fe;
+ i += 16;
+
+ /* mmPA_SC_CENTROID_PRIORITY_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0x2f5;
+ i += 2;
+
+ memcpy(ptr + i, gfx_info->cached_cmd, gfx_info->size_cached_cmd);
+ if (test_priv->info->hang_slow)
+ *(ptr + i + 12) = 0x8000800;
+
+ test_priv->cmd_curr = i + gfx_info->size_cached_cmd/sizeof(uint32_t);
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_state_gfx10(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_gfx_info *gfx_info = &shader_test_gfx_info[test_priv->info->version];
+
+ /* mmPA_SC_TILE_STEERING_OVERRIDE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ ptr[i++] = 0;
+
+ ptr[i++] = 0xffff1000;
+ ptr[i++] = 0xc0021000;
+
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ ptr[i++] = 0;
+
+ /* mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 16);
+ ptr[i++] = 0x2fe;
+ i += 16;
+
+ /* mmPA_SC_CENTROID_PRIORITY_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0x2f5;
+ i += 2;
+
+ memcpy(ptr + i, gfx_info->cached_cmd, gfx_info->size_cached_cmd);
+ if (test_priv->info->hang_slow)
+ *(ptr + i + 12) = 0x8000800;
+ i += gfx_info->size_cached_cmd/sizeof(uint32_t);
+
+ /* mmCB_RMI_GL2_CACHE_CONTROL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x104;
+ ptr[i++] = 0x40aa0055;
+ /* mmDB_RMI_L2_CACHE_CONTROL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1f;
+ ptr[i++] = 0x2a0055;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_state_gfx11(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_gfx_info *gfx_info = &shader_test_gfx_info[test_priv->info->version];
+
+ /* mmPA_SC_TILE_STEERING_OVERRIDE */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ ptr[i++] = 0;
+
+ ptr[i++] = 0xffff1000;
+ ptr[i++] = 0xc0021000;
+
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0xd7;
+ i++;
+
+ /* mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 16);
+ ptr[i++] = 0x2fe;
+ i += 16;
+
+ /* mmPA_SC_CENTROID_PRIORITY_0 */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+ ptr[i++] = 0x2f5;
+ i += 2;
+
+ memcpy(ptr + i, gfx_info->cached_cmd, gfx_info->size_cached_cmd);
+ if (test_priv->info->hang_slow)
+ *(ptr + i + 12) = 0x8000800;
+
+ test_priv->cmd_curr = i + gfx_info->size_cached_cmd/sizeof(uint32_t);
+}
+
+static void amdgpu_draw_setup_and_write_drawblt_state(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ amdgpu_draw_setup_and_write_drawblt_state_gfx9(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_draw_setup_and_write_drawblt_state_gfx10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_draw_setup_and_write_drawblt_state_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_draw_vs_RectPosTexFast_write2hw_gfx9(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ uint64_t shader_addr = test_priv->shader_draw.vs_bo.mc_address;
+ enum ps_type ps = test_priv->shader_draw.ps_type;
+
+ /* mmPA_CL_VS_OUT_CNTL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x207;
+ ptr[i++] = 0;
+
+ /* mmSPI_SHADER_PGM_RSRC3_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x46;
+ ptr[i++] = 0xffff;
+
+ /* mmSPI_SHADER_PGM_LO_VS...mmSPI_SHADER_PGM_HI_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x48;
+ ptr[i++] = shader_addr >> 8;
+ ptr[i++] = shader_addr >> 40;
+
+ /* mmSPI_SHADER_PGM_RSRC1_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x4a;
+ ptr[i++] = 0xc0081;
+
+ /* mmSPI_SHADER_PGM_RSRC2_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x4b;
+ ptr[i++] = 0x18;
+
+ /* mmSPI_VS_OUT_CONFIG */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1b1;
+ ptr[i++] = 2;
+
+ /* mmSPI_SHADER_POS_FORMAT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1c3;
+ ptr[i++] = 4;
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x4c;
+ i += 2;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x50;
+ i += 2;
+ if (ps == PS_CONST) {
+ i += 2;
+ } else if (ps == PS_TEX) {
+ ptr[i++] = 0x3f800000;
+ ptr[i++] = 0x3f800000;
+ }
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x54;
+ i += 4;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_vs_RectPosTexFast_write2hw_gfx10(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ uint64_t shader_addr = test_priv->shader_draw.vs_bo.mc_address;
+ enum ps_type ps = test_priv->shader_draw.ps_type;
+
+ /* mmPA_CL_VS_OUT_CNTL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x207;
+ ptr[i++] = 0;
+
+ /* mmSPI_SHADER_PGM_RSRC3_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000046;
+ ptr[i++] = 0xffff;
+ /* mmSPI_SHADER_PGM_RSRC4_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000041;
+ ptr[i++] = 0xffff;
+
+ /* mmSPI_SHADER_PGM_LO_VS...mmSPI_SHADER_PGM_HI_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x48;
+ ptr[i++] = shader_addr >> 8;
+ ptr[i++] = shader_addr >> 40;
+
+ /* mmSPI_SHADER_PGM_RSRC1_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x4a;
+ ptr[i++] = 0xc0041;
+ /* mmSPI_SHADER_PGM_RSRC2_VS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = 0x4b;
+ ptr[i++] = 0x18;
+
+ /* mmSPI_VS_OUT_CONFIG */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1b1;
+ ptr[i++] = 2;
+
+ /* mmSPI_SHADER_POS_FORMAT */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1c3;
+ ptr[i++] = 4;
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x4c;
+ i += 2;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x50;
+ i += 2;
+ if (ps == PS_CONST) {
+ i += 2;
+ } else if (ps == PS_TEX) {
+ ptr[i++] = 0x3f800000;
+ ptr[i++] = 0x3f800000;
+ }
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x54;
+ i += 4;
+
+ test_priv->cmd_curr = i;
+}
+
+
+static void amdgpu_draw_vs_RectPosTexFast_write2hw_gfx11(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+ const struct shader_test_gfx_info *gfx_info = &shader_test_gfx_info[test_priv->info->version];
+ uint64_t shader_addr = test_priv->shader_draw.vs_bo.mc_address;
+ const struct shader_test_vs_shader *shader = &shader_test_vs[test_priv->info->version][test_priv->shader_draw.vs_type];
+ enum ps_type ps = test_priv->shader_draw.ps_type;
+ int j, offset;
+
+ /* mmPA_CL_VS_OUT_CNTL */
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x207;
+ ptr[i++] = 0;
+
+ /* mmSPI_SHADER_PGM_RSRC3_GS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000087;
+ ptr[i++] = 0xffff;
+ /* mmSPI_SHADER_PGM_RSRC4_GS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000081;
+ ptr[i++] = 0x1fff0001;
+
+ /* mmSPI_SHADER_PGM_LO_ES */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0xc8;
+ ptr[i++] = shader_addr >> 8;
+ ptr[i++] = shader_addr >> 40;
+
+ /* write sh reg */
+ for (j = 0; j < shader->num_sh_reg; j++) {
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = shader->sh_reg[j].reg_offset - gfx_info->sh_reg_base;
+ ptr[i++] = shader->sh_reg[j].reg_value;
+ }
+ /* write context reg */
+ for (j = 0; j < shader->num_context_reg; j++) {
+ switch (shader->context_reg[j].reg_offset) {
+ case 0xA1B1: //mmSPI_VS_OUT_CONFIG
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = shader->context_reg[j].reg_offset - gfx_info->context_reg_base;
+ ptr[i++] = 2;
+ break;
+ case 0xA1C3: //mmSPI_SHADER_POS_FORMAT
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = shader->context_reg[j].reg_offset - gfx_info->context_reg_base;
+ ptr[i++] = 4;
+ break;
+ case 0xA2E4: //mmVGT_GS_INSTANCE_CNT
+ case 0xA2CE: //mmVGT_GS_MAX_VERT_OUT
+ break;
+ default:
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = shader->context_reg[j].reg_offset - gfx_info->context_reg_base;
+ ptr[i++] = shader->context_reg[j].reg_value;
+ break;
+ }
+ }
+
+ // write constant
+ // dst rect
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x8c;
+ i += 2;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+ ptr[i++] = test_priv->info->hang_slow ? 0x45000000 : 0x42000000;
+ // src rect
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x90;
+ i += 2;
+ if (ps == PS_CONST) {
+ i += 2;
+ } else if (ps == PS_TEX) {
+ ptr[i++] = 0x3f800000;
+ ptr[i++] = 0x3f800000;
+ }
+
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr[i++] = 0x94;
+ i += 4;
+ // vtx_attributes_mem
+ ptr[i++] = 0xc02f1000;
+ offset = i * sizeof(uint32_t);
+ i += 44;
+ ptr[i++] = test_priv->vtx_attributes_mem.mc_address & 0xffffffff;
+ ptr[i++] = 0xc0100000 | ((test_priv->vtx_attributes_mem.mc_address >> 32) & 0xffff);
+ ptr[i++] = test_priv->vtx_attributes_mem.size / 16;
+ ptr[i++] = 0x2043ffac;
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_OFFSET, 2);
+ ptr[i++] = 0x98;
+ ptr[i++] = offset;
+ i++;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_vs_RectPosTexFast_write2hw(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ amdgpu_draw_vs_RectPosTexFast_write2hw_gfx9(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_draw_vs_RectPosTexFast_write2hw_gfx10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_draw_vs_RectPosTexFast_write2hw_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_draw_ps_write2hw_gfx9_10(struct shader_test_priv *test_priv)
+{
+ int i, j;
+ uint64_t shader_addr = test_priv->shader_draw.ps_bo.mc_address;
+ const struct shader_test_ps_shader *ps = &shader_test_ps[test_priv->info->version][test_priv->shader_draw.ps_type];
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ i = test_priv->cmd_curr;
+
+ if (test_priv->info->version == AMDGPU_TEST_GFX_V9) {
+ /* 0x2c07 SPI_SHADER_PGM_RSRC3_PS
+ 0x2c08 SPI_SHADER_PGM_LO_PS
+ 0x2c09 SPI_SHADER_PGM_HI_PS */
+ /* multiplicator 9 is from SPI_SHADER_COL_FORMAT */
+ if (!test_priv->info->hang)
+ shader_addr += 256 * 9;
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 3);
+ ptr[i++] = 0x7;
+ ptr[i++] = 0xffff;
+ ptr[i++] = shader_addr >> 8;
+ ptr[i++] = shader_addr >> 40;
+ } else {
+ //if (!test_priv->info->hang)
+ shader_addr += 256 * 9;
+ /* 0x2c08 SPI_SHADER_PGM_LO_PS
+ 0x2c09 SPI_SHADER_PGM_HI_PS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x8;
+ ptr[i++] = shader_addr >> 8;
+ ptr[i++] = shader_addr >> 40;
+
+ /* mmSPI_SHADER_PGM_RSRC3_PS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000007;
+ ptr[i++] = 0xffff;
+ /* mmSPI_SHADER_PGM_RSRC4_PS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000001;
+ ptr[i++] = 0xffff;
+ }
+
+ for (j = 0; j < ps->num_sh_reg; j++) {
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = ps->sh_reg[j].reg_offset - 0x2c00;
+ ptr[i++] = ps->sh_reg[j].reg_value;
+ }
+
+ for (j = 0; j < ps->num_context_reg; j++) {
+ if (ps->context_reg[j].reg_offset != 0xA1C5) {
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = ps->context_reg[j].reg_offset - 0xa000;
+ ptr[i++] = ps->context_reg[j].reg_value;
+ }
+
+ if (ps->context_reg[j].reg_offset == 0xA1B4) {
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1b3;
+ ptr[i++] = 2;
+ }
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_ps_write2hw_gfx11(struct shader_test_priv *test_priv)
+{
+ int i, j;
+ uint64_t shader_addr = test_priv->shader_draw.ps_bo.mc_address;
+ enum amdgpu_test_gfx_version version = test_priv->info->version;
+ const struct shader_test_ps_shader *ps = &shader_test_ps[version][test_priv->shader_draw.ps_type];
+ uint32_t *ptr = test_priv->cmd.ptr;
+ uint32_t export_shader_offset;
+
+ i = test_priv->cmd_curr;
+
+ /* SPI_SHADER_PGM_LO_PS
+ SPI_SHADER_PGM_HI_PS */
+ shader_addr >>= 8;
+ if (!test_priv->info->hang) {
+ export_shader_offset = (round_up_size(ps->shader_size) * 9) >> 8;
+ shader_addr += export_shader_offset;
+ }
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 2);
+ ptr[i++] = 0x8;
+ ptr[i++] = shader_addr & 0xffffffff;
+ ptr[i++] = (shader_addr >> 32) & 0xffffffff;
+ /* mmSPI_SHADER_PGM_RSRC3_PS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000007;
+ ptr[i++] = 0xffff;
+ /* mmSPI_SHADER_PGM_RSRC4_PS */
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG_INDEX, 1);
+ ptr[i++] = 0x30000001;
+ ptr[i++] = 0x3fffff;
+
+ for (j = 0; j < ps->num_sh_reg; j++) {
+ ptr[i++] = PACKET3(PACKET3_SET_SH_REG, 1);
+ ptr[i++] = ps->sh_reg[j].reg_offset - shader_test_gfx_info[version].sh_reg_base;
+ ptr[i++] = ps->sh_reg[j].reg_value;
+ }
+
+ for (j = 0; j < ps->num_context_reg; j++) {
+ /* !mmSPI_SHADER_COL_FORMAT */
+ if (ps->context_reg[j].reg_offset != 0xA1C5) {
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = ps->context_reg[j].reg_offset - shader_test_gfx_info[version].context_reg_base;
+ ptr[i++] = ps->context_reg[j].reg_value;
+ }
+
+ /* mmSPI_PS_INPUT_ADDR */
+ if (ps->context_reg[j].reg_offset == 0xA1B4) {
+ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr[i++] = 0x1b3;
+ ptr[i++] = 2;
+ }
+ }
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_draw_ps_write2hw(struct shader_test_priv *test_priv)
+{
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ case AMDGPU_TEST_GFX_V10:
+ amdgpu_draw_ps_write2hw_gfx9_10(test_priv);
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ amdgpu_draw_ps_write2hw_gfx11(test_priv);
+ break;
+ }
+}
+
+static void amdgpu_draw_draw(struct shader_test_priv *test_priv)
+{
+ int i = test_priv->cmd_curr;
+ uint32_t *ptr = test_priv->cmd.ptr;
+
+ switch (test_priv->info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ /* mmIA_MULTI_VGT_PARAM */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x40000258;
+ ptr[i++] = 0xd00ff;
+ /* mmVGT_PRIMITIVE_TYPE */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x10000242;
+ ptr[i++] = 0x11;
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ /* mmGE_CNTL */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x25b;
+ ptr[i++] = 0xff;
+ /* mmVGT_PRIMITIVE_TYPE */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x242;
+ ptr[i++] = 0x11;
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ /* mmGE_CNTL */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x25b;
+ ptr[i++] = 0x80fc80;
+ /* mmVGT_PRIMITIVE_TYPE */
+ ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
+ ptr[i++] = 0x242;
+ ptr[i++] = 0x11;
+ break;
+ }
+
+ ptr[i++] = PACKET3(PACKET3_DRAW_INDEX_AUTO, 1);
+ ptr[i++] = 3;
+ ptr[i++] = 2;
+
+ test_priv->cmd_curr = i;
+}
+
+static void amdgpu_memset_draw_test(struct shader_test_info *test_info)
+{
+ struct shader_test_priv test_priv;
+ amdgpu_context_handle context_handle;
+ struct shader_test_bo *ps_bo = &(test_priv.shader_draw.ps_bo);
+ struct shader_test_bo *vs_bo = &(test_priv.shader_draw.vs_bo);
+ struct shader_test_bo *dst = &(test_priv.dst);
+ struct shader_test_bo *cmd = &(test_priv.cmd);
+ struct shader_test_bo *vtx_attributes_mem = &(test_priv.vtx_attributes_mem);
+ amdgpu_bo_handle resources[5];
+ uint8_t *ptr_dst;
+ uint32_t *ptr_cmd;
+ int i, r;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ amdgpu_bo_list_handle bo_list;
+ uint8_t cptr[16];
+
+ memset(&test_priv, 0, sizeof(test_priv));
+ test_priv.info = test_info;
+
+ r = amdgpu_cs_ctx_create(test_info->device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ps_bo->size = 0x2000;
+ ps_bo->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ r = shader_test_bo_alloc(test_info->device_handle, ps_bo);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(ps_bo->ptr, 0, ps_bo->size);
+
+ vs_bo->size = 4096;
+ vs_bo->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ r = shader_test_bo_alloc(test_info->device_handle, vs_bo);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vs_bo->ptr, 0, vs_bo->size);
+
+ test_priv.shader_draw.ps_type = PS_CONST;
+ amdgpu_draw_load_ps_shader(&test_priv);
+
+ test_priv.shader_draw.vs_type = VS_RECTPOSTEXFAST;
+ amdgpu_draw_load_vs_shader(&test_priv);
+
+ cmd->size = 4096;
+ cmd->heap = AMDGPU_GEM_DOMAIN_GTT;
+ r = shader_test_bo_alloc(test_info->device_handle, cmd);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_cmd = cmd->ptr;
+ memset(ptr_cmd, 0, cmd->size);
+
+ dst->size = 0x4000;
+ dst->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ r = shader_test_bo_alloc(test_info->device_handle, dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (test_info->version == AMDGPU_TEST_GFX_V11) {
+ vtx_attributes_mem->size = 0x4040000;
+ vtx_attributes_mem->heap = AMDGPU_GEM_DOMAIN_VRAM;
+
+ r = shader_test_bo_alloc(test_info->device_handle, vtx_attributes_mem);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ amdgpu_draw_init(&test_priv);
+
+ amdgpu_draw_setup_and_write_drawblt_surf_info(&test_priv);
+
+ amdgpu_draw_setup_and_write_drawblt_state(&test_priv);
+
+ amdgpu_draw_vs_RectPosTexFast_write2hw(&test_priv);
+
+ amdgpu_draw_ps_write2hw(&test_priv);
+
+ i = test_priv.cmd_curr;
+ /* ps constant data */
+ ptr_cmd[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr_cmd[i++] = 0xc;
+ ptr_cmd[i++] = 0x33333333;
+ ptr_cmd[i++] = 0x33333333;
+ ptr_cmd[i++] = 0x33333333;
+ ptr_cmd[i++] = 0x33333333;
+ test_priv.cmd_curr = i;
+
+ amdgpu_draw_draw(&test_priv);
+
+ i = test_priv.cmd_curr;
+ while (i & 7)
+ ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */
+ test_priv.cmd_curr = i;
+
+ i = 0;
+ resources[i++] = dst->bo;
+ resources[i++] = ps_bo->bo;
+ resources[i++] = vs_bo->bo;
+ resources[i++] = cmd->bo;
+ if (vtx_attributes_mem->size)
+ resources[i++] = vtx_attributes_mem->bo;
+ r = amdgpu_bo_list_create(test_info->device_handle, i, resources, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ib_info.ib_mc_address = cmd->mc_address;
+ ib_info.size = test_priv.cmd_curr;
+ ibs_request.ip_type = test_info->ip;
+ ibs_request.ring = test_info->ring;
+ ibs_request.resources = bo_list;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ /* submit CS */
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.ip_type = test_info->ip;
+ fence_status.ip_instance = 0;
+ fence_status.ring = test_info->ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request.seq_no;
+
+ /* wait for IB accomplished */
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ /* verify if memset test result meets with expected */
+ i = 0;
+ ptr_dst = dst->ptr;
+ memset(cptr, 0x33, 16);
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+ i = dst->size - 16;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+ i = dst->size / 2;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, cptr, 16), 0);
+
+ if (vtx_attributes_mem->size) {
+ r = shader_test_bo_free(vtx_attributes_mem);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ r = shader_test_bo_free(dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(cmd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(ps_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(vs_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_memcpy_draw_test(struct shader_test_info *test_info)
+{
+ struct shader_test_priv test_priv;
+ amdgpu_context_handle context_handle;
+ struct shader_test_bo *ps_bo = &(test_priv.shader_draw.ps_bo);
+ struct shader_test_bo *vs_bo = &(test_priv.shader_draw.vs_bo);
+ struct shader_test_bo *src = &(test_priv.src);
+ struct shader_test_bo *dst = &(test_priv.dst);
+ struct shader_test_bo *cmd = &(test_priv.cmd);
+ struct shader_test_bo *vtx_attributes_mem = &(test_priv.vtx_attributes_mem);
+ amdgpu_bo_handle resources[6];
+ uint8_t *ptr_dst;
+ uint8_t *ptr_src;
+ uint32_t *ptr_cmd;
+ int i, r;
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ uint32_t hang_state, hangs;
+ uint32_t expired;
+ amdgpu_bo_list_handle bo_list;
+ struct amdgpu_cs_fence fence_status = {0};
+
+ memset(&test_priv, 0, sizeof(test_priv));
+ test_priv.info = test_info;
+ test_priv.cmd.size = 4096;
+ test_priv.cmd.heap = AMDGPU_GEM_DOMAIN_GTT;
+
+ ps_bo->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ test_priv.shader_draw.ps_type = PS_TEX;
+ vs_bo->size = 4096;
+ vs_bo->heap = AMDGPU_GEM_DOMAIN_VRAM;
+ test_priv.shader_draw.vs_type = VS_RECTPOSTEXFAST;
+ test_priv.src.heap = AMDGPU_GEM_DOMAIN_VRAM;
+ test_priv.dst.heap = AMDGPU_GEM_DOMAIN_VRAM;
+ if (test_info->hang_slow) {
+ test_priv.shader_draw.ps_bo.size = 16*1024*1024;
+ test_priv.src.size = 0x4000000;
+ test_priv.dst.size = 0x4000000;
+ } else {
+ test_priv.shader_draw.ps_bo.size = 0x2000;
+ test_priv.src.size = 0x4000;
+ test_priv.dst.size = 0x4000;
+ }
+
+ r = amdgpu_cs_ctx_create(test_info->device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_alloc(test_info->device_handle, ps_bo);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(ps_bo->ptr, 0, ps_bo->size);
+
+ r = shader_test_bo_alloc(test_info->device_handle, vs_bo);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vs_bo->ptr, 0, vs_bo->size);
+
+ amdgpu_draw_load_ps_shader(&test_priv);
+ amdgpu_draw_load_vs_shader(&test_priv);
+
+ r = shader_test_bo_alloc(test_info->device_handle, cmd);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_cmd = cmd->ptr;
+ memset(ptr_cmd, 0, cmd->size);
+
+ r = shader_test_bo_alloc(test_info->device_handle, src);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr_src = src->ptr;
+ memset(ptr_src, 0x55, src->size);
+
+ r = shader_test_bo_alloc(test_info->device_handle, dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (test_info->version == AMDGPU_TEST_GFX_V11) {
+ vtx_attributes_mem->size = 0x4040000;
+ vtx_attributes_mem->heap = AMDGPU_GEM_DOMAIN_VRAM;
+
+ r = shader_test_bo_alloc(test_info->device_handle, vtx_attributes_mem);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ amdgpu_draw_init(&test_priv);
+
+ amdgpu_draw_setup_and_write_drawblt_surf_info(&test_priv);
+
+ amdgpu_draw_setup_and_write_drawblt_state(&test_priv);
+
+ amdgpu_draw_vs_RectPosTexFast_write2hw(&test_priv);
+
+ amdgpu_draw_ps_write2hw(&test_priv);
+
+ // write ps user constant data
+ i = test_priv.cmd_curr;
+ ptr_cmd[i++] = PACKET3(PACKET3_SET_SH_REG, 8);
+ switch (test_info->version) {
+ case AMDGPU_TEST_GFX_V9:
+ ptr_cmd[i++] = 0xc;
+ ptr_cmd[i++] = src->mc_address >> 8;
+ ptr_cmd[i++] = src->mc_address >> 40 | 0x10e00000;
+ ptr_cmd[i++] = test_info->hang_slow ? 0x1ffcfff : 0x7c01f;
+ ptr_cmd[i++] = 0x90500fac;
+ ptr_cmd[i++] = test_info->hang_slow ? 0x1ffe000 : 0x3e000;
+ i += 3;
+ break;
+ case AMDGPU_TEST_GFX_V10:
+ ptr_cmd[i++] = 0xc;
+ ptr_cmd[i++] = src->mc_address >> 8;
+ ptr_cmd[i++] = src->mc_address >> 40 | 0xc4b00000;
+ ptr_cmd[i++] = test_info->hang_slow ? 0x81ffc1ff : 0x8007c007;
+ ptr_cmd[i++] = 0x90500fac;
+ i += 2;
+ ptr_cmd[i++] = test_info->hang_slow ? 0 : 0x400;
+ i++;
+ break;
+ case AMDGPU_TEST_GFX_V11:
+ ptr_cmd[i++] = 0xc;
+ ptr_cmd[i++] = src->mc_address >> 8;
+ ptr_cmd[i++] = src->mc_address >> 40 | 0xc4b00000;
+ ptr_cmd[i++] = test_info->hang_slow ? 0x1ffc1ff : 0x7c007;
+ ptr_cmd[i++] = test_info->hang_slow ? 0x90a00fac : 0x90600fac;
+ i += 2;
+ ptr_cmd[i++] = 0x400;
+ i++;
+ break;
+ }
+
+ ptr_cmd[i++] = PACKET3(PACKET3_SET_SH_REG, 4);
+ ptr_cmd[i++] = 0x14;
+ ptr_cmd[i++] = 0x92;
+ i += 3;
+
+ ptr_cmd[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1);
+ ptr_cmd[i++] = 0x191;
+ ptr_cmd[i++] = 0;
+ test_priv.cmd_curr = i;
+
+ amdgpu_draw_draw(&test_priv);
+
+ i = test_priv.cmd_curr;
+ while (i & 7)
+ ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */
+ test_priv.cmd_curr = i;
+
+ i = 0;
+ resources[i++] = dst->bo;
+ resources[i++] = src->bo;
+ resources[i++] = ps_bo->bo;
+ resources[i++] = vs_bo->bo;
+ resources[i++] = cmd->bo;
+ if (vtx_attributes_mem->size)
+ resources[i++] = vtx_attributes_mem->bo;
+ r = amdgpu_bo_list_create(test_info->device_handle, i, resources, NULL, &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ib_info.ib_mc_address = cmd->mc_address;
+ ib_info.size = test_priv.cmd_curr;
+ ibs_request.ip_type = test_info->ip;
+ ibs_request.ring = test_info->ring;
+ ibs_request.resources = bo_list;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ fence_status.ip_type = test_info->ip;
+ fence_status.ip_instance = 0;
+ fence_status.ring = test_info->ring;
+ fence_status.context = context_handle;
+ fence_status.fence = ibs_request.seq_no;
+
+ /* wait for IB accomplished */
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (!test_info->hang) {
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(expired, true);
+
+ /* verify if memcpy test result meets with expected */
+ i = 0;
+ ptr_dst = dst->ptr;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ i = dst->size - 16;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ i = dst->size / 2;
+ CU_ASSERT_EQUAL(memcmp(ptr_dst + i, ptr_src + i, 16), 0);
+ } else {
+ r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET);
+ }
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (vtx_attributes_mem->size) {
+ r = shader_test_bo_free(vtx_attributes_mem);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ r = shader_test_bo_free(src);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(dst);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(cmd);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(ps_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = shader_test_bo_free(vs_bo);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void shader_test_draw_cb(struct shader_test_info *test_info)
+{
+ amdgpu_memset_draw_test(test_info);
+ amdgpu_memcpy_draw_test(test_info);
+}
+
+static void shader_test_draw_hang_cb(struct shader_test_info *test_info)
+{
+ test_info->hang = 0;
+ amdgpu_memcpy_draw_test(test_info);
+
+ test_info->hang = 1;
+ amdgpu_memcpy_draw_test(test_info);
+
+ test_info->hang = 0;
+ amdgpu_memcpy_draw_test(test_info);
+}
+
+static void shader_test_draw_hang_slow_cb(struct shader_test_info *test_info)
+{
+ test_info->hang = 0;
+ test_info->hang_slow = 0;
+ amdgpu_memcpy_draw_test(test_info);
+
+ test_info->hang = 1;
+ test_info->hang_slow = 1;
+ amdgpu_memcpy_draw_test(test_info);
+
+ test_info->hang = 0;
+ test_info->hang_slow = 0;
+ amdgpu_memcpy_draw_test(test_info);
+}
+
+
+void amdgpu_test_draw_helper(amdgpu_device_handle device_handle)
+{
+ shader_test_for_each(device_handle, AMDGPU_HW_IP_GFX, shader_test_draw_cb);
+}
+
+void amdgpu_test_draw_hang_helper(amdgpu_device_handle device_handle)
+{
+ shader_test_for_each(device_handle, AMDGPU_HW_IP_GFX, shader_test_draw_hang_cb);
+}
+
+void amdgpu_test_draw_hang_slow_helper(amdgpu_device_handle device_handle)
+{
+ shader_test_for_each(device_handle, AMDGPU_HW_IP_GFX, shader_test_draw_hang_slow_cb);
+}
diff --git a/tests/amdgpu/syncobj_tests.c b/tests/amdgpu/syncobj_tests.c
new file mode 100644
index 0000000..690bea0
--- /dev/null
+++ b/tests/amdgpu/syncobj_tests.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include "CUnit/Basic.h"
+#include "xf86drm.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include <pthread.h>
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+
+static uint32_t family_id;
+static uint32_t chip_id;
+static uint32_t chip_rev;
+
+static void amdgpu_syncobj_timeline_test(void);
+
+CU_BOOL suite_syncobj_timeline_tests_enable(void)
+{
+ int r;
+ uint64_t cap = 0;
+
+ r = drmGetCap(drm_amdgpu[0], DRM_CAP_SYNCOBJ_TIMELINE, &cap);
+ if (r || cap == 0)
+ return CU_FALSE;
+
+ return CU_TRUE;
+}
+
+int suite_syncobj_timeline_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+ return CUE_SINIT_FAILED;
+ }
+
+ return CUE_SUCCESS;
+}
+
+int suite_syncobj_timeline_tests_clean(void)
+{
+ int r = amdgpu_device_deinitialize(device_handle);
+
+ if (r == 0)
+ return CUE_SUCCESS;
+ else
+ return CUE_SCLEAN_FAILED;
+}
+
+
+CU_TestInfo syncobj_timeline_tests[] = {
+ { "syncobj timeline test", amdgpu_syncobj_timeline_test },
+ CU_TEST_INFO_NULL,
+};
+
+#define GFX_COMPUTE_NOP 0xffff1000
+#define SDMA_NOP 0x0
+static int syncobj_command_submission_helper(uint32_t syncobj_handle, bool
+ wait_or_signal, uint64_t point)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct drm_amdgpu_cs_chunk chunks[2];
+ struct drm_amdgpu_cs_chunk_data chunk_data;
+ struct drm_amdgpu_cs_chunk_syncobj syncobj_data;
+ struct amdgpu_cs_fence fence_status;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ uint32_t expired;
+ int i, r;
+ uint64_t seq_no;
+ static uint32_t *ptr;
+ struct amdgpu_gpu_info gpu_info = {0};
+ unsigned gc_ip_type;
+
+ r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ family_id = device_handle->info.family_id;
+ chip_id = device_handle->info.chip_external_rev;
+ chip_rev = device_handle->info.chip_rev;
+
+ gc_ip_type = (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) ?
+ AMDGPU_HW_IP_COMPUTE : AMDGPU_HW_IP_GFX;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+
+ for (i = 0; i < 16; ++i)
+ ptr[i] = wait_or_signal ? GFX_COMPUTE_NOP: SDMA_NOP;
+
+ chunks[0].chunk_id = AMDGPU_CHUNK_ID_IB;
+ chunks[0].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
+ chunks[0].chunk_data = (uint64_t)(uintptr_t)&chunk_data;
+ chunk_data.ib_data._pad = 0;
+ chunk_data.ib_data.va_start = ib_result_mc_address;
+ chunk_data.ib_data.ib_bytes = 16 * 4;
+ chunk_data.ib_data.ip_type = wait_or_signal ? gc_ip_type :
+ AMDGPU_HW_IP_DMA;
+ chunk_data.ib_data.ip_instance = 0;
+ chunk_data.ib_data.ring = 0;
+ chunk_data.ib_data.flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC;
+
+ chunks[1].chunk_id = wait_or_signal ?
+ AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT :
+ AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL;
+ chunks[1].length_dw = sizeof(struct drm_amdgpu_cs_chunk_syncobj) / 4;
+ chunks[1].chunk_data = (uint64_t)(uintptr_t)&syncobj_data;
+ syncobj_data.handle = syncobj_handle;
+ syncobj_data.point = point;
+ syncobj_data.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+
+ r = amdgpu_cs_submit_raw(device_handle,
+ context_handle,
+ bo_list,
+ 2,
+ chunks,
+ &seq_no);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = wait_or_signal ? gc_ip_type :
+ AMDGPU_HW_IP_DMA;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ return r;
+}
+
+struct syncobj_point {
+ uint32_t syncobj_handle;
+ uint64_t point;
+};
+
+static void *syncobj_wait(void *data)
+{
+ struct syncobj_point *sp = (struct syncobj_point *)data;
+ int r;
+
+ r = syncobj_command_submission_helper(sp->syncobj_handle, true,
+ sp->point);
+ CU_ASSERT_EQUAL(r, 0);
+
+ return (void *)(long)r;
+}
+
+static void *syncobj_signal(void *data)
+{
+ struct syncobj_point *sp = (struct syncobj_point *)data;
+ int r;
+
+ r = syncobj_command_submission_helper(sp->syncobj_handle, false,
+ sp->point);
+ CU_ASSERT_EQUAL(r, 0);
+
+ return (void *)(long)r;
+}
+
+static void amdgpu_syncobj_timeline_test(void)
+{
+ static pthread_t wait_thread;
+ static pthread_t signal_thread;
+ static pthread_t c_thread;
+ struct syncobj_point sp1, sp2, sp3;
+ uint32_t syncobj_handle;
+ uint64_t payload;
+ uint64_t wait_point, signal_point;
+ uint64_t timeout;
+ struct timespec tp;
+ int r, sync_fd;
+ void *tmp;
+
+ r = amdgpu_cs_create_syncobj2(device_handle, 0, &syncobj_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ // wait on point 5
+ sp1.syncobj_handle = syncobj_handle;
+ sp1.point = 5;
+ r = pthread_create(&wait_thread, NULL, syncobj_wait, &sp1);
+ CU_ASSERT_EQUAL(r, 0);
+
+ // signal on point 10
+ sp2.syncobj_handle = syncobj_handle;
+ sp2.point = 10;
+ r = pthread_create(&signal_thread, NULL, syncobj_signal, &sp2);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = pthread_join(wait_thread, &tmp);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(tmp, 0);
+
+ r = pthread_join(signal_thread, &tmp);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(tmp, 0);
+
+ //query timeline payload
+ r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,
+ &payload, 1);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(payload, 10);
+
+ //signal on point 16
+ sp3.syncobj_handle = syncobj_handle;
+ sp3.point = 16;
+ r = pthread_create(&c_thread, NULL, syncobj_signal, &sp3);
+ CU_ASSERT_EQUAL(r, 0);
+ //CPU wait on point 16
+ wait_point = 16;
+ timeout = 0;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ timeout = tp.tv_sec * 1000000000ULL + tp.tv_nsec;
+ timeout += 0x10000000000; //10s
+ r = amdgpu_cs_syncobj_timeline_wait(device_handle, &syncobj_handle,
+ &wait_point, 1, timeout,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ NULL);
+
+ CU_ASSERT_EQUAL(r, 0);
+ r = pthread_join(c_thread, &tmp);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(tmp, 0);
+
+ // export point 16 and import to point 18
+ r = amdgpu_cs_syncobj_export_sync_file2(device_handle, syncobj_handle,
+ 16,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ &sync_fd);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_syncobj_import_sync_file2(device_handle, syncobj_handle,
+ 18, sync_fd);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,
+ &payload, 1);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(payload, 18);
+
+ // CPU signal on point 20
+ signal_point = 20;
+ r = amdgpu_cs_syncobj_timeline_signal(device_handle, &syncobj_handle,
+ &signal_point, 1);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,
+ &payload, 1);
+ CU_ASSERT_EQUAL(r, 0);
+ CU_ASSERT_EQUAL(payload, 20);
+
+ r = amdgpu_cs_destroy_syncobj(device_handle, syncobj_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+}
diff --git a/tests/amdgpu/uvd_enc_tests.c b/tests/amdgpu/uvd_enc_tests.c
new file mode 100644
index 0000000..b4251bc
--- /dev/null
+++ b/tests/amdgpu/uvd_enc_tests.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "frame.h"
+#include "uve_ib.h"
+
+#define IB_SIZE 4096
+#define MAX_RESOURCES 16
+
+struct amdgpu_uvd_enc_bo {
+ amdgpu_bo_handle handle;
+ amdgpu_va_handle va_handle;
+ uint64_t addr;
+ uint64_t size;
+ uint8_t *ptr;
+};
+
+struct amdgpu_uvd_enc {
+ unsigned width;
+ unsigned height;
+ struct amdgpu_uvd_enc_bo session;
+ struct amdgpu_uvd_enc_bo vbuf;
+ struct amdgpu_uvd_enc_bo bs;
+ struct amdgpu_uvd_enc_bo fb;
+ struct amdgpu_uvd_enc_bo cpb;
+};
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+
+static struct amdgpu_uvd_enc enc;
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static void amdgpu_cs_uvd_enc_create(void);
+static void amdgpu_cs_uvd_enc_session_init(void);
+static void amdgpu_cs_uvd_enc_encode(void);
+static void amdgpu_cs_uvd_enc_destroy(void);
+
+
+CU_TestInfo uvd_enc_tests[] = {
+ { "UVD ENC create", amdgpu_cs_uvd_enc_create },
+ { "UVD ENC session init", amdgpu_cs_uvd_enc_session_init },
+ { "UVD ENC encode", amdgpu_cs_uvd_enc_encode },
+ { "UVD ENC destroy", amdgpu_cs_uvd_enc_destroy },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_uvd_enc_tests_enable(void)
+{
+ int r;
+ struct drm_amdgpu_info_hw_ip info;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info);
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ if (!info.available_rings)
+ printf("\n\nThe ASIC NOT support UVD ENC, suite disabled.\n");
+
+ return (r == 0 && (info.available_rings ? CU_TRUE : CU_FALSE));
+}
+
+
+int suite_uvd_enc_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ family_id = device_handle->info.family_id;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_handle, (void**)&ib_cpu,
+ &ib_mc_address, &ib_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+int suite_uvd_enc_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+ ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ int r;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = ndw;
+
+ ibs_request.ip_type = ip;
+
+ r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+ NULL, &ibs_request.resources);
+ if (r)
+ return r;
+
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo,
+ unsigned size, unsigned domain)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ int r;
+
+ req.alloc_size = ALIGN(size, 4096);
+ req.preferred_heap = domain;
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ uvd_enc_bo->addr = va;
+ uvd_enc_bo->handle = buf_handle;
+ uvd_enc_bo->size = req.alloc_size;
+ uvd_enc_bo->va_handle = va_handle;
+ r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(uvd_enc_bo->ptr, 0, size);
+ r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo)
+{
+ int r;
+
+ r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size,
+ uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(uvd_enc_bo->va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(uvd_enc_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo));
+}
+
+static void amdgpu_cs_uvd_enc_create(void)
+{
+ enc.width = 160;
+ enc.height = 128;
+
+ num_resources = 0;
+ alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.session.handle;
+ resources[num_resources++] = ib_handle;
+}
+
+static void check_result(struct amdgpu_uvd_enc *enc)
+{
+ uint64_t sum;
+ uint32_t s = 175602;
+ uint32_t *ptr, size;
+ int j, r;
+
+ r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr = (uint32_t *)enc->fb.ptr;
+ size = ptr[6];
+ r = amdgpu_bo_cpu_unmap(enc->fb.handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ for (j = 0, sum = 0; j < size; ++j)
+ sum += enc->bs.ptr[j];
+ CU_ASSERT_EQUAL(sum, s);
+ r = amdgpu_bo_cpu_unmap(enc->bs.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+}
+
+static void amdgpu_cs_uvd_enc_session_init(void)
+{
+ int len, r;
+
+ len = 0;
+ memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+ len += sizeof(uve_session_info) / 4;
+ ib_cpu[len++] = enc.session.addr >> 32;
+ ib_cpu[len++] = enc.session.addr;
+
+ memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+ len += sizeof(uve_task_info) / 4;
+ ib_cpu[len++] = 0x000000d8;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+
+ memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init));
+ len += sizeof(uve_op_init) / 4;
+
+ memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init));
+ len += sizeof(uve_session_init) / 4;
+
+ memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl));
+ len += sizeof(uve_layer_ctrl) / 4;
+
+ memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl));
+ len += sizeof(uve_slice_ctrl) / 4;
+
+ memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc));
+ len += sizeof(uve_spec_misc) / 4;
+
+ memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init));
+ len += sizeof(uve_rc_session_init) / 4;
+
+ memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter));
+ len += sizeof(uve_deblocking_filter) / 4;
+
+ memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params));
+ len += sizeof(uve_quality_params) / 4;
+
+ memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc));
+ len += sizeof(uve_op_init_rc) / 4;
+
+ memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level));
+ len += sizeof(uve_op_init_rc_vbv_level) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_uvd_enc_encode(void)
+{
+ int len, r, i;
+ uint64_t luma_offset, chroma_offset;
+ uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
+ cpb_size = vbuf_size * 10;
+
+
+ num_resources = 0;
+ alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.fb.handle;
+ alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.bs.handle;
+ alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.vbuf.handle;
+ alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.cpb.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(enc.vbuf.ptr, 0, vbuf_size);
+ for (i = 0; i < enc.height; ++i) {
+ memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+ for (i = 0; i < enc.height / 2; ++i) {
+ memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+
+ r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ len = 0;
+ memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+ len += sizeof(uve_session_info) / 4;
+ ib_cpu[len++] = enc.session.addr >> 32;
+ ib_cpu[len++] = enc.session.addr;
+
+ memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+ len += sizeof(uve_task_info) / 4;
+ ib_cpu[len++] = 0x000005e0;
+ ib_cpu[len++] = 0x00000001;
+ ib_cpu[len++] = 0x00000001;
+
+ memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1));
+ len += sizeof(uve_nalu_buffer_1) / 4;
+
+ memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2));
+ len += sizeof(uve_nalu_buffer_2) / 4;
+
+ memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3));
+ len += sizeof(uve_nalu_buffer_3) / 4;
+
+ memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4));
+ len += sizeof(uve_nalu_buffer_4) / 4;
+
+ memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header));
+ len += sizeof(uve_slice_header) / 4;
+
+ ib_cpu[len++] = 0x00000254;
+ ib_cpu[len++] = 0x00000010;
+ ib_cpu[len++] = enc.cpb.addr >> 32;
+ ib_cpu[len++] = enc.cpb.addr;
+ memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer));
+ len += sizeof(uve_ctx_buffer) / 4;
+
+ memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer));
+ len += sizeof(uve_bitstream_buffer) / 4;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = enc.bs.addr >> 32;
+ ib_cpu[len++] = enc.bs.addr;
+ ib_cpu[len++] = 0x003f4800;
+ ib_cpu[len++] = 0x00000000;
+
+ memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer));
+ len += sizeof(uve_feedback_buffer) / 4;
+ ib_cpu[len++] = enc.fb.addr >> 32;
+ ib_cpu[len++] = enc.fb.addr;
+ ib_cpu[len++] = 0x00000010;
+ ib_cpu[len++] = 0x00000028;
+
+ memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional));
+ len += sizeof(uve_feedback_buffer_additional) / 4;
+
+ memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh));
+ len += sizeof(uve_intra_refresh) / 4;
+
+ memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+ len += sizeof(uve_layer_select) / 4;
+
+ memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init));
+ len += sizeof(uve_rc_layer_init) / 4;
+
+ memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+ len += sizeof(uve_layer_select) / 4;
+
+ memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic));
+ len += sizeof(uve_rc_per_pic) / 4;
+
+ unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16);
+ luma_offset = enc.vbuf.addr;
+ chroma_offset = luma_offset + luma_size;
+ ib_cpu[len++] = 0x00000054;
+ ib_cpu[len++] = 0x0000000c;
+ ib_cpu[len++] = 0x00000002;
+ ib_cpu[len++] = 0x003f4800;
+ ib_cpu[len++] = luma_offset >> 32;
+ ib_cpu[len++] = luma_offset;
+ ib_cpu[len++] = chroma_offset >> 32;
+ ib_cpu[len++] = chroma_offset;
+ memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param));
+ ib_cpu[len] = ALIGN(enc.width, align);
+ ib_cpu[len + 1] = ALIGN(enc.width, align);
+ len += sizeof(uve_encode_param) / 4;
+
+ memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode));
+ len += sizeof(uve_op_speed_enc_mode) / 4;
+
+ memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode));
+ len += sizeof(uve_op_encode) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+
+ check_result(&enc);
+
+ free_resource(&enc.fb);
+ free_resource(&enc.bs);
+ free_resource(&enc.vbuf);
+ free_resource(&enc.cpb);
+}
+
+static void amdgpu_cs_uvd_enc_destroy(void)
+{
+ int len, r;
+
+ num_resources = 0;
+ resources[num_resources++] = ib_handle;
+
+ len = 0;
+ memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+ len += sizeof(uve_session_info) / 4;
+ ib_cpu[len++] = enc.session.addr >> 32;
+ ib_cpu[len++] = enc.session.addr;
+
+ memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+ len += sizeof(uve_task_info) / 4;
+ ib_cpu[len++] = 0xffffffff;
+ ib_cpu[len++] = 0x00000002;
+ ib_cpu[len++] = 0x00000000;
+
+ memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close));
+ len += sizeof(uve_op_close) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&enc.session);
+}
diff --git a/tests/amdgpu/uve_ib.h b/tests/amdgpu/uve_ib.h
new file mode 100644
index 0000000..cb72be2
--- /dev/null
+++ b/tests/amdgpu/uve_ib.h
@@ -0,0 +1,527 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _uve_ib_h_
+#define _uve_ib_h_
+
+static const uint32_t uve_session_info[] = {
+ 0x00000018,
+ 0x00000001,
+ 0x00000000,
+ 0x00010000,
+};
+
+static const uint32_t uve_task_info[] = {
+ 0x00000014,
+ 0x00000002,
+};
+
+static const uint32_t uve_session_init[] = {
+ 0x00000020,
+ 0x00000003,
+ 0x000000c0,
+ 0x00000080,
+ 0x00000020,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_layer_ctrl[] = {
+ 0x00000010,
+ 0x00000004,
+ 0x00000001,
+ 0x00000001,
+};
+
+static const uint32_t uve_layer_select[] = {
+ 0x0000000c,
+ 0x00000005,
+ 0x00000000,
+};
+
+static const uint32_t uve_slice_ctrl[] = {
+ 0x00000014,
+ 0x00000006,
+ 0x00000000,
+ 0x00000006,
+ 0x00000006,
+};
+
+static const uint32_t uve_spec_misc[] = {
+ 0x00000024,
+ 0x00000007,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+ 0x00000001,
+};
+
+static const uint32_t uve_rc_session_init[] = {
+ 0x00000010,
+ 0x00000008,
+ 0x00000000,
+ 0x00000040,
+};
+
+static const uint32_t uve_rc_layer_init[] = {
+ 0x00000028,
+ 0x00000009,
+ 0x001e8480,
+ 0x001e8480,
+ 0x0000001e,
+ 0x00000001,
+ 0x0001046a,
+ 0x0001046a,
+ 0x0001046a,
+ 0xaaaaaaaa,
+};
+
+static const uint32_t uve_deblocking_filter[] = {
+ 0x00000020,
+ 0x0000000e,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_quality_params[] = {
+ 0x00000014,
+ 0x0000000d,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_feedback_buffer[] = {
+ 0x0000001c,
+ 0x00000012,
+ 0x00000000,
+};
+
+static const uint32_t uve_feedback_buffer_additional[] = {
+ 0x00000108,
+ 0x00000014,
+ 0x00000001,
+ 0x00000010,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_nalu_buffer_1[] = {
+ 0x00000018,
+ 0x00000013,
+ 0x00000001,
+ 0x00000007,
+ 0x00000001,
+ 0x46011000,
+};
+
+static const uint32_t uve_nalu_buffer_2[] = {
+ 0x0000002c,
+ 0x00000013,
+ 0x00000002,
+ 0x0000001b,
+ 0x00000001,
+ 0x40010c01,
+ 0xffff0160,
+ 0x00000300,
+ 0xb0000003,
+ 0x00000300,
+ 0x962c0900,
+};
+
+static const uint32_t uve_nalu_buffer_3[] = {
+ 0x00000034,
+ 0x00000013,
+ 0x00000003,
+ 0x00000023,
+ 0x00000001,
+ 0x42010101,
+ 0x60000003,
+ 0x00b00000,
+ 0x03000003,
+ 0x0096a018,
+ 0x2020708f,
+ 0xcb924295,
+ 0x12e08000,
+};
+
+static const uint32_t uve_nalu_buffer_4[] = {
+ 0x0000001c,
+ 0x00000013,
+ 0x00000004,
+ 0x0000000b,
+ 0x00000001,
+ 0x4401e0f1,
+ 0x80992000,
+};
+
+static const uint32_t uve_slice_header[] = {
+ 0x000000c8,
+ 0x0000000b,
+ 0x28010000,
+ 0x40000000,
+ 0x60000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000002,
+ 0x00000010,
+ 0x00000003,
+ 0x00000000,
+ 0x00000002,
+ 0x00000002,
+ 0x00000004,
+ 0x00000000,
+ 0x00000001,
+ 0x00000000,
+ 0x00000002,
+ 0x00000003,
+ 0x00000005,
+ 0x00000000,
+ 0x00000002,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_encode_param[] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_intra_refresh[] = {
+ 0x00000014,
+ 0x0000000f,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+};
+
+static const uint32_t uve_ctx_buffer[] = {
+ 0x00000000,
+ 0x00000000,
+ 0x000000a0,
+ 0x000000a0,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t uve_bitstream_buffer[] = {
+ 0x0000001c,
+ 0x00000011,
+};
+
+static const uint32_t uve_rc_per_pic[] = {
+ 0x00000024,
+ 0x0000000a,
+ 0x0000001a,
+ 0x00000000,
+ 0x00000033,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+};
+
+static const uint32_t uve_op_init[] = {
+ 0x00000008,
+ 0x08000001,
+};
+
+static const uint32_t uve_op_close[] = {
+ 0x00000008,
+ 0x08000002,
+};
+
+static const uint32_t uve_op_encode[] = {
+ 0x00000008,
+ 0x08000003,
+};
+
+static const uint32_t uve_op_init_rc[] = {
+ 0x00000008,
+ 0x08000004,
+};
+
+static const uint32_t uve_op_init_rc_vbv_level[] = {
+ 0x00000008,
+ 0x08000005,
+};
+
+static const uint32_t uve_op_speed_enc_mode[] = {
+ 0x00000008,
+ 0x08000006,
+};
+
+static const uint32_t uve_op_balance_enc_mode[] = {
+ 0x00000008,
+ 0x08000007,
+};
+
+static const uint32_t uve_op_quality_enc_mode[] = {
+ 0x00000008,
+ 0x08000008,
+};
+#endif /*_uve_ib_h*/
diff --git a/tests/amdgpu/vce_ib.h b/tests/amdgpu/vce_ib.h
new file mode 100644
index 0000000..f3108a0
--- /dev/null
+++ b/tests/amdgpu/vce_ib.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#ifndef _vce_ib_h_
+#define _vce_ib_h_
+
+static const uint32_t vce_session[] = {
+ 0x0000000c,
+ 0x00000001,
+ 0x400c0001,
+};
+
+static uint32_t vce_taskinfo[8] = {
+ 0x00000020,
+ 0x00000002,
+ 0xffffffff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_create[] = {
+ 0x00000030,
+ 0x01000001,
+ 0x00000000,
+ 0x00000042,
+ 0x0000002a,
+ 0x00000000,
+ 0x000000a0,
+ 0x00000080,
+ 0x000000a0,
+ 0x000000a0,
+ 0x00000010,
+ 0x00000201,
+};
+
+static const uint32_t vce_rate_ctrl[] = {
+ 0x00000070,
+ 0x04000005,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x0000001c,
+ 0x0000001c,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000033,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_config_ext[] = {
+ 0x0000000c,
+ 0x04000001,
+ 0x00000003,
+};
+
+static const uint32_t vce_motion_est[] = {
+ 0x00000068,
+ 0x04000007,
+ 0x00000001,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000010,
+ 0x00000010,
+ 0x00000010,
+ 0x00000010,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x000000fe,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_rdo[] = {
+ 0x0000004c,
+ 0x04000008,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_pic_ctrl[] = {
+ 0x00000074,
+ 0x04000002,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000aa0,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000040,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+ 0x00000002,
+ 0x00000001,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_feedback[] = {
+ 0x00000014,
+ 0x05000005,
+ 0x00000000,
+ 0xffffffff,
+ 0x00000001,
+};
+
+static const uint32_t vce_context_buffer[] = {
+ 0x00000010,
+ 0x05000001,
+ 0x00000000,
+ 0xffffffff,
+};
+
+static const uint32_t vce_bs_buffer[] = {
+ 0x00000014,
+ 0x05000004,
+ 0x00000000,
+ 0xffffffff,
+ 0x00154000,
+};
+
+static const uint32_t vce_aux_buffer[] = {
+ 0x00000048,
+ 0x05000002,
+ 0x0000f000,
+ 0x00016800,
+ 0x0001e000,
+ 0x00025800,
+ 0x0002d000,
+ 0x00034800,
+ 0x0003c000,
+ 0x00043800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+ 0x00007800,
+};
+
+static uint32_t vce_encode[88] = {
+ 0x00000160,
+ 0x03000001,
+ 0x00000011,
+ 0x00000000,
+ 0x00154000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0x00000000,
+ 0xffffffff,
+ 0x00000080,
+ 0x000000a0,
+ 0x000000a0,
+ 0x00010000,
+ 0x00000000,
+ 0x00000003,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+ 0x00000001,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0xffffffff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0xffffffff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const uint32_t vce_destroy[] = {
+ 0x00000008,
+ 0x02000001,
+};
+
+static const uint32_t vce_mv_buffer[] = {
+ 0x00000038,
+ 0x0500000d,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+#endif /*_vce_ib_h*/
diff --git a/tests/amdgpu/vce_tests.c b/tests/amdgpu/vce_tests.c
new file mode 100644
index 0000000..9aa0a8e
--- /dev/null
+++ b/tests/amdgpu/vce_tests.c
@@ -0,0 +1,764 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#include "vce_ib.h"
+#include "frame.h"
+
+#define IB_SIZE 4096
+#define MAX_RESOURCES 16
+#define FW_53_0_03 ((53 << 24) | (0 << 16) | (03 << 8))
+
+struct amdgpu_vce_bo {
+ amdgpu_bo_handle handle;
+ amdgpu_va_handle va_handle;
+ uint64_t addr;
+ uint64_t size;
+ uint8_t *ptr;
+};
+
+struct amdgpu_vce_encode {
+ unsigned width;
+ unsigned height;
+ struct amdgpu_vce_bo vbuf;
+ struct amdgpu_vce_bo bs[2];
+ struct amdgpu_vce_bo fb[2];
+ struct amdgpu_vce_bo cpb;
+ unsigned ib_len;
+ bool two_instance;
+ struct amdgpu_vce_bo mvrefbuf;
+ struct amdgpu_vce_bo mvb;
+ unsigned mvbuf_size;
+};
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t vce_harvest_config;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+static uint32_t ids_flags;
+static bool is_mv_supported = true;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+
+static struct amdgpu_vce_encode enc;
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static void amdgpu_cs_vce_create(void);
+static void amdgpu_cs_vce_encode(void);
+static void amdgpu_cs_vce_encode_mv(void);
+static void amdgpu_cs_vce_destroy(void);
+
+CU_TestInfo vce_tests[] = {
+ { "VCE create", amdgpu_cs_vce_create },
+ { "VCE encode", amdgpu_cs_vce_encode },
+ { "VCE MV dump", amdgpu_cs_vce_encode_mv },
+ { "VCE destroy", amdgpu_cs_vce_destroy },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_vce_tests_enable(void)
+{
+ uint32_t version, feature;
+ CU_BOOL ret_mv = CU_FALSE;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ family_id = device_handle->info.family_id;
+ chip_rev = device_handle->info.chip_rev;
+ chip_id = device_handle->info.chip_external_rev;
+ ids_flags = device_handle->info.ids_flags;
+
+ amdgpu_query_firmware_version(device_handle, AMDGPU_INFO_FW_VCE, 0,
+ 0, &version, &feature);
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI ||
+ asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) {
+ printf("\n\nThe ASIC NOT support VCE, suite disabled\n");
+ return CU_FALSE;
+ }
+
+ if (!(chip_id == (chip_rev + 0x3C) || /* FIJI */
+ chip_id == (chip_rev + 0x50) || /* Polaris 10*/
+ chip_id == (chip_rev + 0x5A) || /* Polaris 11*/
+ chip_id == (chip_rev + 0x64) || /* Polaris 12*/
+ (family_id >= AMDGPU_FAMILY_AI && !ids_flags))) /* dGPU > Polaris */
+ printf("\n\nThe ASIC NOT support VCE MV, suite disabled\n");
+ else if (FW_53_0_03 > version)
+ printf("\n\nThe ASIC FW version NOT support VCE MV, suite disabled\n");
+ else
+ ret_mv = CU_TRUE;
+
+ if (ret_mv == CU_FALSE) {
+ amdgpu_set_test_active("VCE Tests", "VCE MV dump", ret_mv);
+ is_mv_supported = false;
+ }
+
+ return CU_TRUE;
+}
+
+int suite_vce_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+
+ return CUE_SINIT_FAILED;
+ }
+
+ family_id = device_handle->info.family_id;
+ vce_harvest_config = device_handle->info.vce_harvest_config;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_handle, (void**)&ib_cpu,
+ &ib_mc_address, &ib_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ memset(&enc, 0, sizeof(struct amdgpu_vce_encode));
+
+ return CUE_SUCCESS;
+}
+
+int suite_vce_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+ ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ int r;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = ndw;
+
+ ibs_request.ip_type = ip;
+
+ r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+ NULL, &ibs_request.resources);
+ if (r)
+ return r;
+
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void alloc_resource(struct amdgpu_vce_bo *vce_bo, unsigned size, unsigned domain)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ int r;
+
+ req.alloc_size = ALIGN(size, 4096);
+ req.preferred_heap = domain;
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ vce_bo->addr = va;
+ vce_bo->handle = buf_handle;
+ vce_bo->size = req.alloc_size;
+ vce_bo->va_handle = va_handle;
+ r = amdgpu_bo_cpu_map(vce_bo->handle, (void **)&vce_bo->ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vce_bo->ptr, 0, size);
+ r = amdgpu_bo_cpu_unmap(vce_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_vce_bo *vce_bo)
+{
+ int r;
+
+ r = amdgpu_bo_va_op(vce_bo->handle, 0, vce_bo->size,
+ vce_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(vce_bo->va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(vce_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vce_bo, 0, sizeof(*vce_bo));
+}
+
+static void amdgpu_cs_vce_create(void)
+{
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ int len, r;
+
+ enc.width = vce_create[6];
+ enc.height = vce_create[7];
+
+ num_resources = 0;
+ alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.fb[0].handle;
+ resources[num_resources++] = ib_handle;
+
+ len = 0;
+ memcpy(ib_cpu, vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_create, sizeof(vce_create));
+ ib_cpu[len + 8] = ALIGN(enc.width, align);
+ ib_cpu[len + 9] = ALIGN(enc.width, align);
+ if (is_mv_supported == true) {/* disableTwoInstance */
+ if (family_id >= AMDGPU_FAMILY_AI)
+ ib_cpu[len + 11] = 0x01000001;
+ else
+ ib_cpu[len + 11] = 0x01000201;
+ }
+ len += sizeof(vce_create) / 4;
+ memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
+ ib_cpu[len + 2] = enc.fb[0].addr >> 32;
+ ib_cpu[len + 3] = enc.fb[0].addr;
+ len += sizeof(vce_feedback) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&enc.fb[0]);
+}
+
+static void amdgpu_cs_vce_config(void)
+{
+ int len = 0, r;
+
+ memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ ib_cpu[len + 3] = 2;
+ ib_cpu[len + 6] = 0xffffffff;
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_rate_ctrl, sizeof(vce_rate_ctrl));
+ len += sizeof(vce_rate_ctrl) / 4;
+ memcpy((ib_cpu + len), vce_config_ext, sizeof(vce_config_ext));
+ len += sizeof(vce_config_ext) / 4;
+ memcpy((ib_cpu + len), vce_motion_est, sizeof(vce_motion_est));
+ len += sizeof(vce_motion_est) / 4;
+ memcpy((ib_cpu + len), vce_rdo, sizeof(vce_rdo));
+ len += sizeof(vce_rdo) / 4;
+ memcpy((ib_cpu + len), vce_pic_ctrl, sizeof(vce_pic_ctrl));
+ if (is_mv_supported == true)
+ ib_cpu[len + 27] = 0x00000001; /* encSliceMode */
+ len += sizeof(vce_pic_ctrl) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc)
+{
+
+ uint64_t luma_offset, chroma_offset;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16);
+ int len = 0, i, r;
+
+ luma_offset = enc->vbuf.addr;
+ chroma_offset = luma_offset + luma_size;
+
+ memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_bs_buffer, sizeof(vce_bs_buffer));
+ ib_cpu[len + 2] = enc->bs[0].addr >> 32;
+ ib_cpu[len + 3] = enc->bs[0].addr;
+ len += sizeof(vce_bs_buffer) / 4;
+ memcpy((ib_cpu + len), vce_context_buffer, sizeof(vce_context_buffer));
+ ib_cpu[len + 2] = enc->cpb.addr >> 32;
+ ib_cpu[len + 3] = enc->cpb.addr;
+ len += sizeof(vce_context_buffer) / 4;
+ memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer));
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2);
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 10 + i] = luma_size * 1.5;
+ len += sizeof(vce_aux_buffer) / 4;
+ memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
+ ib_cpu[len + 2] = enc->fb[0].addr >> 32;
+ ib_cpu[len + 3] = enc->fb[0].addr;
+ len += sizeof(vce_feedback) / 4;
+ memcpy((ib_cpu + len), vce_encode, sizeof(vce_encode));
+ ib_cpu[len + 9] = luma_offset >> 32;
+ ib_cpu[len + 10] = luma_offset;
+ ib_cpu[len + 11] = chroma_offset >> 32;
+ ib_cpu[len + 12] = chroma_offset;
+ ib_cpu[len + 14] = ALIGN(enc->width, align);
+ ib_cpu[len + 15] = ALIGN(enc->width, align);
+ ib_cpu[len + 73] = luma_size * 1.5;
+ ib_cpu[len + 74] = luma_size * 2.5;
+ len += sizeof(vce_encode) / 4;
+ enc->ib_len = len;
+ if (!enc->two_instance) {
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+}
+
+static void amdgpu_cs_vce_encode_p(struct amdgpu_vce_encode *enc)
+{
+ uint64_t luma_offset, chroma_offset;
+ int len, i, r;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16);
+
+ len = (enc->two_instance) ? enc->ib_len : 0;
+ luma_offset = enc->vbuf.addr;
+ chroma_offset = luma_offset + luma_size;
+
+ if (!enc->two_instance) {
+ memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ }
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_bs_buffer, sizeof(vce_bs_buffer));
+ ib_cpu[len + 2] = enc->bs[1].addr >> 32;
+ ib_cpu[len + 3] = enc->bs[1].addr;
+ len += sizeof(vce_bs_buffer) / 4;
+ memcpy((ib_cpu + len), vce_context_buffer, sizeof(vce_context_buffer));
+ ib_cpu[len + 2] = enc->cpb.addr >> 32;
+ ib_cpu[len + 3] = enc->cpb.addr;
+ len += sizeof(vce_context_buffer) / 4;
+ memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer));
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2);
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 10 + i] = luma_size * 1.5;
+ len += sizeof(vce_aux_buffer) / 4;
+ memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
+ ib_cpu[len + 2] = enc->fb[1].addr >> 32;
+ ib_cpu[len + 3] = enc->fb[1].addr;
+ len += sizeof(vce_feedback) / 4;
+ memcpy((ib_cpu + len), vce_encode, sizeof(vce_encode));
+ ib_cpu[len + 2] = 0;
+ ib_cpu[len + 9] = luma_offset >> 32;
+ ib_cpu[len + 10] = luma_offset;
+ ib_cpu[len + 11] = chroma_offset >> 32;
+ ib_cpu[len + 12] = chroma_offset;
+ ib_cpu[len + 14] = ALIGN(enc->width, align);
+ ib_cpu[len + 15] = ALIGN(enc->width, align);
+ ib_cpu[len + 18] = 0;
+ ib_cpu[len + 19] = 0;
+ ib_cpu[len + 56] = 3;
+ ib_cpu[len + 57] = 0;
+ ib_cpu[len + 58] = 0;
+ ib_cpu[len + 59] = luma_size * 1.5;
+ ib_cpu[len + 60] = luma_size * 2.5;
+ ib_cpu[len + 73] = 0;
+ ib_cpu[len + 74] = luma_size;
+ ib_cpu[len + 81] = 1;
+ ib_cpu[len + 82] = 1;
+ len += sizeof(vce_encode) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void check_result(struct amdgpu_vce_encode *enc)
+{
+ uint64_t sum;
+ uint32_t s[2] = {180325, 15946};
+ uint32_t *ptr, size;
+ int i, j, r;
+
+ for (i = 0; i < 2; ++i) {
+ r = amdgpu_bo_cpu_map(enc->fb[i].handle, (void **)&enc->fb[i].ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ ptr = (uint32_t *)enc->fb[i].ptr;
+ size = ptr[4] - ptr[9];
+ r = amdgpu_bo_cpu_unmap(enc->fb[i].handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_map(enc->bs[i].handle, (void **)&enc->bs[i].ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ for (j = 0, sum = 0; j < size; ++j)
+ sum += enc->bs[i].ptr[j];
+ CU_ASSERT_EQUAL(sum, s[i]);
+ r = amdgpu_bo_cpu_unmap(enc->bs[i].handle);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+}
+
+static void amdgpu_cs_vce_encode(void)
+{
+ uint32_t vbuf_size, bs_size = 0x154000, cpb_size;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ int i, r;
+
+ vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
+ cpb_size = vbuf_size * 10;
+ num_resources = 0;
+ alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.fb[0].handle;
+ alloc_resource(&enc.fb[1], 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.fb[1].handle;
+ alloc_resource(&enc.bs[0], bs_size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.bs[0].handle;
+ alloc_resource(&enc.bs[1], bs_size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.bs[1].handle;
+ alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.vbuf.handle;
+ alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.cpb.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(enc.vbuf.ptr, 0, vbuf_size);
+ for (i = 0; i < enc.height; ++i) {
+ memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+ for (i = 0; i < enc.height / 2; ++i) {
+ memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+
+ r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ amdgpu_cs_vce_config();
+
+ if (family_id >= AMDGPU_FAMILY_VI) {
+ vce_taskinfo[3] = 3;
+ amdgpu_cs_vce_encode_idr(&enc);
+ amdgpu_cs_vce_encode_p(&enc);
+ check_result(&enc);
+
+ /* two pipes */
+ vce_encode[16] = 0;
+ amdgpu_cs_vce_encode_idr(&enc);
+ amdgpu_cs_vce_encode_p(&enc);
+ check_result(&enc);
+
+ /* two instances */
+ if (vce_harvest_config == 0) {
+ enc.two_instance = true;
+ vce_taskinfo[2] = 0x83;
+ vce_taskinfo[4] = 1;
+ amdgpu_cs_vce_encode_idr(&enc);
+ vce_taskinfo[2] = 0xffffffff;
+ vce_taskinfo[4] = 2;
+ amdgpu_cs_vce_encode_p(&enc);
+ check_result(&enc);
+ }
+ } else {
+ vce_taskinfo[3] = 3;
+ vce_encode[16] = 0;
+ amdgpu_cs_vce_encode_idr(&enc);
+ amdgpu_cs_vce_encode_p(&enc);
+ check_result(&enc);
+ }
+
+ free_resource(&enc.fb[0]);
+ free_resource(&enc.fb[1]);
+ free_resource(&enc.bs[0]);
+ free_resource(&enc.bs[1]);
+ free_resource(&enc.vbuf);
+ free_resource(&enc.cpb);
+}
+
+static void amdgpu_cs_vce_mv(struct amdgpu_vce_encode *enc)
+{
+ uint64_t luma_offset, chroma_offset;
+ uint64_t mv_ref_luma_offset;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16);
+ int len = 0, i, r;
+
+ luma_offset = enc->vbuf.addr;
+ chroma_offset = luma_offset + luma_size;
+ mv_ref_luma_offset = enc->mvrefbuf.addr;
+
+ memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_bs_buffer, sizeof(vce_bs_buffer));
+ ib_cpu[len + 2] = enc->bs[0].addr >> 32;
+ ib_cpu[len + 3] = enc->bs[0].addr;
+ len += sizeof(vce_bs_buffer) / 4;
+ memcpy((ib_cpu + len), vce_context_buffer, sizeof(vce_context_buffer));
+ ib_cpu[len + 2] = enc->cpb.addr >> 32;
+ ib_cpu[len + 3] = enc->cpb.addr;
+ len += sizeof(vce_context_buffer) / 4;
+ memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer));
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2);
+ for (i = 0; i < 8; ++i)
+ ib_cpu[len + 10 + i] = luma_size * 1.5;
+ len += sizeof(vce_aux_buffer) / 4;
+ memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
+ ib_cpu[len + 2] = enc->fb[0].addr >> 32;
+ ib_cpu[len + 3] = enc->fb[0].addr;
+ len += sizeof(vce_feedback) / 4;
+ memcpy((ib_cpu + len), vce_mv_buffer, sizeof(vce_mv_buffer));
+ ib_cpu[len + 2] = mv_ref_luma_offset >> 32;
+ ib_cpu[len + 3] = mv_ref_luma_offset;
+ ib_cpu[len + 4] = ALIGN(enc->width, align);
+ ib_cpu[len + 5] = ALIGN(enc->width, align);
+ ib_cpu[len + 6] = luma_size;
+ ib_cpu[len + 7] = enc->mvb.addr >> 32;
+ ib_cpu[len + 8] = enc->mvb.addr;
+ len += sizeof(vce_mv_buffer) / 4;
+ memcpy((ib_cpu + len), vce_encode, sizeof(vce_encode));
+ ib_cpu[len + 2] = 0;
+ ib_cpu[len + 3] = 0;
+ ib_cpu[len + 4] = 0x154000;
+ ib_cpu[len + 9] = luma_offset >> 32;
+ ib_cpu[len + 10] = luma_offset;
+ ib_cpu[len + 11] = chroma_offset >> 32;
+ ib_cpu[len + 12] = chroma_offset;
+ ib_cpu[len + 13] = ALIGN(enc->height, 16);;
+ ib_cpu[len + 14] = ALIGN(enc->width, align);
+ ib_cpu[len + 15] = ALIGN(enc->width, align);
+ /* encDisableMBOffloading-encDisableTwoPipeMode-encInputPicArrayMode-encInputPicAddrMode */
+ ib_cpu[len + 16] = 0x01010000;
+ ib_cpu[len + 18] = 0; /* encPicType */
+ ib_cpu[len + 19] = 0; /* encIdrFlag */
+ ib_cpu[len + 20] = 0; /* encIdrPicId */
+ ib_cpu[len + 21] = 0; /* encMGSKeyPic */
+ ib_cpu[len + 22] = 0; /* encReferenceFlag */
+ ib_cpu[len + 23] = 0; /* encTemporalLayerIndex */
+ ib_cpu[len + 55] = 0; /* pictureStructure */
+ ib_cpu[len + 56] = 0; /* encPicType -ref[0] */
+ ib_cpu[len + 61] = 0; /* pictureStructure */
+ ib_cpu[len + 62] = 0; /* encPicType -ref[1] */
+ ib_cpu[len + 67] = 0; /* pictureStructure */
+ ib_cpu[len + 68] = 0; /* encPicType -ref1 */
+ ib_cpu[len + 81] = 1; /* frameNumber */
+ ib_cpu[len + 82] = 2; /* pictureOrderCount */
+ ib_cpu[len + 83] = 0xffffffff; /* numIPicRemainInRCGOP */
+ ib_cpu[len + 84] = 0xffffffff; /* numPPicRemainInRCGOP */
+ ib_cpu[len + 85] = 0xffffffff; /* numBPicRemainInRCGOP */
+ ib_cpu[len + 86] = 0xffffffff; /* numIRPicRemainInRCGOP */
+ ib_cpu[len + 87] = 0; /* remainedIntraRefreshPictures */
+ len += sizeof(vce_encode) / 4;
+
+ enc->ib_len = len;
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void check_mv_result(struct amdgpu_vce_encode *enc)
+{
+ uint64_t sum;
+ uint32_t s = 140790;
+ int j, r;
+
+ r = amdgpu_bo_cpu_map(enc->fb[0].handle, (void **)&enc->fb[0].ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_unmap(enc->fb[0].handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_map(enc->mvb.handle, (void **)&enc->mvb.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ for (j = 0, sum = 0; j < enc->mvbuf_size; ++j)
+ sum += enc->mvb.ptr[j];
+ CU_ASSERT_EQUAL(sum, s);
+ r = amdgpu_bo_cpu_unmap(enc->mvb.handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_vce_encode_mv(void)
+{
+ uint32_t vbuf_size, bs_size = 0x154000, cpb_size;
+ unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+ int i, r;
+
+ vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
+ enc.mvbuf_size = ALIGN(enc.width, 16) * ALIGN(enc.height, 16) / 8;
+ cpb_size = vbuf_size * 10;
+ num_resources = 0;
+ alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.fb[0].handle;
+ alloc_resource(&enc.bs[0], bs_size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.bs[0].handle;
+ alloc_resource(&enc.mvb, enc.mvbuf_size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.mvb.handle;
+ alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.vbuf.handle;
+ alloc_resource(&enc.mvrefbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.mvrefbuf.handle;
+ alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM);
+ resources[num_resources++] = enc.cpb.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(enc.vbuf.ptr, 0, vbuf_size);
+ for (i = 0; i < enc.height; ++i) {
+ memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+ for (i = 0; i < enc.height / 2; ++i) {
+ memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
+ enc.vbuf.ptr += ALIGN(enc.width, align);
+ }
+
+ r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_cpu_map(enc.mvrefbuf.handle, (void **)&enc.mvrefbuf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(enc.mvrefbuf.ptr, 0, vbuf_size);
+ for (i = 0; i < enc.height; ++i) {
+ memcpy(enc.mvrefbuf.ptr, (frame + (enc.height - i -1) * enc.width), enc.width);
+ enc.mvrefbuf.ptr += ALIGN(enc.width, align);
+ }
+ for (i = 0; i < enc.height / 2; ++i) {
+ memcpy(enc.mvrefbuf.ptr,
+ ((frame + enc.height * enc.width) + (enc.height / 2 - i -1) * enc.width), enc.width);
+ enc.mvrefbuf.ptr += ALIGN(enc.width, align);
+ }
+
+ r = amdgpu_bo_cpu_unmap(enc.mvrefbuf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ amdgpu_cs_vce_config();
+
+ vce_taskinfo[3] = 3;
+ amdgpu_cs_vce_mv(&enc);
+ check_mv_result(&enc);
+
+ free_resource(&enc.fb[0]);
+ free_resource(&enc.bs[0]);
+ free_resource(&enc.vbuf);
+ free_resource(&enc.cpb);
+ free_resource(&enc.mvrefbuf);
+ free_resource(&enc.mvb);
+}
+
+static void amdgpu_cs_vce_destroy(void)
+{
+ int len, r;
+
+ num_resources = 0;
+ alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc.fb[0].handle;
+ resources[num_resources++] = ib_handle;
+
+ len = 0;
+ memcpy(ib_cpu, vce_session, sizeof(vce_session));
+ len += sizeof(vce_session) / 4;
+ memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
+ ib_cpu[len + 3] = 1;
+ len += sizeof(vce_taskinfo) / 4;
+ memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
+ ib_cpu[len + 2] = enc.fb[0].addr >> 32;
+ ib_cpu[len + 3] = enc.fb[0].addr;
+ len += sizeof(vce_feedback) / 4;
+ memcpy((ib_cpu + len), vce_destroy, sizeof(vce_destroy));
+ len += sizeof(vce_destroy) / 4;
+
+ r = submit(len, AMDGPU_HW_IP_VCE);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&enc.fb[0]);
+}
diff --git a/tests/amdgpu/vcn_tests.c b/tests/amdgpu/vcn_tests.c
new file mode 100644
index 0000000..5e20fb6
--- /dev/null
+++ b/tests/amdgpu/vcn_tests.c
@@ -0,0 +1,1635 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include "CUnit/Basic.h"
+
+#include <unistd.h>
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "decode_messages.h"
+#include "frame.h"
+
+#define IB_SIZE 4096
+#define MAX_RESOURCES 16
+
+#define DECODE_CMD_MSG_BUFFER 0x00000000
+#define DECODE_CMD_DPB_BUFFER 0x00000001
+#define DECODE_CMD_DECODING_TARGET_BUFFER 0x00000002
+#define DECODE_CMD_FEEDBACK_BUFFER 0x00000003
+#define DECODE_CMD_PROB_TBL_BUFFER 0x00000004
+#define DECODE_CMD_SESSION_CONTEXT_BUFFER 0x00000005
+#define DECODE_CMD_BITSTREAM_BUFFER 0x00000100
+#define DECODE_CMD_IT_SCALING_TABLE_BUFFER 0x00000204
+#define DECODE_CMD_CONTEXT_BUFFER 0x00000206
+
+#define DECODE_IB_PARAM_DECODE_BUFFER (0x00000001)
+
+#define DECODE_CMDBUF_FLAGS_MSG_BUFFER (0x00000001)
+#define DECODE_CMDBUF_FLAGS_DPB_BUFFER (0x00000002)
+#define DECODE_CMDBUF_FLAGS_BITSTREAM_BUFFER (0x00000004)
+#define DECODE_CMDBUF_FLAGS_DECODING_TARGET_BUFFER (0x00000008)
+#define DECODE_CMDBUF_FLAGS_FEEDBACK_BUFFER (0x00000010)
+#define DECODE_CMDBUF_FLAGS_IT_SCALING_BUFFER (0x00000200)
+#define DECODE_CMDBUF_FLAGS_CONTEXT_BUFFER (0x00000800)
+#define DECODE_CMDBUF_FLAGS_PROB_TBL_BUFFER (0x00001000)
+#define DECODE_CMDBUF_FLAGS_SESSION_CONTEXT_BUFFER (0x00100000)
+
+static bool vcn_dec_sw_ring = false;
+static bool vcn_unified_ring = false;
+
+#define H264_NAL_TYPE_NON_IDR_SLICE 1
+#define H264_NAL_TYPE_DP_A_SLICE 2
+#define H264_NAL_TYPE_DP_B_SLICE 3
+#define H264_NAL_TYPE_DP_C_SLICE 0x4
+#define H264_NAL_TYPE_IDR_SLICE 0x5
+#define H264_NAL_TYPE_SEI 0x6
+#define H264_NAL_TYPE_SEQ_PARAM 0x7
+#define H264_NAL_TYPE_PIC_PARAM 0x8
+#define H264_NAL_TYPE_ACCESS_UNIT 0x9
+#define H264_NAL_TYPE_END_OF_SEQ 0xa
+#define H264_NAL_TYPE_END_OF_STREAM 0xb
+#define H264_NAL_TYPE_FILLER_DATA 0xc
+#define H264_NAL_TYPE_SEQ_EXTENSION 0xd
+
+#define H264_START_CODE 0x000001
+
+struct amdgpu_vcn_bo {
+ amdgpu_bo_handle handle;
+ amdgpu_va_handle va_handle;
+ uint64_t addr;
+ uint64_t size;
+ uint8_t *ptr;
+};
+
+typedef struct rvcn_decode_buffer_s {
+ unsigned int valid_buf_flag;
+ unsigned int msg_buffer_address_hi;
+ unsigned int msg_buffer_address_lo;
+ unsigned int dpb_buffer_address_hi;
+ unsigned int dpb_buffer_address_lo;
+ unsigned int target_buffer_address_hi;
+ unsigned int target_buffer_address_lo;
+ unsigned int session_contex_buffer_address_hi;
+ unsigned int session_contex_buffer_address_lo;
+ unsigned int bitstream_buffer_address_hi;
+ unsigned int bitstream_buffer_address_lo;
+ unsigned int context_buffer_address_hi;
+ unsigned int context_buffer_address_lo;
+ unsigned int feedback_buffer_address_hi;
+ unsigned int feedback_buffer_address_lo;
+ unsigned int luma_hist_buffer_address_hi;
+ unsigned int luma_hist_buffer_address_lo;
+ unsigned int prob_tbl_buffer_address_hi;
+ unsigned int prob_tbl_buffer_address_lo;
+ unsigned int sclr_coeff_buffer_address_hi;
+ unsigned int sclr_coeff_buffer_address_lo;
+ unsigned int it_sclr_table_buffer_address_hi;
+ unsigned int it_sclr_table_buffer_address_lo;
+ unsigned int sclr_target_buffer_address_hi;
+ unsigned int sclr_target_buffer_address_lo;
+ unsigned int cenc_size_info_buffer_address_hi;
+ unsigned int cenc_size_info_buffer_address_lo;
+ unsigned int mpeg2_pic_param_buffer_address_hi;
+ unsigned int mpeg2_pic_param_buffer_address_lo;
+ unsigned int mpeg2_mb_control_buffer_address_hi;
+ unsigned int mpeg2_mb_control_buffer_address_lo;
+ unsigned int mpeg2_idct_coeff_buffer_address_hi;
+ unsigned int mpeg2_idct_coeff_buffer_address_lo;
+} rvcn_decode_buffer_t;
+
+typedef struct rvcn_decode_ib_package_s {
+ unsigned int package_size;
+ unsigned int package_type;
+} rvcn_decode_ib_package_t;
+
+
+struct amdgpu_vcn_reg {
+ uint32_t data0;
+ uint32_t data1;
+ uint32_t cmd;
+ uint32_t nop;
+ uint32_t cntl;
+};
+
+typedef struct BufferInfo_t {
+ uint32_t numOfBitsInBuffer;
+ const uint8_t *decBuffer;
+ uint8_t decData;
+ uint32_t decBufferSize;
+ const uint8_t *end;
+} bufferInfo;
+
+typedef struct h264_decode_t {
+ uint8_t profile;
+ uint8_t level_idc;
+ uint8_t nal_ref_idc;
+ uint8_t nal_unit_type;
+ uint32_t pic_width, pic_height;
+ uint32_t slice_type;
+} h264_decode;
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t chip_rev;
+static uint32_t chip_id;
+static uint32_t asic_id;
+static uint32_t chip_rev;
+static struct amdgpu_vcn_bo enc_buf;
+static struct amdgpu_vcn_bo cpb_buf;
+static uint32_t enc_task_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+static uint32_t *ib_checksum;
+static uint32_t *ib_size_in_dw;
+
+static rvcn_decode_buffer_t *decode_buffer;
+
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static uint8_t vcn_reg_index;
+static struct amdgpu_vcn_reg reg[] = {
+ {0x81c4, 0x81c5, 0x81c3, 0x81ff, 0x81c6},
+ {0x504, 0x505, 0x503, 0x53f, 0x506},
+ {0x10, 0x11, 0xf, 0x29, 0x26d},
+};
+
+uint32_t gWidth, gHeight, gSliceType;
+static uint32_t vcn_ip_version_major;
+static uint32_t vcn_ip_version_minor;
+static void amdgpu_cs_vcn_dec_create(void);
+static void amdgpu_cs_vcn_dec_decode(void);
+static void amdgpu_cs_vcn_dec_destroy(void);
+
+static void amdgpu_cs_vcn_enc_create(void);
+static void amdgpu_cs_vcn_enc_encode(void);
+static void amdgpu_cs_vcn_enc_destroy(void);
+
+static void amdgpu_cs_sq_head(uint32_t *base, int *offset, bool enc);
+static void amdgpu_cs_sq_ib_tail(uint32_t *end);
+static void h264_check_0s (bufferInfo * bufInfo, int count);
+static int32_t h264_se (bufferInfo * bufInfo);
+static inline uint32_t bs_read_u1(bufferInfo *bufinfo);
+static inline int bs_eof(bufferInfo *bufinfo);
+static inline uint32_t bs_read_u(bufferInfo* bufinfo, int n);
+static inline uint32_t bs_read_ue(bufferInfo* bufinfo);
+static uint32_t remove_03 (uint8_t *bptr, uint32_t len);
+static void scaling_list (uint32_t ix, uint32_t sizeOfScalingList, bufferInfo *bufInfo);
+static void h264_parse_sequence_parameter_set (h264_decode * dec, bufferInfo *bufInfo);
+static void h264_slice_header (h264_decode *dec, bufferInfo *bufInfo);
+static uint8_t h264_parse_nal (h264_decode *dec, bufferInfo *bufInfo);
+static uint32_t h264_find_next_start_code (uint8_t *pBuf, uint32_t bufLen);
+static int verify_checksum(uint8_t *buffer, uint32_t buffer_size);
+
+CU_TestInfo vcn_tests[] = {
+
+ { "VCN DEC create", amdgpu_cs_vcn_dec_create },
+ { "VCN DEC decode", amdgpu_cs_vcn_dec_decode },
+ { "VCN DEC destroy", amdgpu_cs_vcn_dec_destroy },
+
+ { "VCN ENC create", amdgpu_cs_vcn_enc_create },
+ { "VCN ENC encode", amdgpu_cs_vcn_enc_encode },
+ { "VCN ENC destroy", amdgpu_cs_vcn_enc_destroy },
+ CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_vcn_tests_enable(void)
+{
+ struct drm_amdgpu_info_hw_ip info;
+ bool enc_ring, dec_ring;
+ int r;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ family_id = device_handle->info.family_id;
+ asic_id = device_handle->info.asic_id;
+ chip_rev = device_handle->info.chip_rev;
+ chip_id = device_handle->info.chip_external_rev;
+
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_VCN_ENC, 0, &info);
+ if (!r) {
+ vcn_ip_version_major = info.hw_ip_version_major;
+ vcn_ip_version_minor = info.hw_ip_version_minor;
+ enc_ring = !!info.available_rings;
+ /* in vcn 4.0 it re-uses encoding queue as unified queue */
+ if (vcn_ip_version_major >= 4) {
+ vcn_unified_ring = true;
+ vcn_dec_sw_ring = true;
+ dec_ring = enc_ring;
+ } else {
+ r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_VCN_DEC, 0, &info);
+ dec_ring = !!info.available_rings;
+ }
+ }
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ if (r) {
+ printf("\n\nASIC query hw info failed\n");
+ return CU_FALSE;
+ }
+
+ if (!(dec_ring || enc_ring) ||
+ (family_id < AMDGPU_FAMILY_RV &&
+ (family_id == AMDGPU_FAMILY_AI &&
+ (chip_id - chip_rev) < 0x32))) { /* Arcturus */
+ printf("\n\nThe ASIC NOT support VCN, suite disabled\n");
+ return CU_FALSE;
+ }
+
+ if (!dec_ring) {
+ amdgpu_set_test_active("VCN Tests", "VCN DEC create", CU_FALSE);
+ amdgpu_set_test_active("VCN Tests", "VCN DEC decode", CU_FALSE);
+ amdgpu_set_test_active("VCN Tests", "VCN DEC destroy", CU_FALSE);
+ }
+
+ if (family_id == AMDGPU_FAMILY_AI || !enc_ring) {
+ amdgpu_set_test_active("VCN Tests", "VCN ENC create", CU_FALSE);
+ amdgpu_set_test_active("VCN Tests", "VCN ENC encode", CU_FALSE);
+ amdgpu_set_test_active("VCN Tests", "VCN ENC destroy", CU_FALSE);
+ }
+
+ if (vcn_ip_version_major == 1)
+ vcn_reg_index = 0;
+ else if (vcn_ip_version_major == 2 && vcn_ip_version_minor == 0)
+ vcn_reg_index = 1;
+ else if ((vcn_ip_version_major == 2 && vcn_ip_version_minor >= 5) ||
+ vcn_ip_version_major == 3)
+ vcn_reg_index = 2;
+
+ return CU_TRUE;
+}
+
+int suite_vcn_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ family_id = device_handle->info.family_id;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_handle, (void**)&ib_cpu,
+ &ib_mc_address, &ib_va_handle);
+ if (r)
+ return CUE_SINIT_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+int suite_vcn_tests_clean(void)
+{
+ int r;
+
+ r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+ ib_mc_address, IB_SIZE);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ r = amdgpu_device_deinitialize(device_handle);
+ if (r)
+ return CUE_SCLEAN_FAILED;
+
+ return CUE_SUCCESS;
+}
+
+static void amdgpu_cs_sq_head(uint32_t *base, int *offset, bool enc)
+{
+ /* signature */
+ *(base + (*offset)++) = 0x00000010;
+ *(base + (*offset)++) = 0x30000002;
+ ib_checksum = base + (*offset)++;
+ ib_size_in_dw = base + (*offset)++;
+
+ /* engine info */
+ *(base + (*offset)++) = 0x00000010;
+ *(base + (*offset)++) = 0x30000001;
+ *(base + (*offset)++) = enc ? 2 : 3;
+ *(base + (*offset)++) = 0x00000000;
+}
+
+static void amdgpu_cs_sq_ib_tail(uint32_t *end)
+{
+ uint32_t size_in_dw;
+ uint32_t checksum = 0;
+
+ /* if the pointers are invalid, no need to process */
+ if (ib_checksum == NULL || ib_size_in_dw == NULL)
+ return;
+
+ size_in_dw = end - ib_size_in_dw - 1;
+ *ib_size_in_dw = size_in_dw;
+ *(ib_size_in_dw + 4) = size_in_dw * sizeof(uint32_t);
+
+ for (int i = 0; i < size_in_dw; i++)
+ checksum += *(ib_checksum + 2 + i);
+
+ *ib_checksum = checksum;
+
+ ib_checksum = NULL;
+ ib_size_in_dw = NULL;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+ struct amdgpu_cs_request ibs_request = {0};
+ struct amdgpu_cs_ib_info ib_info = {0};
+ struct amdgpu_cs_fence fence_status = {0};
+ uint32_t expired;
+ int r;
+
+ ib_info.ib_mc_address = ib_mc_address;
+ ib_info.size = ndw;
+
+ ibs_request.ip_type = ip;
+
+ r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+ NULL, &ibs_request.resources);
+ if (r)
+ return r;
+
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+ if (r)
+ return r;
+
+ r = amdgpu_bo_list_destroy(ibs_request.resources);
+ if (r)
+ return r;
+
+ fence_status.context = context_handle;
+ fence_status.ip_type = ip;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,
+ 0, &expired);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void alloc_resource(struct amdgpu_vcn_bo *vcn_bo,
+ unsigned size, unsigned domain)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle va_handle;
+ uint64_t va = 0;
+ int r;
+
+ req.alloc_size = ALIGN(size, 4096);
+ req.preferred_heap = domain;
+ r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_va_range_alloc(device_handle,
+ amdgpu_gpu_va_range_general,
+ req.alloc_size, 1, 0, &va,
+ &va_handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ vcn_bo->addr = va;
+ vcn_bo->handle = buf_handle;
+ vcn_bo->size = req.alloc_size;
+ vcn_bo->va_handle = va_handle;
+ r = amdgpu_bo_cpu_map(vcn_bo->handle, (void **)&vcn_bo->ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vcn_bo->ptr, 0, size);
+ r = amdgpu_bo_cpu_unmap(vcn_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_vcn_bo *vcn_bo)
+{
+ int r;
+
+ r = amdgpu_bo_va_op(vcn_bo->handle, 0, vcn_bo->size,
+ vcn_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_va_range_free(vcn_bo->va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_free(vcn_bo->handle);
+ CU_ASSERT_EQUAL(r, 0);
+ memset(vcn_bo, 0, sizeof(*vcn_bo));
+}
+
+static void vcn_dec_cmd(uint64_t addr, unsigned cmd, int *idx)
+{
+ if (vcn_dec_sw_ring == false) {
+ ib_cpu[(*idx)++] = reg[vcn_reg_index].data0;
+ ib_cpu[(*idx)++] = addr;
+ ib_cpu[(*idx)++] = reg[vcn_reg_index].data1;
+ ib_cpu[(*idx)++] = addr >> 32;
+ ib_cpu[(*idx)++] = reg[vcn_reg_index].cmd;
+ ib_cpu[(*idx)++] = cmd << 1;
+ return;
+ }
+
+ /* Support decode software ring message */
+ if (!(*idx)) {
+ rvcn_decode_ib_package_t *ib_header;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_head(ib_cpu, idx, false);
+
+ ib_header = (rvcn_decode_ib_package_t *)&ib_cpu[*idx];
+ ib_header->package_size = sizeof(struct rvcn_decode_buffer_s) +
+ sizeof(struct rvcn_decode_ib_package_s);
+
+ (*idx)++;
+ ib_header->package_type = (DECODE_IB_PARAM_DECODE_BUFFER);
+ (*idx)++;
+
+ decode_buffer = (rvcn_decode_buffer_t *)&(ib_cpu[*idx]);
+ *idx += sizeof(struct rvcn_decode_buffer_s) / 4;
+ memset(decode_buffer, 0, sizeof(struct rvcn_decode_buffer_s));
+ }
+
+ switch(cmd) {
+ case DECODE_CMD_MSG_BUFFER:
+ decode_buffer->valid_buf_flag |= DECODE_CMDBUF_FLAGS_MSG_BUFFER;
+ decode_buffer->msg_buffer_address_hi = (addr >> 32);
+ decode_buffer->msg_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_DPB_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_DPB_BUFFER);
+ decode_buffer->dpb_buffer_address_hi = (addr >> 32);
+ decode_buffer->dpb_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_DECODING_TARGET_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_DECODING_TARGET_BUFFER);
+ decode_buffer->target_buffer_address_hi = (addr >> 32);
+ decode_buffer->target_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_FEEDBACK_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_FEEDBACK_BUFFER);
+ decode_buffer->feedback_buffer_address_hi = (addr >> 32);
+ decode_buffer->feedback_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_PROB_TBL_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_PROB_TBL_BUFFER);
+ decode_buffer->prob_tbl_buffer_address_hi = (addr >> 32);
+ decode_buffer->prob_tbl_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_SESSION_CONTEXT_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_SESSION_CONTEXT_BUFFER);
+ decode_buffer->session_contex_buffer_address_hi = (addr >> 32);
+ decode_buffer->session_contex_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_BITSTREAM_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_BITSTREAM_BUFFER);
+ decode_buffer->bitstream_buffer_address_hi = (addr >> 32);
+ decode_buffer->bitstream_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_IT_SCALING_TABLE_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_IT_SCALING_BUFFER);
+ decode_buffer->it_sclr_table_buffer_address_hi = (addr >> 32);
+ decode_buffer->it_sclr_table_buffer_address_lo = (addr);
+ break;
+ case DECODE_CMD_CONTEXT_BUFFER:
+ decode_buffer->valid_buf_flag |= (DECODE_CMDBUF_FLAGS_CONTEXT_BUFFER);
+ decode_buffer->context_buffer_address_hi = (addr >> 32);
+ decode_buffer->context_buffer_address_lo = (addr);
+ break;
+ default:
+ printf("Not Support!\n");
+ }
+}
+
+static void amdgpu_cs_vcn_dec_create(void)
+{
+ struct amdgpu_vcn_bo msg_buf;
+ unsigned ip;
+ int len, r;
+
+ num_resources = 0;
+ alloc_resource(&msg_buf, 4096, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = msg_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(msg_buf.ptr, 0, 4096);
+ memcpy(msg_buf.ptr, vcn_dec_create_msg, sizeof(vcn_dec_create_msg));
+
+ len = 0;
+ if (vcn_dec_sw_ring == true)
+ vcn_dec_cmd(msg_buf.addr, 0, &len);
+ else {
+ ib_cpu[len++] = reg[vcn_reg_index].data0;
+ ib_cpu[len++] = msg_buf.addr;
+ ib_cpu[len++] = reg[vcn_reg_index].data1;
+ ib_cpu[len++] = msg_buf.addr >> 32;
+ ib_cpu[len++] = reg[vcn_reg_index].cmd;
+ ib_cpu[len++] = 0;
+ for (; len % 16; ) {
+ ib_cpu[len++] = reg[vcn_reg_index].nop;
+ ib_cpu[len++] = 0;
+ }
+ }
+
+ if (vcn_unified_ring) {
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+ ip = AMDGPU_HW_IP_VCN_ENC;
+ } else
+ ip = AMDGPU_HW_IP_VCN_DEC;
+
+ r = submit(len, ip);
+
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&msg_buf);
+}
+
+static void amdgpu_cs_vcn_dec_decode(void)
+{
+ const unsigned dpb_size = 15923584, dt_size = 737280;
+ uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr, sum;
+ struct amdgpu_vcn_bo dec_buf;
+ int size, len, i, r;
+ unsigned ip;
+ uint8_t *dec;
+
+ size = 4*1024; /* msg */
+ size += 4*1024; /* fb */
+ size += 4096; /*it_scaling_table*/
+ size += ALIGN(sizeof(uvd_bitstream), 4*1024);
+ size += ALIGN(dpb_size, 4*1024);
+ size += ALIGN(dt_size, 4*1024);
+
+ num_resources = 0;
+ alloc_resource(&dec_buf, size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = dec_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr);
+ dec = dec_buf.ptr;
+
+ CU_ASSERT_EQUAL(r, 0);
+ memset(dec_buf.ptr, 0, size);
+ memcpy(dec_buf.ptr, vcn_dec_decode_msg, sizeof(vcn_dec_decode_msg));
+ memcpy(dec_buf.ptr + sizeof(vcn_dec_decode_msg),
+ avc_decode_msg, sizeof(avc_decode_msg));
+
+ dec += 4*1024;
+ memcpy(dec, feedback_msg, sizeof(feedback_msg));
+ dec += 4*1024;
+ memcpy(dec, uvd_it_scaling_table, sizeof(uvd_it_scaling_table));
+
+ dec += 4*1024;
+ memcpy(dec, uvd_bitstream, sizeof(uvd_bitstream));
+
+ dec += ALIGN(sizeof(uvd_bitstream), 4*1024);
+
+ dec += ALIGN(dpb_size, 4*1024);
+
+ msg_addr = dec_buf.addr;
+ fb_addr = msg_addr + 4*1024;
+ it_addr = fb_addr + 4*1024;
+ bs_addr = it_addr + 4*1024;
+ dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
+ ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
+ dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
+
+ len = 0;
+ vcn_dec_cmd(msg_addr, 0x0, &len);
+ vcn_dec_cmd(dpb_addr, 0x1, &len);
+ vcn_dec_cmd(dt_addr, 0x2, &len);
+ vcn_dec_cmd(fb_addr, 0x3, &len);
+ vcn_dec_cmd(bs_addr, 0x100, &len);
+ vcn_dec_cmd(it_addr, 0x204, &len);
+ vcn_dec_cmd(ctx_addr, 0x206, &len);
+
+ if (vcn_dec_sw_ring == false) {
+ ib_cpu[len++] = reg[vcn_reg_index].cntl;
+ ib_cpu[len++] = 0x1;
+ for (; len % 16; ) {
+ ib_cpu[len++] = reg[vcn_reg_index].nop;
+ ib_cpu[len++] = 0;
+ }
+ }
+
+ if (vcn_unified_ring) {
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+ ip = AMDGPU_HW_IP_VCN_ENC;
+ } else
+ ip = AMDGPU_HW_IP_VCN_DEC;
+
+ r = submit(len, ip);
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (i = 0, sum = 0; i < dt_size; ++i)
+ sum += dec[i];
+
+ CU_ASSERT_EQUAL(sum, SUM_DECODE);
+
+ free_resource(&dec_buf);
+}
+
+static void amdgpu_cs_vcn_dec_destroy(void)
+{
+ struct amdgpu_vcn_bo msg_buf;
+ unsigned ip;
+ int len, r;
+
+ num_resources = 0;
+ alloc_resource(&msg_buf, 1024, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = msg_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ memset(msg_buf.ptr, 0, 1024);
+ memcpy(msg_buf.ptr, vcn_dec_destroy_msg, sizeof(vcn_dec_destroy_msg));
+
+ len = 0;
+ if (vcn_dec_sw_ring == true)
+ vcn_dec_cmd(msg_buf.addr, 0, &len);
+ else {
+ ib_cpu[len++] = reg[vcn_reg_index].data0;
+ ib_cpu[len++] = msg_buf.addr;
+ ib_cpu[len++] = reg[vcn_reg_index].data1;
+ ib_cpu[len++] = msg_buf.addr >> 32;
+ ib_cpu[len++] = reg[vcn_reg_index].cmd;
+ ib_cpu[len++] = 0;
+ for (; len % 16; ) {
+ ib_cpu[len++] = reg[vcn_reg_index].nop;
+ ib_cpu[len++] = 0;
+ }
+ }
+
+ if (vcn_unified_ring) {
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+ ip = AMDGPU_HW_IP_VCN_ENC;
+ } else
+ ip = AMDGPU_HW_IP_VCN_DEC;
+
+ r = submit(len, ip);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&msg_buf);
+}
+
+static void amdgpu_cs_vcn_enc_create(void)
+{
+ int len, r;
+ uint32_t *p_task_size = NULL;
+ uint32_t task_offset = 0, st_offset;
+ uint32_t *st_size = NULL;
+ unsigned width = 160, height = 128, buf_size;
+ uint32_t fw_maj = 1, fw_min = 9;
+
+ if (vcn_ip_version_major == 2) {
+ fw_maj = 1;
+ fw_min = 1;
+ } else if (vcn_ip_version_major == 3) {
+ fw_maj = 1;
+ fw_min = 0;
+ }
+
+ gWidth = width;
+ gHeight = height;
+ buf_size = ALIGN(width, 256) * ALIGN(height, 32) * 3 / 2;
+ enc_task_id = 1;
+
+ num_resources = 0;
+ alloc_resource(&enc_buf, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT);
+ alloc_resource(&cpb_buf, buf_size * 2, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc_buf.handle;
+ resources[num_resources++] = cpb_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+ r = amdgpu_bo_cpu_map(enc_buf.handle, (void**)&enc_buf.ptr);
+ memset(enc_buf.ptr, 0, 128 * 1024);
+ r = amdgpu_bo_cpu_unmap(enc_buf.handle);
+
+ r = amdgpu_bo_cpu_map(cpb_buf.handle, (void**)&enc_buf.ptr);
+ memset(enc_buf.ptr, 0, buf_size * 2);
+ r = amdgpu_bo_cpu_unmap(cpb_buf.handle);
+
+ len = 0;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_head(ib_cpu, &len, true);
+
+ /* session info */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000001; /* RENCODE_IB_PARAM_SESSION_INFO */
+ ib_cpu[len++] = ((fw_maj << 16) | (fw_min << 0));
+ ib_cpu[len++] = enc_buf.addr >> 32;
+ ib_cpu[len++] = enc_buf.addr;
+ ib_cpu[len++] = 1; /* RENCODE_ENGINE_TYPE_ENCODE; */
+ *st_size = (len - st_offset) * 4;
+
+ /* task info */
+ task_offset = len;
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000002; /* RENCODE_IB_PARAM_TASK_INFO */
+ p_task_size = &ib_cpu[len++];
+ ib_cpu[len++] = enc_task_id++; /* task_id */
+ ib_cpu[len++] = 0; /* feedback */
+ *st_size = (len - st_offset) * 4;
+
+ /* op init */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x01000001; /* RENCODE_IB_OP_INITIALIZE */
+ *st_size = (len - st_offset) * 4;
+
+ /* session_init */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000003; /* RENCODE_IB_PARAM_SESSION_INIT */
+ ib_cpu[len++] = 1; /* RENCODE_ENCODE_STANDARD_H264 */
+ ib_cpu[len++] = width;
+ ib_cpu[len++] = height;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 0; /* pre encode mode */
+ ib_cpu[len++] = 0; /* chroma enabled : false */
+ *st_size = (len - st_offset) * 4;
+
+ /* slice control */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00200001; /* RENCODE_H264_IB_PARAM_SLICE_CONTROL */
+ ib_cpu[len++] = 0; /* RENCODE_H264_SLICE_CONTROL_MODE_FIXED_MBS */
+ ib_cpu[len++] = ALIGN(width, 16) / 16 * ALIGN(height, 16) / 16;
+ *st_size = (len - st_offset) * 4;
+
+ /* enc spec misc */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00200002; /* RENCODE_H264_IB_PARAM_SPEC_MISC */
+ ib_cpu[len++] = 0; /* constrained intra pred flag */
+ ib_cpu[len++] = 0; /* cabac enable */
+ ib_cpu[len++] = 0; /* cabac init idc */
+ ib_cpu[len++] = 1; /* half pel enabled */
+ ib_cpu[len++] = 1; /* quarter pel enabled */
+ ib_cpu[len++] = 100; /* BASELINE profile */
+ ib_cpu[len++] = 11; /* level */
+ if (vcn_ip_version_major == 3) {
+ ib_cpu[len++] = 0; /* b_picture_enabled */
+ ib_cpu[len++] = 0; /* weighted_bipred_idc */
+ }
+ *st_size = (len - st_offset) * 4;
+
+ /* deblocking filter */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00200004; /* RENCODE_H264_IB_PARAM_DEBLOCKING_FILTER */
+ ib_cpu[len++] = 0; /* disable deblocking filter idc */
+ ib_cpu[len++] = 0; /* alpha c0 offset */
+ ib_cpu[len++] = 0; /* tc offset */
+ ib_cpu[len++] = 0; /* cb offset */
+ ib_cpu[len++] = 0; /* cr offset */
+ *st_size = (len - st_offset) * 4;
+
+ /* layer control */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000004; /* RENCODE_IB_PARAM_LAYER_CONTROL */
+ ib_cpu[len++] = 1; /* max temporal layer */
+ ib_cpu[len++] = 1; /* no of temporal layer */
+ *st_size = (len - st_offset) * 4;
+
+ /* rc_session init */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000006; /* RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT */
+ ib_cpu[len++] = 0; /* rate control */
+ ib_cpu[len++] = 48; /* vbv buffer level */
+ *st_size = (len - st_offset) * 4;
+
+ /* quality params */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000009; /* RENCODE_IB_PARAM_QUALITY_PARAMS */
+ ib_cpu[len++] = 0; /* vbaq mode */
+ ib_cpu[len++] = 0; /* scene change sensitivity */
+ ib_cpu[len++] = 0; /* scene change min idr interval */
+ ib_cpu[len++] = 0;
+ if (vcn_ip_version_major == 3)
+ ib_cpu[len++] = 0;
+ *st_size = (len - st_offset) * 4;
+
+ /* layer select */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000005; /* RENCODE_IB_PARAM_LAYER_SELECT */
+ ib_cpu[len++] = 0; /* temporal layer */
+ *st_size = (len - st_offset) * 4;
+
+ /* rc layer init */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000007; /* RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT */
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 25;
+ ib_cpu[len++] = 1;
+ ib_cpu[len++] = 0x01312d00;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 0;
+ *st_size = (len - st_offset) * 4;
+
+ /* layer select */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000005; /* RENCODE_IB_PARAM_LAYER_SELECT */
+ ib_cpu[len++] = 0; /* temporal layer */
+ *st_size = (len - st_offset) * 4;
+
+ /* rc per pic */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000008; /* RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE */
+ ib_cpu[len++] = 20;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 51;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 1;
+ ib_cpu[len++] = 0;
+ ib_cpu[len++] = 1;
+ *st_size = (len - st_offset) * 4;
+
+ /* op init rc */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x01000004; /* RENCODE_IB_OP_INIT_RC */
+ *st_size = (len - st_offset) * 4;
+
+ /* op init rc vbv */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x01000005; /* RENCODE_IB_OP_INIT_RC_VBV_BUFFER_LEVEL */
+ *st_size = (len - st_offset) * 4;
+
+ *p_task_size = (len - task_offset) * 4;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+
+ r = submit(len, AMDGPU_HW_IP_VCN_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static int32_t h264_se (bufferInfo * bufInfo)
+{
+ uint32_t ret;
+
+ ret = bs_read_ue (bufInfo);
+ if ((ret & 0x1) == 0) {
+ ret >>= 1;
+ int32_t temp = 0 - ret;
+ return temp;
+ }
+
+ return (ret + 1) >> 1;
+}
+
+static void h264_check_0s (bufferInfo * bufInfo, int count)
+{
+ uint32_t val;
+
+ val = bs_read_u (bufInfo, count);
+ if (val != 0) {
+ printf ("field error - %d bits should be 0 is %x\n", count, val);
+ }
+}
+
+static inline int bs_eof(bufferInfo * bufinfo)
+{
+ if (bufinfo->decBuffer >= bufinfo->end)
+ return 1;
+ else
+ return 0;
+}
+
+static inline uint32_t bs_read_u1(bufferInfo *bufinfo)
+{
+ uint32_t r = 0;
+ uint32_t temp = 0;
+
+ bufinfo->numOfBitsInBuffer--;
+ if (! bs_eof(bufinfo)) {
+ temp = (((bufinfo->decData)) >> bufinfo->numOfBitsInBuffer);
+ r = temp & 0x01;
+ }
+
+ if (bufinfo->numOfBitsInBuffer == 0) {
+ bufinfo->decBuffer++;
+ bufinfo->decData = *bufinfo->decBuffer;
+ bufinfo->numOfBitsInBuffer = 8;
+ }
+
+ return r;
+}
+
+static inline uint32_t bs_read_u(bufferInfo* bufinfo, int n)
+{
+ uint32_t r = 0;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ r |= ( bs_read_u1(bufinfo) << ( n - i - 1 ) );
+ }
+
+ return r;
+}
+
+static inline uint32_t bs_read_ue(bufferInfo* bufinfo)
+{
+ int32_t r = 0;
+ int i = 0;
+
+ while( (bs_read_u1(bufinfo) == 0) && (i < 32) && (!bs_eof(bufinfo))) {
+ i++;
+ }
+ r = bs_read_u(bufinfo, i);
+ r += (1 << i) - 1;
+ return r;
+}
+
+static uint32_t remove_03 (uint8_t * bptr, uint32_t len)
+{
+ uint32_t nal_len = 0;
+ while (nal_len + 2 < len) {
+ if (bptr[0] == 0 && bptr[1] == 0 && bptr[2] == 3) {
+ bptr += 2;
+ nal_len += 2;
+ len--;
+ memmove (bptr, bptr + 1, len - nal_len);
+ } else {
+ bptr++;
+ nal_len++;
+ }
+ }
+ return len;
+}
+
+static void scaling_list (uint32_t ix, uint32_t sizeOfScalingList, bufferInfo * bufInfo)
+{
+ uint32_t lastScale = 8, nextScale = 8;
+ uint32_t jx;
+ int deltaScale;
+
+ for (jx = 0; jx < sizeOfScalingList; jx++) {
+ if (nextScale != 0) {
+ deltaScale = h264_se (bufInfo);
+ nextScale = (lastScale + deltaScale + 256) % 256;
+ }
+ if (nextScale == 0) {
+ lastScale = lastScale;
+ } else {
+ lastScale = nextScale;
+ }
+ }
+}
+
+static void h264_parse_sequence_parameter_set (h264_decode * dec, bufferInfo * bufInfo)
+{
+ uint32_t temp;
+
+ dec->profile = bs_read_u (bufInfo, 8);
+ bs_read_u (bufInfo, 1); /* constaint_set0_flag */
+ bs_read_u (bufInfo, 1); /* constaint_set1_flag */
+ bs_read_u (bufInfo, 1); /* constaint_set2_flag */
+ bs_read_u (bufInfo, 1); /* constaint_set3_flag */
+ bs_read_u (bufInfo, 1); /* constaint_set4_flag */
+ bs_read_u (bufInfo, 1); /* constaint_set5_flag */
+
+
+ h264_check_0s (bufInfo, 2);
+ dec->level_idc = bs_read_u (bufInfo, 8);
+ bs_read_ue (bufInfo); /* SPS id*/
+
+ if (dec->profile == 100 || dec->profile == 110 ||
+ dec->profile == 122 || dec->profile == 144) {
+ uint32_t chroma_format_idc = bs_read_ue (bufInfo);
+ if (chroma_format_idc == 3) {
+ bs_read_u (bufInfo, 1); /* residual_colour_transform_flag */
+ }
+ bs_read_ue (bufInfo); /* bit_depth_luma_minus8 */
+ bs_read_ue (bufInfo); /* bit_depth_chroma_minus8 */
+ bs_read_u (bufInfo, 1); /* qpprime_y_zero_transform_bypass_flag */
+ uint32_t seq_scaling_matrix_present_flag = bs_read_u (bufInfo, 1);
+
+ if (seq_scaling_matrix_present_flag) {
+ for (uint32_t ix = 0; ix < 8; ix++) {
+ temp = bs_read_u (bufInfo, 1);
+ if (temp) {
+ scaling_list (ix, ix < 6 ? 16 : 64, bufInfo);
+ }
+ }
+ }
+ }
+
+ bs_read_ue (bufInfo); /* log2_max_frame_num_minus4 */
+ uint32_t pic_order_cnt_type = bs_read_ue (bufInfo);
+
+ if (pic_order_cnt_type == 0) {
+ bs_read_ue (bufInfo); /* log2_max_pic_order_cnt_lsb_minus4 */
+ } else if (pic_order_cnt_type == 1) {
+ bs_read_u (bufInfo, 1); /* delta_pic_order_always_zero_flag */
+ h264_se (bufInfo); /* offset_for_non_ref_pic */
+ h264_se (bufInfo); /* offset_for_top_to_bottom_field */
+ temp = bs_read_ue (bufInfo);
+ for (uint32_t ix = 0; ix < temp; ix++) {
+ h264_se (bufInfo); /* offset_for_ref_frame[index] */
+ }
+ }
+ bs_read_ue (bufInfo); /* num_ref_frames */
+ bs_read_u (bufInfo, 1); /* gaps_in_frame_num_flag */
+ uint32_t PicWidthInMbs = bs_read_ue (bufInfo) + 1;
+
+ dec->pic_width = PicWidthInMbs * 16;
+ uint32_t PicHeightInMapUnits = bs_read_ue (bufInfo) + 1;
+
+ dec->pic_height = PicHeightInMapUnits * 16;
+ uint32_t frame_mbs_only_flag = bs_read_u (bufInfo, 1);
+ if (!frame_mbs_only_flag) {
+ bs_read_u (bufInfo, 1); /* mb_adaptive_frame_field_flag */
+ }
+ bs_read_u (bufInfo, 1); /* direct_8x8_inference_flag */
+ temp = bs_read_u (bufInfo, 1);
+ if (temp) {
+ bs_read_ue (bufInfo); /* frame_crop_left_offset */
+ bs_read_ue (bufInfo); /* frame_crop_right_offset */
+ bs_read_ue (bufInfo); /* frame_crop_top_offset */
+ bs_read_ue (bufInfo); /* frame_crop_bottom_offset */
+ }
+ temp = bs_read_u (bufInfo, 1); /* VUI Parameters */
+}
+
+static void h264_slice_header (h264_decode * dec, bufferInfo * bufInfo)
+{
+ uint32_t temp;
+
+ bs_read_ue (bufInfo); /* first_mb_in_slice */
+ temp = bs_read_ue (bufInfo);
+ dec->slice_type = ((temp > 5) ? (temp - 5) : temp);
+}
+
+static uint8_t h264_parse_nal (h264_decode * dec, bufferInfo * bufInfo)
+{
+ uint8_t type = 0;
+
+ h264_check_0s (bufInfo, 1);
+ dec->nal_ref_idc = bs_read_u (bufInfo, 2);
+ dec->nal_unit_type = type = bs_read_u (bufInfo, 5);
+ switch (type)
+ {
+ case H264_NAL_TYPE_NON_IDR_SLICE:
+ case H264_NAL_TYPE_IDR_SLICE:
+ h264_slice_header (dec, bufInfo);
+ break;
+ case H264_NAL_TYPE_SEQ_PARAM:
+ h264_parse_sequence_parameter_set (dec, bufInfo);
+ break;
+ case H264_NAL_TYPE_PIC_PARAM:
+ case H264_NAL_TYPE_SEI:
+ case H264_NAL_TYPE_ACCESS_UNIT:
+ case H264_NAL_TYPE_SEQ_EXTENSION:
+ /* NOP */
+ break;
+ default:
+ printf ("Nal type unknown %d \n ", type);
+ break;
+ }
+ return type;
+}
+
+static uint32_t h264_find_next_start_code (uint8_t * pBuf, uint32_t bufLen)
+{
+ uint32_t val;
+ uint32_t offset, startBytes;
+
+ offset = startBytes = 0;
+ if (pBuf[0] == 0 && pBuf[1] == 0 && pBuf[2] == 0 && pBuf[3] == 1) {
+ pBuf += 4;
+ offset = 4;
+ startBytes = 1;
+ } else if (pBuf[0] == 0 && pBuf[1] == 0 && pBuf[2] == 1) {
+ pBuf += 3;
+ offset = 3;
+ startBytes = 1;
+ }
+ val = 0xffffffff;
+ while (offset < bufLen - 3) {
+ val <<= 8;
+ val |= *pBuf++;
+ offset++;
+ if (val == H264_START_CODE)
+ return offset - 4;
+
+ if ((val & 0x00ffffff) == H264_START_CODE)
+ return offset - 3;
+ }
+ if (bufLen - offset <= 3 && startBytes == 0) {
+ startBytes = 0;
+ return 0;
+ }
+
+ return offset;
+}
+
+static int verify_checksum(uint8_t *buffer, uint32_t buffer_size)
+{
+ uint32_t buffer_pos = 0;
+ int done = 0;
+ h264_decode dec;
+
+ memset(&dec, 0, sizeof(h264_decode));
+ do {
+ uint32_t ret;
+
+ ret = h264_find_next_start_code (buffer + buffer_pos,
+ buffer_size - buffer_pos);
+ if (ret == 0) {
+ done = 1;
+ if (buffer_pos == 0) {
+ fprintf (stderr,
+ "couldn't find start code in buffer from 0\n");
+ }
+ } else {
+ /* have a complete NAL from buffer_pos to end */
+ if (ret > 3) {
+ uint32_t nal_len;
+ bufferInfo bufinfo;
+
+ nal_len = remove_03 (buffer + buffer_pos, ret);
+ bufinfo.decBuffer = buffer + buffer_pos + (buffer[buffer_pos + 2] == 1 ? 3 : 4);
+ bufinfo.decBufferSize = (nal_len - (buffer[buffer_pos + 2] == 1 ? 3 : 4)) * 8;
+ bufinfo.end = buffer + buffer_pos + nal_len;
+ bufinfo.numOfBitsInBuffer = 8;
+ bufinfo.decData = *bufinfo.decBuffer;
+ h264_parse_nal (&dec, &bufinfo);
+ }
+ buffer_pos += ret; /* buffer_pos points to next code */
+ }
+ } while (done == 0);
+
+ if ((dec.pic_width == gWidth) &&
+ (dec.pic_height == gHeight) &&
+ (dec.slice_type == gSliceType))
+ return 0;
+ else
+ return -1;
+}
+
+static void check_result(struct amdgpu_vcn_bo fb_buf, struct amdgpu_vcn_bo bs_buf, int frame_type)
+{
+ uint32_t *fb_ptr;
+ uint8_t *bs_ptr;
+ uint32_t size;
+ int r;
+/* uint64_t s[3] = {0, 1121279001727, 1059312481445}; */
+
+ r = amdgpu_bo_cpu_map(fb_buf.handle, (void **)&fb_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+ fb_ptr = (uint32_t*)fb_buf.ptr;
+ size = fb_ptr[6];
+ r = amdgpu_bo_cpu_unmap(fb_buf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_map(bs_buf.handle, (void **)&bs_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ bs_ptr = (uint8_t*)bs_buf.ptr;
+ r = verify_checksum(bs_ptr, size);
+ CU_ASSERT_EQUAL(r, 0);
+ r = amdgpu_bo_cpu_unmap(bs_buf.handle);
+
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_vcn_enc_encode_frame(int frame_type)
+{
+ struct amdgpu_vcn_bo bs_buf, fb_buf, vbv_buf;
+ int len, r, i;
+ unsigned width = 160, height = 128, buf_size;
+ uint32_t *p_task_size = NULL;
+ uint32_t task_offset = 0, st_offset;
+ uint32_t *st_size = NULL;
+ uint32_t fw_maj = 1, fw_min = 9;
+
+ if (vcn_ip_version_major == 2) {
+ fw_maj = 1;
+ fw_min = 1;
+ } else if (vcn_ip_version_major == 3) {
+ fw_maj = 1;
+ fw_min = 0;
+ }
+ gSliceType = frame_type;
+ buf_size = ALIGN(width, 256) * ALIGN(height, 32) * 3 / 2;
+
+ num_resources = 0;
+ alloc_resource(&bs_buf, 4096, AMDGPU_GEM_DOMAIN_GTT);
+ alloc_resource(&fb_buf, 4096, AMDGPU_GEM_DOMAIN_GTT);
+ alloc_resource(&vbv_buf, buf_size, AMDGPU_GEM_DOMAIN_GTT);
+ resources[num_resources++] = enc_buf.handle;
+ resources[num_resources++] = cpb_buf.handle;
+ resources[num_resources++] = bs_buf.handle;
+ resources[num_resources++] = fb_buf.handle;
+ resources[num_resources++] = vbv_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+
+ r = amdgpu_bo_cpu_map(bs_buf.handle, (void**)&bs_buf.ptr);
+ memset(bs_buf.ptr, 0, 4096);
+ r = amdgpu_bo_cpu_unmap(bs_buf.handle);
+
+ r = amdgpu_bo_cpu_map(fb_buf.handle, (void**)&fb_buf.ptr);
+ memset(fb_buf.ptr, 0, 4096);
+ r = amdgpu_bo_cpu_unmap(fb_buf.handle);
+
+ r = amdgpu_bo_cpu_map(vbv_buf.handle, (void **)&vbv_buf.ptr);
+ CU_ASSERT_EQUAL(r, 0);
+
+ for (int i = 0; i < ALIGN(height, 32) * 3 / 2; i++)
+ memcpy(vbv_buf.ptr + i * ALIGN(width, 256), frame + i * width, width);
+
+ r = amdgpu_bo_cpu_unmap(vbv_buf.handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ len = 0;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_head(ib_cpu, &len, true);
+
+ /* session info */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000001; /* RENCODE_IB_PARAM_SESSION_INFO */
+ ib_cpu[len++] = ((fw_maj << 16) | (fw_min << 0));
+ ib_cpu[len++] = enc_buf.addr >> 32;
+ ib_cpu[len++] = enc_buf.addr;
+ ib_cpu[len++] = 1; /* RENCODE_ENGINE_TYPE_ENCODE */;
+ *st_size = (len - st_offset) * 4;
+
+ /* task info */
+ task_offset = len;
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000002; /* RENCODE_IB_PARAM_TASK_INFO */
+ p_task_size = &ib_cpu[len++];
+ ib_cpu[len++] = enc_task_id++; /* task_id */
+ ib_cpu[len++] = 1; /* feedback */
+ *st_size = (len - st_offset) * 4;
+
+ if (frame_type == 2) {
+ /* sps */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x00000020; /* RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU vcn 1 */
+ else
+ ib_cpu[len++] = 0x0000000a; /* RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU vcn 2,3 */
+ ib_cpu[len++] = 0x00000002; /* RENCODE_DIRECT_OUTPUT_NALU_TYPE_SPS */
+ ib_cpu[len++] = 0x00000011; /* sps len */
+ ib_cpu[len++] = 0x00000001; /* start code */
+ ib_cpu[len++] = 0x6764440b;
+ ib_cpu[len++] = 0xac54c284;
+ ib_cpu[len++] = 0x68078442;
+ ib_cpu[len++] = 0x37000000;
+ *st_size = (len - st_offset) * 4;
+
+ /* pps */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x00000020; /* RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU vcn 1*/
+ else
+ ib_cpu[len++] = 0x0000000a; /* RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU vcn 2,3*/
+ ib_cpu[len++] = 0x00000003; /* RENCODE_DIRECT_OUTPUT_NALU_TYPE_PPS */
+ ib_cpu[len++] = 0x00000008; /* pps len */
+ ib_cpu[len++] = 0x00000001; /* start code */
+ ib_cpu[len++] = 0x68ce3c80;
+ *st_size = (len - st_offset) * 4;
+ }
+
+ /* slice header */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x0000000a; /* RENCODE_IB_PARAM_SLICE_HEADER vcn 1 */
+ else
+ ib_cpu[len++] = 0x0000000b; /* RENCODE_IB_PARAM_SLICE_HEADER vcn 2,3 */
+ if (frame_type == 2) {
+ ib_cpu[len++] = 0x65000000;
+ ib_cpu[len++] = 0x11040000;
+ } else {
+ ib_cpu[len++] = 0x41000000;
+ ib_cpu[len++] = 0x34210000;
+ }
+ ib_cpu[len++] = 0xe0000000;
+ for(i = 0; i < 13; i++)
+ ib_cpu[len++] = 0x00000000;
+
+ ib_cpu[len++] = 0x00000001;
+ ib_cpu[len++] = 0x00000008;
+ ib_cpu[len++] = 0x00020000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000001;
+ ib_cpu[len++] = 0x00000015;
+ ib_cpu[len++] = 0x00020001;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000001;
+ ib_cpu[len++] = 0x00000003;
+ for(i = 0; i < 22; i++)
+ ib_cpu[len++] = 0x00000000;
+
+ *st_size = (len - st_offset) * 4;
+
+ /* encode params */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x0000000b; /* RENCODE_IB_PARAM_ENCODE_PARAMS vcn 1*/
+ else
+ ib_cpu[len++] = 0x0000000f; /* RENCODE_IB_PARAM_ENCODE_PARAMS vcn 2,3*/
+ ib_cpu[len++] = frame_type;
+ ib_cpu[len++] = 0x0001f000;
+ ib_cpu[len++] = vbv_buf.addr >> 32;
+ ib_cpu[len++] = vbv_buf.addr;
+ ib_cpu[len++] = (vbv_buf.addr + ALIGN(width, 256) * ALIGN(height, 32)) >> 32;
+ ib_cpu[len++] = vbv_buf.addr + ALIGN(width, 256) * ALIGN(height, 32);
+ ib_cpu[len++] = 0x00000100;
+ ib_cpu[len++] = 0x00000080;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0xffffffff;
+ ib_cpu[len++] = 0x00000000;
+ *st_size = (len - st_offset) * 4;
+
+ /* encode params h264 */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00200003; /* RENCODE_H264_IB_PARAM_ENCODE_PARAMS */
+ if (vcn_ip_version_major != 3) {
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0xffffffff;
+ } else {
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0xffffffff;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0xffffffff;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ }
+ *st_size = (len - st_offset) * 4;
+
+ /* encode context */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x0000000d; /* ENCODE_CONTEXT_BUFFER vcn 1 */
+ else
+ ib_cpu[len++] = 0x00000011; /* ENCODE_CONTEXT_BUFFER vcn 2,3 */
+ ib_cpu[len++] = cpb_buf.addr >> 32;
+ ib_cpu[len++] = cpb_buf.addr;
+ ib_cpu[len++] = 0x00000000; /* swizzle mode */
+ ib_cpu[len++] = 0x00000100; /* luma pitch */
+ ib_cpu[len++] = 0x00000100; /* chroma pitch */
+ ib_cpu[len++] = 0x00000003; /* no reconstructed picture */
+ ib_cpu[len++] = 0x00000000; /* reconstructed pic 1 luma offset */
+ ib_cpu[len++] = ALIGN(width, 256) * ALIGN(height, 32); /* pic1 chroma offset */
+ ib_cpu[len++] = ALIGN(width, 256) * ALIGN(height, 32) * 3 / 2; /* pic2 luma offset */
+ ib_cpu[len++] = ALIGN(width, 256) * ALIGN(height, 32) * 5 / 2; /* pic2 chroma offset */
+
+ for (int i = 0; i < 136; i++)
+ ib_cpu[len++] = 0x00000000;
+ *st_size = (len - st_offset) * 4;
+
+ /* bitstream buffer */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x0000000e; /* VIDEO_BITSTREAM_BUFFER vcn 1 */
+ else
+ ib_cpu[len++] = 0x00000012; /* VIDEO_BITSTREAM_BUFFER vcn 2,3 */
+ ib_cpu[len++] = 0x00000000; /* mode */
+ ib_cpu[len++] = bs_buf.addr >> 32;
+ ib_cpu[len++] = bs_buf.addr;
+ ib_cpu[len++] = 0x0001f000;
+ ib_cpu[len++] = 0x00000000;
+ *st_size = (len - st_offset) * 4;
+
+ /* feedback */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x00000010; /* FEEDBACK_BUFFER vcn 1 */
+ else
+ ib_cpu[len++] = 0x00000015; /* FEEDBACK_BUFFER vcn 2,3 */
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = fb_buf.addr >> 32;
+ ib_cpu[len++] = fb_buf.addr;
+ ib_cpu[len++] = 0x00000010;
+ ib_cpu[len++] = 0x00000028;
+ *st_size = (len - st_offset) * 4;
+
+ /* intra refresh */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ if(vcn_ip_version_major == 1)
+ ib_cpu[len++] = 0x0000000c; /* INTRA_REFRESH vcn 1 */
+ else
+ ib_cpu[len++] = 0x00000010; /* INTRA_REFRESH vcn 2,3 */
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ *st_size = (len - st_offset) * 4;
+
+ if(vcn_ip_version_major != 1) {
+ /* Input Format */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ ib_cpu[len++] = 0x0000000c;
+ ib_cpu[len++] = 0x00000000; /* RENCODE_COLOR_VOLUME_G22_BT709 */
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000; /* RENCODE_COLOR_BIT_DEPTH_8_BIT */
+ ib_cpu[len++] = 0x00000000; /* RENCODE_COLOR_PACKING_FORMAT_NV12 */
+ *st_size = (len - st_offset) * 4;
+
+ /* Output Format */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ ib_cpu[len++] = 0x0000000d;
+ ib_cpu[len++] = 0x00000000; /* RENCODE_COLOR_VOLUME_G22_BT709 */
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000;
+ ib_cpu[len++] = 0x00000000; /* RENCODE_COLOR_BIT_DEPTH_8_BIT */
+ *st_size = (len - st_offset) * 4;
+ }
+ /* op_speed */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ ib_cpu[len++] = 0x01000006; /* SPEED_ENCODING_MODE */
+ *st_size = (len - st_offset) * 4;
+
+ /* op_enc */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ ib_cpu[len++] = 0x01000003;
+ *st_size = (len - st_offset) * 4;
+
+ *p_task_size = (len - task_offset) * 4;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+
+ r = submit(len, AMDGPU_HW_IP_VCN_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+
+ /* check result */
+ check_result(fb_buf, bs_buf, frame_type);
+
+ free_resource(&fb_buf);
+ free_resource(&bs_buf);
+ free_resource(&vbv_buf);
+}
+
+static void amdgpu_cs_vcn_enc_encode(void)
+{
+ amdgpu_cs_vcn_enc_encode_frame(2); /* IDR frame */
+}
+
+static void amdgpu_cs_vcn_enc_destroy(void)
+{
+ int len = 0, r;
+ uint32_t *p_task_size = NULL;
+ uint32_t task_offset = 0, st_offset;
+ uint32_t *st_size = NULL;
+ uint32_t fw_maj = 1, fw_min = 9;
+
+ if (vcn_ip_version_major == 2) {
+ fw_maj = 1;
+ fw_min = 1;
+ } else if (vcn_ip_version_major == 3) {
+ fw_maj = 1;
+ fw_min = 0;
+ }
+
+ num_resources = 0;
+/* alloc_resource(&enc_buf, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT); */
+ resources[num_resources++] = enc_buf.handle;
+ resources[num_resources++] = ib_handle;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_head(ib_cpu, &len, true);
+
+ /* session info */
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000001; /* RENCODE_IB_PARAM_SESSION_INFO */
+ ib_cpu[len++] = ((fw_maj << 16) | (fw_min << 0));
+ ib_cpu[len++] = enc_buf.addr >> 32;
+ ib_cpu[len++] = enc_buf.addr;
+ ib_cpu[len++] = 1; /* RENCODE_ENGINE_TYPE_ENCODE; */
+ *st_size = (len - st_offset) * 4;
+
+ /* task info */
+ task_offset = len;
+ st_offset = len;
+ st_size = &ib_cpu[len++]; /* size */
+ ib_cpu[len++] = 0x00000002; /* RENCODE_IB_PARAM_TASK_INFO */
+ p_task_size = &ib_cpu[len++];
+ ib_cpu[len++] = enc_task_id++; /* task_id */
+ ib_cpu[len++] = 0; /* feedback */
+ *st_size = (len - st_offset) * 4;
+
+ /* op close */
+ st_offset = len;
+ st_size = &ib_cpu[len++];
+ ib_cpu[len++] = 0x01000002; /* RENCODE_IB_OP_CLOSE_SESSION */
+ *st_size = (len - st_offset) * 4;
+
+ *p_task_size = (len - task_offset) * 4;
+
+ if (vcn_unified_ring)
+ amdgpu_cs_sq_ib_tail(ib_cpu + len);
+
+ r = submit(len, AMDGPU_HW_IP_VCN_ENC);
+ CU_ASSERT_EQUAL(r, 0);
+
+ free_resource(&cpb_buf);
+ free_resource(&enc_buf);
+}
diff --git a/tests/amdgpu/vm_tests.c b/tests/amdgpu/vm_tests.c
new file mode 100644
index 0000000..b94999c
--- /dev/null
+++ b/tests/amdgpu/vm_tests.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+*/
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+static uint32_t chip_id;
+static uint32_t chip_rev;
+
+static void amdgpu_vmid_reserve_test(void);
+static void amdgpu_vm_unaligned_map(void);
+static void amdgpu_vm_mapping_test(void);
+
+CU_BOOL suite_vm_tests_enable(void)
+{
+ CU_BOOL enable = CU_TRUE;
+
+ if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle))
+ return CU_FALSE;
+
+ if (device_handle->info.family_id == AMDGPU_FAMILY_SI) {
+ printf("\n\nCurrently hangs the CP on this ASIC, VM suite disabled\n");
+ enable = CU_FALSE;
+ }
+
+ if (amdgpu_device_deinitialize(device_handle))
+ return CU_FALSE;
+
+ return enable;
+}
+
+int suite_vm_tests_init(void)
+{
+ int r;
+
+ r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+ &minor_version, &device_handle);
+
+ if (r) {
+ if ((r == -EACCES) && (errno == EACCES))
+ printf("\n\nError:%s. "
+ "Hint:Try to run this test program as root.",
+ strerror(errno));
+ return CUE_SINIT_FAILED;
+ }
+
+ return CUE_SUCCESS;
+}
+
+int suite_vm_tests_clean(void)
+{
+ int r = amdgpu_device_deinitialize(device_handle);
+
+ if (r == 0)
+ return CUE_SUCCESS;
+ else
+ return CUE_SCLEAN_FAILED;
+}
+
+
+CU_TestInfo vm_tests[] = {
+ { "resere vmid test", amdgpu_vmid_reserve_test },
+ { "unaligned map", amdgpu_vm_unaligned_map },
+ { "vm mapping test", amdgpu_vm_mapping_test },
+ CU_TEST_INFO_NULL,
+};
+
+static void amdgpu_vmid_reserve_test(void)
+{
+ amdgpu_context_handle context_handle;
+ amdgpu_bo_handle ib_result_handle;
+ void *ib_result_cpu;
+ uint64_t ib_result_mc_address;
+ struct amdgpu_cs_request ibs_request;
+ struct amdgpu_cs_ib_info ib_info;
+ struct amdgpu_cs_fence fence_status;
+ uint32_t expired, flags;
+ int i, r;
+ amdgpu_bo_list_handle bo_list;
+ amdgpu_va_handle va_handle;
+ static uint32_t *ptr;
+ struct amdgpu_gpu_info gpu_info = {0};
+ unsigned gc_ip_type;
+
+ r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ family_id = device_handle->info.family_id;
+ chip_id = device_handle->info.chip_external_rev;
+ chip_rev = device_handle->info.chip_rev;
+
+ gc_ip_type = (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) ?
+ AMDGPU_HW_IP_COMPUTE : AMDGPU_HW_IP_GFX;
+
+ r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ flags = 0;
+ r = amdgpu_vm_reserve_vmid(device_handle, flags);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+ r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+ AMDGPU_GEM_DOMAIN_GTT, 0,
+ &ib_result_handle, &ib_result_cpu,
+ &ib_result_mc_address, &va_handle);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+ &bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ ptr = ib_result_cpu;
+
+ for (i = 0; i < 16; ++i)
+ ptr[i] = 0xffff1000;
+
+ memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+ ib_info.ib_mc_address = ib_result_mc_address;
+ ib_info.size = 16;
+
+ memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+ ibs_request.ip_type = gc_ip_type;
+ ibs_request.ring = 0;
+ ibs_request.number_of_ibs = 1;
+ ibs_request.ibs = &ib_info;
+ ibs_request.resources = bo_list;
+ ibs_request.fence_info.handle = NULL;
+
+ r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+ memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+ fence_status.context = context_handle;
+ fence_status.ip_type = gc_ip_type;
+ fence_status.ip_instance = 0;
+ fence_status.ring = 0;
+ fence_status.fence = ibs_request.seq_no;
+
+ r = amdgpu_cs_query_fence_status(&fence_status,
+ AMDGPU_TIMEOUT_INFINITE,0, &expired);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_list_destroy(bo_list);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+ ib_result_mc_address, 4096);
+ CU_ASSERT_EQUAL(r, 0);
+
+ flags = 0;
+ r = amdgpu_vm_unreserve_vmid(device_handle, flags);
+ CU_ASSERT_EQUAL(r, 0);
+
+
+ r = amdgpu_cs_ctx_free(context_handle);
+ CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_vm_unaligned_map(void)
+{
+ const uint64_t map_size = (4ULL << 30) - (2 << 12);
+ struct amdgpu_bo_alloc_request request = {};
+ amdgpu_bo_handle buf_handle;
+ amdgpu_va_handle handle;
+ uint64_t vmc_addr;
+ int r;
+
+ request.alloc_size = 4ULL << 30;
+ request.phys_alignment = 4096;
+ request.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM;
+ request.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+
+ r = amdgpu_bo_alloc(device_handle, &request, &buf_handle);
+ /* Don't let the test fail if the device doesn't have enough VRAM */
+ if (r)
+ return;
+
+ r = amdgpu_va_range_alloc(device_handle, amdgpu_gpu_va_range_general,
+ 4ULL << 30, 1ULL << 30, 0, &vmc_addr,
+ &handle, 0);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ goto error_va_alloc;
+
+ vmc_addr += 1 << 12;
+
+ r = amdgpu_bo_va_op(buf_handle, 0, map_size, vmc_addr, 0,
+ AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ if (r)
+ goto error_va_alloc;
+
+ amdgpu_bo_va_op(buf_handle, 0, map_size, vmc_addr, 0,
+ AMDGPU_VA_OP_UNMAP);
+
+error_va_alloc:
+ amdgpu_bo_free(buf_handle);
+}
+
+static void amdgpu_vm_mapping_test(void)
+{
+ struct amdgpu_bo_alloc_request req = {0};
+ struct drm_amdgpu_info_device dev_info;
+ const uint64_t size = 4096;
+ amdgpu_bo_handle buf;
+ uint64_t addr;
+ int r;
+
+ req.alloc_size = size;
+ req.phys_alignment = 0;
+ req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
+ req.flags = 0;
+
+ r = amdgpu_bo_alloc(device_handle, &req, &buf);
+ CU_ASSERT_EQUAL(r, 0);
+
+ r = amdgpu_query_info(device_handle, AMDGPU_INFO_DEV_INFO,
+ sizeof(dev_info), &dev_info);
+ CU_ASSERT_EQUAL(r, 0);
+
+ addr = dev_info.virtual_address_offset;
+ r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ addr = dev_info.virtual_address_max - size;
+ r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ if (dev_info.high_va_offset) {
+ addr = dev_info.high_va_offset;
+ r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+
+ addr = dev_info.high_va_max - size;
+ r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP);
+ CU_ASSERT_EQUAL(r, 0);
+ }
+
+ amdgpu_bo_free(buf);
+}
diff --git a/tests/drmdevice.c b/tests/drmdevice.c
new file mode 100644
index 0000000..b4b62d9
--- /dev/null
+++ b/tests/drmdevice.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015 Emil Velikov <emil.l.velikov@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xf86drm.h>
+
+
+static void
+print_device_info(drmDevicePtr device, int i, bool print_revision)
+{
+ printf("device[%i]\n", i);
+ printf("+-> available_nodes %#04x\n", device->available_nodes);
+ printf("+-> nodes\n");
+ for (int j = 0; j < DRM_NODE_MAX; j++)
+ if (device->available_nodes & 1 << j)
+ printf("| +-> nodes[%d] %s\n", j, device->nodes[j]);
+
+ printf("+-> bustype %04x\n", device->bustype);
+ if (device->bustype == DRM_BUS_PCI) {
+ printf("| +-> pci\n");
+ printf("| +-> domain %04x\n",device->businfo.pci->domain);
+ printf("| +-> bus %02x\n", device->businfo.pci->bus);
+ printf("| +-> dev %02x\n", device->businfo.pci->dev);
+ printf("| +-> func %1u\n", device->businfo.pci->func);
+
+ printf("+-> deviceinfo\n");
+ printf(" +-> pci\n");
+ printf(" +-> vendor_id %04x\n", device->deviceinfo.pci->vendor_id);
+ printf(" +-> device_id %04x\n", device->deviceinfo.pci->device_id);
+ printf(" +-> subvendor_id %04x\n", device->deviceinfo.pci->subvendor_id);
+ printf(" +-> subdevice_id %04x\n", device->deviceinfo.pci->subdevice_id);
+ if (print_revision)
+ printf(" +-> revision_id %02x\n", device->deviceinfo.pci->revision_id);
+ else
+ printf(" +-> revision_id IGNORED\n");
+
+ } else if (device->bustype == DRM_BUS_USB) {
+ printf("| +-> usb\n");
+ printf("| +-> bus %03u\n", device->businfo.usb->bus);
+ printf("| +-> dev %03u\n", device->businfo.usb->dev);
+
+ printf("+-> deviceinfo\n");
+ printf(" +-> usb\n");
+ printf(" +-> vendor %04x\n", device->deviceinfo.usb->vendor);
+ printf(" +-> product %04x\n", device->deviceinfo.usb->product);
+ } else if (device->bustype == DRM_BUS_PLATFORM) {
+ char **compatible = device->deviceinfo.platform->compatible;
+
+ printf("| +-> platform\n");
+ printf("| +-> fullname\t%s\n", device->businfo.platform->fullname);
+
+ printf("+-> deviceinfo\n");
+ printf(" +-> platform\n");
+ printf(" +-> compatible\n");
+
+ while (*compatible) {
+ printf(" %s\n", *compatible);
+ compatible++;
+ }
+ } else if (device->bustype == DRM_BUS_HOST1X) {
+ char **compatible = device->deviceinfo.host1x->compatible;
+
+ printf("| +-> host1x\n");
+ printf("| +-> fullname\t%s\n", device->businfo.host1x->fullname);
+
+ printf("+-> deviceinfo\n");
+ printf(" +-> host1x\n");
+ printf(" +-> compatible\n");
+
+ while (*compatible) {
+ printf(" %s\n", *compatible);
+ compatible++;
+ }
+ } else {
+ printf("Unknown/unhandled bustype\n");
+ }
+ printf("\n");
+}
+
+int
+main(void)
+{
+ drmDevicePtr *devices;
+ drmDevicePtr device;
+ int fd, ret, max_devices;
+
+ printf("--- Checking the number of DRM device available ---\n");
+ max_devices = drmGetDevices2(0, NULL, 0);
+
+ if (max_devices <= 0) {
+ printf("drmGetDevices2() has not found any devices (errno=%d)\n",
+ -max_devices);
+ return 77;
+ }
+ printf("--- Devices reported %d ---\n", max_devices);
+
+
+ devices = calloc(max_devices, sizeof(drmDevicePtr));
+ if (devices == NULL) {
+ printf("Failed to allocate memory for the drmDevicePtr array\n");
+ return -1;
+ }
+
+ printf("--- Retrieving devices information (PCI device revision is ignored) ---\n");
+ ret = drmGetDevices2(0, devices, max_devices);
+ if (ret < 0) {
+ printf("drmGetDevices2() returned an error %d\n", ret);
+ free(devices);
+ return -1;
+ }
+
+ for (int i = 0; i < ret; i++) {
+ print_device_info(devices[i], i, false);
+
+ for (int j = 0; j < DRM_NODE_MAX; j++) {
+ if (devices[i]->available_nodes & 1 << j) {
+ printf("--- Opening device node %s ---\n", devices[i]->nodes[j]);
+ fd = open(devices[i]->nodes[j], O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Failed - %s (%d)\n", strerror(errno), errno);
+ continue;
+ }
+
+ printf("--- Retrieving device info, for node %s ---\n", devices[i]->nodes[j]);
+ if (drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, &device) == 0) {
+ print_device_info(device, i, true);
+ drmFreeDevice(&device);
+ }
+ close(fd);
+ }
+ }
+ }
+
+ drmFreeDevices(devices, ret);
+ free(devices);
+ return 0;
+}
diff --git a/tests/drmsl.c b/tests/drmsl.c
new file mode 100644
index 0000000..d1b59a8
--- /dev/null
+++ b/tests/drmsl.c
@@ -0,0 +1,184 @@
+/* drmsl.c -- Skip list test
+ * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward skip list implementation.n
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * REFERENCES
+ *
+ * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to
+ * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "xf86drm.h"
+
+static void print(void* list)
+{
+ unsigned long key;
+ void *value;
+
+ if (drmSLFirst(list, &key, &value)) {
+ do {
+ printf("key = %5lu, value = %p\n", key, value);
+ } while (drmSLNext(list, &key, &value));
+ }
+}
+
+static double do_time(int size, int iter)
+{
+ void *list;
+ int i, j;
+ unsigned long keys[1000000];
+ unsigned long previous;
+ unsigned long key;
+ void *value;
+ struct timeval start, stop;
+ double usec;
+ void *ranstate;
+
+ list = drmSLCreate();
+ ranstate = drmRandomCreate(12345);
+
+ for (i = 0; i < size; i++) {
+ keys[i] = drmRandom(ranstate);
+ drmSLInsert(list, keys[i], NULL);
+ }
+
+ previous = 0;
+ if (drmSLFirst(list, &key, &value)) {
+ do {
+ if (key <= previous) {
+ printf( "%lu !< %lu\n", previous, key);
+ }
+ previous = key;
+ } while (drmSLNext(list, &key, &value));
+ }
+
+ gettimeofday(&start, NULL);
+ for (j = 0; j < iter; j++) {
+ for (i = 0; i < size; i++) {
+ if (drmSLLookup(list, keys[i], &value))
+ printf("Error %lu %d\n", keys[i], i);
+ }
+ }
+ gettimeofday(&stop, NULL);
+
+ usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec
+ - start.tv_sec * 1000000 - start.tv_usec) / (size * iter);
+
+ printf("%0.2f microseconds for list length %d\n", usec, size);
+
+ drmRandomDouble(ranstate);
+ drmSLDestroy(list);
+
+ return usec;
+}
+
+static void print_neighbors(void *list, unsigned long key,
+ unsigned long expected_prev,
+ unsigned long expected_next)
+{
+ unsigned long prev_key = 0;
+ unsigned long next_key = 0;
+ void *prev_value;
+ void *next_value;
+ int retval;
+
+ retval = drmSLLookupNeighbors(list, key,
+ &prev_key, &prev_value,
+ &next_key, &next_value);
+ printf("Neighbors of %5lu: %d %5lu %5lu\n",
+ key, retval, prev_key, next_key);
+ if (prev_key != expected_prev) {
+ fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n",
+ prev_key, expected_prev);
+ exit(1);
+ }
+ if (next_key != expected_next) {
+ fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n",
+ next_key, expected_next);
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ void* list;
+ double usec, usec2, usec3, usec4;
+
+ list = drmSLCreate();
+ printf( "list at %p\n", list);
+
+ print(list);
+ printf("\n==============================\n\n");
+
+ drmSLInsert(list, 123, NULL);
+ drmSLInsert(list, 213, NULL);
+ drmSLInsert(list, 50, NULL);
+ print(list);
+ printf("\n==============================\n\n");
+
+ print_neighbors(list, 0, 0, 50);
+ print_neighbors(list, 50, 0, 50);
+ print_neighbors(list, 51, 50, 123);
+ print_neighbors(list, 123, 50, 123);
+ print_neighbors(list, 200, 123, 213);
+ print_neighbors(list, 213, 123, 213);
+ print_neighbors(list, 256, 213, 256);
+ printf("\n==============================\n\n");
+
+ drmSLDelete(list, 50);
+ print(list);
+ printf("\n==============================\n\n");
+
+ drmSLDump(list);
+ drmSLDestroy(list);
+ printf("\n==============================\n\n");
+
+ usec = do_time(100, 10000);
+ usec2 = do_time(1000, 500);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 1000.0/100.0, usec2 / usec);
+
+ usec3 = do_time(10000, 50);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 10000.0/100.0, usec3 / usec);
+
+ usec4 = do_time(100000, 4);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 100000.0/100.0, usec4 / usec);
+
+ return 0;
+}
diff --git a/tests/etnaviv/cmdstream.xml.h b/tests/etnaviv/cmdstream.xml.h
new file mode 100644
index 0000000..109285c
--- /dev/null
+++ b/tests/etnaviv/cmdstream.xml.h
@@ -0,0 +1,242 @@
+#ifndef CMDSTREAM_XML
+#define CMDSTREAM_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- cmdstream.xml ( 12621 bytes, from 2016-09-06 14:44:16)
+- copyright.xml ( 1597 bytes, from 2016-09-06 14:44:16)
+- common.xml ( 20583 bytes, from 2016-09-06 14:14:12)
+
+Copyright (C) 2012-2016 by the following authors:
+- Wladimir J. van der Laan <laanwj@gmail.com>
+- Christian Gmeiner <christian.gmeiner@gmail.com>
+- Lucas Stach <l.stach@pengutronix.de>
+- Russell King <rmk@arm.linux.org.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define FE_OPCODE_LOAD_STATE 0x00000001
+#define FE_OPCODE_END 0x00000002
+#define FE_OPCODE_NOP 0x00000003
+#define FE_OPCODE_DRAW_2D 0x00000004
+#define FE_OPCODE_DRAW_PRIMITIVES 0x00000005
+#define FE_OPCODE_DRAW_INDEXED_PRIMITIVES 0x00000006
+#define FE_OPCODE_WAIT 0x00000007
+#define FE_OPCODE_LINK 0x00000008
+#define FE_OPCODE_STALL 0x00000009
+#define FE_OPCODE_CALL 0x0000000a
+#define FE_OPCODE_RETURN 0x0000000b
+#define FE_OPCODE_CHIP_SELECT 0x0000000d
+#define PRIMITIVE_TYPE_POINTS 0x00000001
+#define PRIMITIVE_TYPE_LINES 0x00000002
+#define PRIMITIVE_TYPE_LINE_STRIP 0x00000003
+#define PRIMITIVE_TYPE_TRIANGLES 0x00000004
+#define PRIMITIVE_TYPE_TRIANGLE_STRIP 0x00000005
+#define PRIMITIVE_TYPE_TRIANGLE_FAN 0x00000006
+#define PRIMITIVE_TYPE_LINE_LOOP 0x00000007
+#define PRIMITIVE_TYPE_QUADS 0x00000008
+#define VIV_FE_LOAD_STATE 0x00000000
+
+#define VIV_FE_LOAD_STATE_HEADER 0x00000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__SHIFT 27
+#define VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE 0x08000000
+#define VIV_FE_LOAD_STATE_HEADER_FIXP 0x04000000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__MASK 0x03ff0000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT 16
+#define VIV_FE_LOAD_STATE_HEADER_COUNT(x) (((x) << VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK 0x0000ffff
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT 0
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET(x) (((x) << VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT) & VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR 2
+
+#define VIV_FE_END 0x00000000
+
+#define VIV_FE_END_HEADER 0x00000000
+#define VIV_FE_END_HEADER_EVENT_ID__MASK 0x0000001f
+#define VIV_FE_END_HEADER_EVENT_ID__SHIFT 0
+#define VIV_FE_END_HEADER_EVENT_ID(x) (((x) << VIV_FE_END_HEADER_EVENT_ID__SHIFT) & VIV_FE_END_HEADER_EVENT_ID__MASK)
+#define VIV_FE_END_HEADER_EVENT_ENABLE 0x00000100
+#define VIV_FE_END_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_END_HEADER_OP__SHIFT 27
+#define VIV_FE_END_HEADER_OP_END 0x10000000
+
+#define VIV_FE_NOP 0x00000000
+
+#define VIV_FE_NOP_HEADER 0x00000000
+#define VIV_FE_NOP_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_NOP_HEADER_OP__SHIFT 27
+#define VIV_FE_NOP_HEADER_OP_NOP 0x18000000
+
+#define VIV_FE_DRAW_2D 0x00000000
+
+#define VIV_FE_DRAW_2D_HEADER 0x00000000
+#define VIV_FE_DRAW_2D_HEADER_COUNT__MASK 0x0000ff00
+#define VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT 8
+#define VIV_FE_DRAW_2D_HEADER_COUNT(x) (((x) << VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK 0x07ff0000
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT 16
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT(x) (((x) << VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_DRAW_2D_HEADER_OP__SHIFT 27
+#define VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D 0x20000000
+
+#define VIV_FE_DRAW_2D_TOP_LEFT 0x00000008
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__MASK 0x0000ffff
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT 0
+#define VIV_FE_DRAW_2D_TOP_LEFT_X(x) (((x) << VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_X__MASK)
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK 0xffff0000
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT 16
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y(x) (((x) << VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK)
+
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT 0x0000000c
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK 0x0000ffff
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT 0
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x) (((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK)
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK 0xffff0000
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT 16
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(x) (((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES 0x00000000
+
+#define VIV_FE_DRAW_PRIMITIVES_HEADER 0x00000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__SHIFT 27
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES 0x28000000
+
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND 0x00000004
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK 0x000000ff
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT 0
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE(x) (((x) << VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES_START 0x00000008
+
+#define VIV_FE_DRAW_PRIMITIVES_COUNT 0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES 0x00000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER 0x00000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__SHIFT 27
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES 0x30000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND 0x00000004
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK 0x000000ff
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT 0
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE(x) (((x) << VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_START 0x00000008
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COUNT 0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_OFFSET 0x00000010
+
+#define VIV_FE_WAIT 0x00000000
+
+#define VIV_FE_WAIT_HEADER 0x00000000
+#define VIV_FE_WAIT_HEADER_DELAY__MASK 0x0000ffff
+#define VIV_FE_WAIT_HEADER_DELAY__SHIFT 0
+#define VIV_FE_WAIT_HEADER_DELAY(x) (((x) << VIV_FE_WAIT_HEADER_DELAY__SHIFT) & VIV_FE_WAIT_HEADER_DELAY__MASK)
+#define VIV_FE_WAIT_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_WAIT_HEADER_OP__SHIFT 27
+#define VIV_FE_WAIT_HEADER_OP_WAIT 0x38000000
+
+#define VIV_FE_LINK 0x00000000
+
+#define VIV_FE_LINK_HEADER 0x00000000
+#define VIV_FE_LINK_HEADER_PREFETCH__MASK 0x0000ffff
+#define VIV_FE_LINK_HEADER_PREFETCH__SHIFT 0
+#define VIV_FE_LINK_HEADER_PREFETCH(x) (((x) << VIV_FE_LINK_HEADER_PREFETCH__SHIFT) & VIV_FE_LINK_HEADER_PREFETCH__MASK)
+#define VIV_FE_LINK_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_LINK_HEADER_OP__SHIFT 27
+#define VIV_FE_LINK_HEADER_OP_LINK 0x40000000
+
+#define VIV_FE_LINK_ADDRESS 0x00000004
+
+#define VIV_FE_STALL 0x00000000
+
+#define VIV_FE_STALL_HEADER 0x00000000
+#define VIV_FE_STALL_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_STALL_HEADER_OP__SHIFT 27
+#define VIV_FE_STALL_HEADER_OP_STALL 0x48000000
+
+#define VIV_FE_STALL_TOKEN 0x00000004
+#define VIV_FE_STALL_TOKEN_FROM__MASK 0x0000001f
+#define VIV_FE_STALL_TOKEN_FROM__SHIFT 0
+#define VIV_FE_STALL_TOKEN_FROM(x) (((x) << VIV_FE_STALL_TOKEN_FROM__SHIFT) & VIV_FE_STALL_TOKEN_FROM__MASK)
+#define VIV_FE_STALL_TOKEN_TO__MASK 0x00001f00
+#define VIV_FE_STALL_TOKEN_TO__SHIFT 8
+#define VIV_FE_STALL_TOKEN_TO(x) (((x) << VIV_FE_STALL_TOKEN_TO__SHIFT) & VIV_FE_STALL_TOKEN_TO__MASK)
+
+#define VIV_FE_CALL 0x00000000
+
+#define VIV_FE_CALL_HEADER 0x00000000
+#define VIV_FE_CALL_HEADER_PREFETCH__MASK 0x0000ffff
+#define VIV_FE_CALL_HEADER_PREFETCH__SHIFT 0
+#define VIV_FE_CALL_HEADER_PREFETCH(x) (((x) << VIV_FE_CALL_HEADER_PREFETCH__SHIFT) & VIV_FE_CALL_HEADER_PREFETCH__MASK)
+#define VIV_FE_CALL_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_CALL_HEADER_OP__SHIFT 27
+#define VIV_FE_CALL_HEADER_OP_CALL 0x50000000
+
+#define VIV_FE_CALL_ADDRESS 0x00000004
+
+#define VIV_FE_CALL_RETURN_PREFETCH 0x00000008
+
+#define VIV_FE_CALL_RETURN_ADDRESS 0x0000000c
+
+#define VIV_FE_RETURN 0x00000000
+
+#define VIV_FE_RETURN_HEADER 0x00000000
+#define VIV_FE_RETURN_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_RETURN_HEADER_OP__SHIFT 27
+#define VIV_FE_RETURN_HEADER_OP_RETURN 0x58000000
+
+#define VIV_FE_CHIP_SELECT 0x00000000
+
+#define VIV_FE_CHIP_SELECT_HEADER 0x00000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__MASK 0xf8000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__SHIFT 27
+#define VIV_FE_CHIP_SELECT_HEADER_OP_CHIP_SELECT 0x68000000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP15 0x00008000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP14 0x00004000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP13 0x00002000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP12 0x00001000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP11 0x00000800
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP10 0x00000400
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP9 0x00000200
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP8 0x00000100
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP7 0x00000080
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP6 0x00000040
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP5 0x00000020
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP4 0x00000010
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP3 0x00000008
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP2 0x00000004
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1 0x00000002
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0 0x00000001
+
+
+#endif /* CMDSTREAM_XML */
diff --git a/tests/etnaviv/etnaviv_2d_test.c b/tests/etnaviv/etnaviv_2d_test.c
new file mode 100644
index 0000000..9fcdae1
--- /dev/null
+++ b/tests/etnaviv/etnaviv_2d_test.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2014-2015 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Christian Gmeiner <christian.gmeiner@gmail.com>
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xf86drm.h"
+#include "etnaviv_drmif.h"
+#include "etnaviv_drm.h"
+
+#include "state.xml.h"
+#include "state_2d.xml.h"
+#include "cmdstream.xml.h"
+
+#include "write_bmp.h"
+
+static inline void etna_emit_load_state(struct etna_cmd_stream *stream,
+ const uint16_t offset, const uint16_t count)
+{
+ uint32_t v;
+
+ v = (VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) |
+ (VIV_FE_LOAD_STATE_HEADER_COUNT(count) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK));
+
+ etna_cmd_stream_emit(stream, v);
+}
+
+static inline void etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value)
+{
+ etna_cmd_stream_reserve(stream, 2);
+ etna_emit_load_state(stream, address >> 2, 1);
+ etna_cmd_stream_emit(stream, value);
+}
+
+static inline void etna_set_state_from_bo(struct etna_cmd_stream *stream,
+ uint32_t address, struct etna_bo *bo)
+{
+ etna_cmd_stream_reserve(stream, 2);
+ etna_emit_load_state(stream, address >> 2, 1);
+
+ etna_cmd_stream_reloc(stream, &(struct etna_reloc){
+ .bo = bo,
+ .flags = ETNA_RELOC_READ,
+ .offset = 0,
+ });
+}
+
+static void gen_cmd_stream(struct etna_cmd_stream *stream, struct etna_bo *bmp, const int width, const int height)
+{
+ int rec;
+ static int num_rects = 256;
+
+ etna_set_state(stream, VIVS_DE_SRC_STRIDE, 0);
+ etna_set_state(stream, VIVS_DE_SRC_ROTATION_CONFIG, 0);
+ etna_set_state(stream, VIVS_DE_SRC_CONFIG, 0);
+ etna_set_state(stream, VIVS_DE_SRC_ORIGIN, 0);
+ etna_set_state(stream, VIVS_DE_SRC_SIZE, 0);
+ etna_set_state(stream, VIVS_DE_SRC_COLOR_BG, 0);
+ etna_set_state(stream, VIVS_DE_SRC_COLOR_FG, 0);
+ etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_LOW, 0);
+ etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_HIGH, 0);
+ etna_set_state_from_bo(stream, VIVS_DE_DEST_ADDRESS, bmp);
+ etna_set_state(stream, VIVS_DE_DEST_STRIDE, width*4);
+ etna_set_state(stream, VIVS_DE_DEST_ROTATION_CONFIG, 0);
+ etna_set_state(stream, VIVS_DE_DEST_CONFIG,
+ VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) |
+ VIVS_DE_DEST_CONFIG_COMMAND_CLEAR |
+ VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) |
+ VIVS_DE_DEST_CONFIG_TILED_DISABLE |
+ VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE
+ );
+ etna_set_state(stream, VIVS_DE_ROP,
+ VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4);
+ etna_set_state(stream, VIVS_DE_CLIP_TOP_LEFT,
+ VIVS_DE_CLIP_TOP_LEFT_X(0) |
+ VIVS_DE_CLIP_TOP_LEFT_Y(0)
+ );
+ etna_set_state(stream, VIVS_DE_CLIP_BOTTOM_RIGHT,
+ VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) |
+ VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height)
+ );
+ etna_set_state(stream, VIVS_DE_CONFIG, 0); /* TODO */
+ etna_set_state(stream, VIVS_DE_SRC_ORIGIN_FRACTION, 0);
+ etna_set_state(stream, VIVS_DE_ALPHA_CONTROL, 0);
+ etna_set_state(stream, VIVS_DE_ALPHA_MODES, 0);
+ etna_set_state(stream, VIVS_DE_DEST_ROTATION_HEIGHT, 0);
+ etna_set_state(stream, VIVS_DE_SRC_ROTATION_HEIGHT, 0);
+ etna_set_state(stream, VIVS_DE_ROT_ANGLE, 0);
+
+ /* Clear color PE20 */
+ etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40);
+ /* Clear color PE10 */
+ etna_set_state(stream, VIVS_DE_CLEAR_BYTE_MASK, 0xff);
+ etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40);
+ etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40);
+
+ etna_set_state(stream, VIVS_DE_DEST_COLOR_KEY, 0);
+ etna_set_state(stream, VIVS_DE_GLOBAL_SRC_COLOR, 0);
+ etna_set_state(stream, VIVS_DE_GLOBAL_DEST_COLOR, 0);
+ etna_set_state(stream, VIVS_DE_COLOR_MULTIPLY_MODES, 0);
+ etna_set_state(stream, VIVS_DE_PE_TRANSPARENCY, 0);
+ etna_set_state(stream, VIVS_DE_PE_CONTROL, 0);
+ etna_set_state(stream, VIVS_DE_PE_DITHER_LOW, 0xffffffff);
+ etna_set_state(stream, VIVS_DE_PE_DITHER_HIGH, 0xffffffff);
+
+ /* Queue DE command */
+ etna_cmd_stream_emit(stream,
+ VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(num_rects) /* render one rectangle */
+ );
+ etna_cmd_stream_emit(stream, 0x0); /* rectangles start aligned */
+
+ for(rec=0; rec < num_rects; ++rec) {
+ int x = rec%16;
+ int y = rec/16;
+ etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_TOP_LEFT_X(x*8) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y*8));
+ etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x*8+4) | VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(y*8+4));
+ }
+ etna_set_state(stream, 1, 0);
+ etna_set_state(stream, 1, 0);
+ etna_set_state(stream, 1, 0);
+
+ etna_set_state(stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D);
+}
+
+int etna_check_image(uint32_t *p, int width, int height)
+{
+ int i;
+ uint32_t expected;
+
+ for (i = 0; i < width * height; i++) {
+ if (i%8 < 4 && i%(width*8) < width*4 && i%width < 8*16 && i < width*8*16)
+ expected = 0xff40ff40;
+ else
+ expected = 0x00000000;
+
+ if (p[i] != expected) {
+ fprintf(stderr, "Offset %d: expected: 0x%08x, got: 0x%08x\n",
+ i, expected, p[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const int width = 256;
+ const int height = 256;
+ const size_t bmp_size = width * height * 4;
+
+ struct etna_device *dev;
+ struct etna_gpu *gpu;
+ struct etna_pipe *pipe;
+ struct etna_bo *bmp;
+ struct etna_cmd_stream *stream;
+
+ drmVersionPtr version;
+ int fd, ret = 0;
+ uint64_t feat;
+ int core = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s /dev/dri/<device> [<etna.bmp>]\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(argv[1], O_RDWR);
+ if (fd < 0) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ version = drmGetVersion(fd);
+ if (version) {
+ printf("Version: %d.%d.%d\n", version->version_major,
+ version->version_minor, version->version_patchlevel);
+ printf(" Name: %s\n", version->name);
+ printf(" Date: %s\n", version->date);
+ printf(" Description: %s\n", version->desc);
+ drmFreeVersion(version);
+ }
+
+ dev = etna_device_new(fd);
+ if (!dev) {
+ perror("etna_device_new");
+ ret = 2;
+ goto out;
+ }
+
+ do {
+ gpu = etna_gpu_new(dev, core);
+ if (!gpu) {
+ perror("etna_gpu_new");
+ ret = 3;
+ goto out_device;
+ }
+
+ if (etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &feat)) {
+ perror("etna_gpu_get_param");
+ ret = 4;
+ goto out_device;
+ }
+
+ if ((feat & (1 << 9)) == 0) {
+ /* GPU not 2D capable. */
+ etna_gpu_del(gpu);
+ gpu = NULL;
+ }
+
+ core++;
+ } while (!gpu);
+
+ pipe = etna_pipe_new(gpu, ETNA_PIPE_2D);
+ if (!pipe) {
+ perror("etna_pipe_new");
+ ret = 4;
+ goto out_gpu;
+ }
+
+ bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED);
+ if (!bmp) {
+ perror("etna_bo_new");
+ ret = 5;
+ goto out_pipe;
+ }
+ memset(etna_bo_map(bmp), 0, bmp_size);
+
+ stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL);
+ if (!stream) {
+ perror("etna_cmd_stream_new");
+ ret = 6;
+ goto out_bo;
+ }
+
+ /* generate command sequence */
+ gen_cmd_stream(stream, bmp, width, height);
+
+ etna_cmd_stream_finish(stream);
+
+ if (argc > 2)
+ bmp_dump32(etna_bo_map(bmp), width, height, false, argv[2]);
+
+ if (etna_check_image(etna_bo_map(bmp), width, height))
+ ret = 7;
+
+ etna_cmd_stream_del(stream);
+
+out_bo:
+ etna_bo_del(bmp);
+
+out_pipe:
+ etna_pipe_del(pipe);
+
+out_gpu:
+ etna_gpu_del(gpu);
+
+out_device:
+ etna_device_del(dev);
+
+out:
+ close(fd);
+
+ return ret;
+}
diff --git a/tests/etnaviv/etnaviv_bo_cache_test.c b/tests/etnaviv/etnaviv_bo_cache_test.c
new file mode 100644
index 0000000..7fb0629
--- /dev/null
+++ b/tests/etnaviv/etnaviv_bo_cache_test.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Christian Gmeiner <christian.gmeiner@gmail.com>
+ */
+
+#undef NDEBUG
+#include <assert.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xf86drm.h"
+#include "etnaviv_drmif.h"
+#include "etnaviv_drm.h"
+
+static void test_cache(struct etna_device *dev)
+{
+ struct etna_bo *bo, *tmp;
+
+ /* allocate and free some bo's with same size - we must
+ * get the same bo over and over. */
+ printf("testing bo cache ... ");
+
+ bo = tmp = etna_bo_new(dev, 0x100, ETNA_BO_UNCACHED);
+ assert(bo);
+ etna_bo_del(bo);
+
+ for (unsigned i = 0; i < 100; i++) {
+ tmp = etna_bo_new(dev, 0x100, ETNA_BO_UNCACHED);
+ etna_bo_del(tmp);
+ assert(tmp == bo);
+ }
+
+ printf("ok\n");
+}
+
+static void test_size_rounding(struct etna_device *dev)
+{
+ struct etna_bo *bo;
+
+ printf("testing size rounding ... ");
+
+ bo = etna_bo_new(dev, 15, ETNA_BO_UNCACHED);
+ assert(etna_bo_size(bo) == 4096);
+ etna_bo_del(bo);
+
+ bo = etna_bo_new(dev, 4096, ETNA_BO_UNCACHED);
+ assert(etna_bo_size(bo) == 4096);
+ etna_bo_del(bo);
+
+ bo = etna_bo_new(dev, 4100, ETNA_BO_UNCACHED);
+ assert(etna_bo_size(bo) == 8192);
+ etna_bo_del(bo);
+
+ printf("ok\n");
+}
+
+int main(int argc, char *argv[])
+{
+ struct etna_device *dev;
+
+ drmVersionPtr version;
+ int fd, ret = 0;
+
+ fd = open(argv[1], O_RDWR);
+ if (fd < 0)
+ return 1;
+
+ version = drmGetVersion(fd);
+ if (version) {
+ printf("Version: %d.%d.%d\n", version->version_major,
+ version->version_minor, version->version_patchlevel);
+ printf(" Name: %s\n", version->name);
+ printf(" Date: %s\n", version->date);
+ printf(" Description: %s\n", version->desc);
+ drmFreeVersion(version);
+ }
+
+ dev = etna_device_new(fd);
+ if (!dev) {
+ ret = 2;
+ goto out;
+ }
+
+ test_cache(dev);
+ test_size_rounding(dev);
+
+ etna_device_del(dev);
+
+out:
+ close(fd);
+
+ return ret;
+}
diff --git a/tests/etnaviv/etnaviv_cmd_stream_test.c b/tests/etnaviv/etnaviv_cmd_stream_test.c
new file mode 100644
index 0000000..b650aae
--- /dev/null
+++ b/tests/etnaviv/etnaviv_cmd_stream_test.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Christian Gmeiner <christian.gmeiner@gmail.com>
+ */
+
+#undef NDEBUG
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "etnaviv_drmif.h"
+
+static void test_avail()
+{
+ struct etna_cmd_stream *stream;
+
+ printf("testing etna_cmd_stream_avail ... ");
+
+ /* invalid size */
+ stream = etna_cmd_stream_new(NULL, 0, NULL, NULL);
+ assert(stream == NULL);
+
+ stream = etna_cmd_stream_new(NULL, 4, NULL, NULL);
+ assert(stream);
+ assert(etna_cmd_stream_avail(stream) == 2);
+ etna_cmd_stream_del(stream);
+
+ stream = etna_cmd_stream_new(NULL, 20, NULL, NULL);
+ assert(stream);
+ assert(etna_cmd_stream_avail(stream) == 18);
+ etna_cmd_stream_del(stream);
+
+ /* odd number of 32 bit words */
+ stream = etna_cmd_stream_new(NULL, 1, NULL, NULL);
+ assert(stream);
+ assert(etna_cmd_stream_avail(stream) == 0);
+ etna_cmd_stream_del(stream);
+
+ stream = etna_cmd_stream_new(NULL, 23, NULL, NULL);
+ assert(stream);
+ assert(etna_cmd_stream_avail(stream) == 22);
+ etna_cmd_stream_del(stream);
+
+ printf("ok\n");
+}
+
+static void test_emit()
+{
+ struct etna_cmd_stream *stream;
+
+ printf("testing etna_cmd_stream_emit ... ");
+
+ stream = etna_cmd_stream_new(NULL, 6, NULL, NULL);
+ assert(stream);
+ assert(etna_cmd_stream_avail(stream) == 4);
+
+ etna_cmd_stream_emit(stream, 0x1);
+ assert(etna_cmd_stream_avail(stream) == 3);
+
+ etna_cmd_stream_emit(stream, 0x2);
+ assert(etna_cmd_stream_avail(stream) == 2);
+
+ etna_cmd_stream_emit(stream, 0x3);
+ assert(etna_cmd_stream_avail(stream) == 1);
+
+ etna_cmd_stream_del(stream);
+
+ printf("ok\n");
+}
+
+static void test_offset()
+{
+ struct etna_cmd_stream *stream;
+
+ printf("testing etna_cmd_stream_offset ... ");
+
+ stream = etna_cmd_stream_new(NULL, 6, NULL, NULL);
+ assert(etna_cmd_stream_offset(stream) == 0);
+
+ etna_cmd_stream_emit(stream, 0x1);
+ assert(etna_cmd_stream_offset(stream) == 1);
+
+ etna_cmd_stream_emit(stream, 0x2);
+ assert(etna_cmd_stream_offset(stream) == 2);
+
+ etna_cmd_stream_emit(stream, 0x3);
+ etna_cmd_stream_emit(stream, 0x4);
+ assert(etna_cmd_stream_offset(stream) == 4);
+
+ etna_cmd_stream_del(stream);
+
+ printf("ok\n");
+}
+
+int main(int argc, char *argv[])
+{
+ test_avail();
+ test_emit();
+ test_offset();
+
+ return 0;
+}
diff --git a/tests/etnaviv/meson.build b/tests/etnaviv/meson.build
new file mode 100644
index 0000000..8b4a3cf
--- /dev/null
+++ b/tests/etnaviv/meson.build
@@ -0,0 +1,45 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+inc_etnaviv_tests = [inc_root, inc_drm, include_directories('../../etnaviv')]
+
+etnaviv_2d_test = executable(
+ 'etnaviv_2d_test',
+ files('etnaviv_2d_test.c', 'write_bmp.c'),
+ include_directories : inc_etnaviv_tests,
+ link_with : [libdrm, libdrm_etnaviv],
+ install : with_install_tests,
+)
+
+etnaviv_cmd_stream_test = executable(
+ 'etnaviv_cmd_stream_test',
+ files('etnaviv_cmd_stream_test.c'),
+ include_directories : inc_etnaviv_tests,
+ link_with : [libdrm, libdrm_etnaviv],
+ install : with_install_tests,
+)
+
+etnaviv_bo_cache_test = executable(
+ 'etnaviv_bo_cache_test',
+ files('etnaviv_bo_cache_test.c'),
+ include_directories : inc_etnaviv_tests,
+ link_with : [libdrm, libdrm_etnaviv],
+ install : with_install_tests,
+)
diff --git a/tests/etnaviv/state.xml.h b/tests/etnaviv/state.xml.h
new file mode 100644
index 0000000..e1ecbf3
--- /dev/null
+++ b/tests/etnaviv/state.xml.h
@@ -0,0 +1,375 @@
+#ifndef STATE_XML
+#define STATE_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- state.xml ( 18940 bytes, from 2016-09-06 14:14:12)
+- common.xml ( 20583 bytes, from 2016-09-06 14:14:12)
+- state_hi.xml ( 25653 bytes, from 2016-09-06 14:45:17)
+- copyright.xml ( 1597 bytes, from 2016-09-06 14:44:16)
+- state_2d.xml ( 51552 bytes, from 2016-09-06 14:44:16)
+- state_3d.xml ( 54603 bytes, from 2016-09-06 14:44:16)
+- state_vg.xml ( 5975 bytes, from 2016-09-06 14:44:16)
+
+Copyright (C) 2012-2016 by the following authors:
+- Wladimir J. van der Laan <laanwj@gmail.com>
+- Christian Gmeiner <christian.gmeiner@gmail.com>
+- Lucas Stach <l.stach@pengutronix.de>
+- Russell King <rmk@arm.linux.org.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define VARYING_COMPONENT_USE_UNUSED 0x00000000
+#define VARYING_COMPONENT_USE_USED 0x00000001
+#define VARYING_COMPONENT_USE_POINTCOORD_X 0x00000002
+#define VARYING_COMPONENT_USE_POINTCOORD_Y 0x00000003
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK 0x000000ff
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT 0
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(x) (((x) << FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT) & FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK)
+#define VIVS_FE 0x00000000
+
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG(i0) (0x00000600 + 0x4*(i0))
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__ESIZE 0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__LEN 0x00000010
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__MASK 0x0000000f
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__SHIFT 0
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_BYTE 0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_BYTE 0x00000001
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_SHORT 0x00000002
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_SHORT 0x00000003
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT 0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT 0x00000005
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT 0x00000008
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_HALF_FLOAT 0x00000009
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FIXED 0x0000000b
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT_10_10_10_2 0x0000000c
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT_10_10_10_2 0x0000000d
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK 0x00000030
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT 4
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE 0x00000080
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK 0x00000700
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT 8
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK 0x00003000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT 12
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__MASK 0x0000c000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__SHIFT 14
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF 0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON 0x00008000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK 0x00ff0000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT 16
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK 0xff000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT 24
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK)
+
+#define VIVS_FE_CMD_STREAM_BASE_ADDR 0x00000640
+
+#define VIVS_FE_INDEX_STREAM_BASE_ADDR 0x00000644
+
+#define VIVS_FE_INDEX_STREAM_CONTROL 0x00000648
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__MASK 0x00000003
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__SHIFT 0
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR 0x00000000
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT 0x00000001
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT 0x00000002
+
+#define VIVS_FE_VERTEX_STREAM_BASE_ADDR 0x0000064c
+
+#define VIVS_FE_VERTEX_STREAM_CONTROL 0x00000650
+
+#define VIVS_FE_COMMAND_ADDRESS 0x00000654
+
+#define VIVS_FE_COMMAND_CONTROL 0x00000658
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK 0x0000ffff
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT 0
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH(x) (((x) << VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT) & VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK)
+#define VIVS_FE_COMMAND_CONTROL_ENABLE 0x00010000
+
+#define VIVS_FE_DMA_STATUS 0x0000065c
+
+#define VIVS_FE_DMA_DEBUG_STATE 0x00000660
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__MASK 0x0000001f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__SHIFT 0
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DEC 0x00000001
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR0 0x00000002
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD0 0x00000003
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR1 0x00000004
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD1 0x00000005
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DADR 0x00000006
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCMD 0x00000007
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCNTL 0x00000008
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DIDXCNTL 0x00000009
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_INITREQDMA 0x0000000a
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAWIDX 0x0000000b
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAW 0x0000000c
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT0 0x0000000d
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT1 0x0000000e
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA0 0x0000000f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA1 0x00000010
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAITFIFO 0x00000011
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAIT 0x00000012
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LINK 0x00000013
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_END 0x00000014
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_STALL 0x00000015
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__MASK 0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__SHIFT 8
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_START 0x00000100
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_REQ 0x00000200
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_END 0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__MASK 0x00000c00
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__SHIFT 10
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_RAMVALID 0x00000400
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_VALID 0x00000800
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__MASK 0x00003000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__SHIFT 12
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_WAITIDX 0x00001000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_CAL 0x00002000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__MASK 0x0000c000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__SHIFT 14
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_LDADR 0x00004000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDXCALC 0x00008000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__MASK 0x00030000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__SHIFT 16
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_IDLE 0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_CKCACHE 0x00010000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_MISS 0x00020000
+
+#define VIVS_FE_DMA_ADDRESS 0x00000664
+
+#define VIVS_FE_DMA_LOW 0x00000668
+
+#define VIVS_FE_DMA_HIGH 0x0000066c
+
+#define VIVS_FE_AUTO_FLUSH 0x00000670
+
+#define VIVS_FE_UNK00678 0x00000678
+
+#define VIVS_FE_UNK0067C 0x0000067c
+
+#define VIVS_FE_VERTEX_STREAMS(i0) (0x00000000 + 0x4*(i0))
+#define VIVS_FE_VERTEX_STREAMS__ESIZE 0x00000004
+#define VIVS_FE_VERTEX_STREAMS__LEN 0x00000008
+
+#define VIVS_FE_VERTEX_STREAMS_BASE_ADDR(i0) (0x00000680 + 0x4*(i0))
+
+#define VIVS_FE_VERTEX_STREAMS_CONTROL(i0) (0x000006a0 + 0x4*(i0))
+
+#define VIVS_FE_UNK00700(i0) (0x00000700 + 0x4*(i0))
+#define VIVS_FE_UNK00700__ESIZE 0x00000004
+#define VIVS_FE_UNK00700__LEN 0x00000010
+
+#define VIVS_FE_UNK00740(i0) (0x00000740 + 0x4*(i0))
+#define VIVS_FE_UNK00740__ESIZE 0x00000004
+#define VIVS_FE_UNK00740__LEN 0x00000010
+
+#define VIVS_FE_UNK00780(i0) (0x00000780 + 0x4*(i0))
+#define VIVS_FE_UNK00780__ESIZE 0x00000004
+#define VIVS_FE_UNK00780__LEN 0x00000010
+
+#define VIVS_GL 0x00000000
+
+#define VIVS_GL_PIPE_SELECT 0x00003800
+#define VIVS_GL_PIPE_SELECT_PIPE__MASK 0x00000001
+#define VIVS_GL_PIPE_SELECT_PIPE__SHIFT 0
+#define VIVS_GL_PIPE_SELECT_PIPE(x) (((x) << VIVS_GL_PIPE_SELECT_PIPE__SHIFT) & VIVS_GL_PIPE_SELECT_PIPE__MASK)
+
+#define VIVS_GL_EVENT 0x00003804
+#define VIVS_GL_EVENT_EVENT_ID__MASK 0x0000001f
+#define VIVS_GL_EVENT_EVENT_ID__SHIFT 0
+#define VIVS_GL_EVENT_EVENT_ID(x) (((x) << VIVS_GL_EVENT_EVENT_ID__SHIFT) & VIVS_GL_EVENT_EVENT_ID__MASK)
+#define VIVS_GL_EVENT_FROM_FE 0x00000020
+#define VIVS_GL_EVENT_FROM_PE 0x00000040
+#define VIVS_GL_EVENT_SOURCE__MASK 0x00001f00
+#define VIVS_GL_EVENT_SOURCE__SHIFT 8
+#define VIVS_GL_EVENT_SOURCE(x) (((x) << VIVS_GL_EVENT_SOURCE__SHIFT) & VIVS_GL_EVENT_SOURCE__MASK)
+
+#define VIVS_GL_SEMAPHORE_TOKEN 0x00003808
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK 0x0000001f
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT 0
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM(x) (((x) << VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK)
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__MASK 0x00001f00
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT 8
+#define VIVS_GL_SEMAPHORE_TOKEN_TO(x) (((x) << VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_TO__MASK)
+
+#define VIVS_GL_FLUSH_CACHE 0x0000380c
+#define VIVS_GL_FLUSH_CACHE_DEPTH 0x00000001
+#define VIVS_GL_FLUSH_CACHE_COLOR 0x00000002
+#define VIVS_GL_FLUSH_CACHE_TEXTURE 0x00000004
+#define VIVS_GL_FLUSH_CACHE_PE2D 0x00000008
+#define VIVS_GL_FLUSH_CACHE_TEXTUREVS 0x00000010
+#define VIVS_GL_FLUSH_CACHE_SHADER_L1 0x00000020
+#define VIVS_GL_FLUSH_CACHE_SHADER_L2 0x00000040
+
+#define VIVS_GL_FLUSH_MMU 0x00003810
+#define VIVS_GL_FLUSH_MMU_FLUSH_FEMMU 0x00000001
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK1 0x00000002
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK2 0x00000004
+#define VIVS_GL_FLUSH_MMU_FLUSH_PEMMU 0x00000008
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK4 0x00000010
+
+#define VIVS_GL_VERTEX_ELEMENT_CONFIG 0x00003814
+
+#define VIVS_GL_MULTI_SAMPLE_CONFIG 0x00003818
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK 0x00000003
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__SHIFT 0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE 0x00000000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X 0x00000001
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X 0x00000002
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_MASK 0x00000008
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK 0x000000f0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT 4
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES_MASK 0x00000100
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK 0x00007000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT 12
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12_MASK 0x00008000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK 0x00030000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT 16
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16_MASK 0x00080000
+
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS 0x0000381c
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK 0x000000ff
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT 0
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(x) (((x) << VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT) & VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK)
+
+#define VIVS_GL_VARYING_NUM_COMPONENTS 0x00003820
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK 0x00000007
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT 0
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK 0x00000070
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT 4
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK 0x00000700
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT 8
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK 0x00007000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT 12
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK 0x00070000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT 16
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK 0x00700000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT 20
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK 0x07000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT 24
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK 0x70000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT 28
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK)
+
+#define VIVS_GL_VARYING_COMPONENT_USE(i0) (0x00003828 + 0x4*(i0))
+#define VIVS_GL_VARYING_COMPONENT_USE__ESIZE 0x00000004
+#define VIVS_GL_VARYING_COMPONENT_USE__LEN 0x00000002
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK 0x00000003
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT 0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK 0x0000000c
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT 2
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK 0x00000030
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT 4
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK 0x000000c0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT 6
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK 0x00000300
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT 8
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK 0x00000c00
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT 10
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK 0x00003000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT 12
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK 0x0000c000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT 14
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK 0x00030000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT 16
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK 0x000c0000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT 18
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK 0x00300000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT 20
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK 0x00c00000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT 22
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK 0x03000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT 24
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK 0x0c000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT 26
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK 0x30000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT 28
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK 0xc0000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT 30
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK)
+
+#define VIVS_GL_UNK03834 0x00003834
+
+#define VIVS_GL_UNK03838 0x00003838
+
+#define VIVS_GL_API_MODE 0x0000384c
+#define VIVS_GL_API_MODE_OPENGL 0x00000000
+#define VIVS_GL_API_MODE_OPENVG 0x00000001
+#define VIVS_GL_API_MODE_OPENCL 0x00000002
+
+#define VIVS_GL_CONTEXT_POINTER 0x00003850
+
+#define VIVS_GL_UNK03A00 0x00003a00
+
+#define VIVS_GL_STALL_TOKEN 0x00003c00
+#define VIVS_GL_STALL_TOKEN_FROM__MASK 0x0000001f
+#define VIVS_GL_STALL_TOKEN_FROM__SHIFT 0
+#define VIVS_GL_STALL_TOKEN_FROM(x) (((x) << VIVS_GL_STALL_TOKEN_FROM__SHIFT) & VIVS_GL_STALL_TOKEN_FROM__MASK)
+#define VIVS_GL_STALL_TOKEN_TO__MASK 0x00001f00
+#define VIVS_GL_STALL_TOKEN_TO__SHIFT 8
+#define VIVS_GL_STALL_TOKEN_TO(x) (((x) << VIVS_GL_STALL_TOKEN_TO__SHIFT) & VIVS_GL_STALL_TOKEN_TO__MASK)
+#define VIVS_GL_STALL_TOKEN_FLIP0 0x40000000
+#define VIVS_GL_STALL_TOKEN_FLIP1 0x80000000
+
+#define VIVS_DUMMY 0x00000000
+
+#define VIVS_DUMMY_DUMMY 0x0003fffc
+
+
+#endif /* STATE_XML */
diff --git a/tests/etnaviv/state_2d.xml.h b/tests/etnaviv/state_2d.xml.h
new file mode 100644
index 0000000..715eed4
--- /dev/null
+++ b/tests/etnaviv/state_2d.xml.h
@@ -0,0 +1,1497 @@
+#ifndef STATE_2D_XML
+#define STATE_2D_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- state.xml ( 18940 bytes, from 2016-09-06 14:14:12)
+- common.xml ( 20583 bytes, from 2016-09-06 14:14:12)
+- state_hi.xml ( 25653 bytes, from 2016-09-06 14:45:17)
+- copyright.xml ( 1597 bytes, from 2016-09-06 14:44:16)
+- state_2d.xml ( 51552 bytes, from 2016-09-06 14:44:16)
+- state_3d.xml ( 54603 bytes, from 2016-09-06 14:44:16)
+- state_vg.xml ( 5975 bytes, from 2016-09-06 14:44:16)
+
+Copyright (C) 2012-2016 by the following authors:
+- Wladimir J. van der Laan <laanwj@gmail.com>
+- Christian Gmeiner <christian.gmeiner@gmail.com>
+- Lucas Stach <l.stach@pengutronix.de>
+- Russell King <rmk@arm.linux.org.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define DE_FORMAT_X4R4G4B4 0x00000000
+#define DE_FORMAT_A4R4G4B4 0x00000001
+#define DE_FORMAT_X1R5G5B5 0x00000002
+#define DE_FORMAT_A1R5G5B5 0x00000003
+#define DE_FORMAT_R5G6B5 0x00000004
+#define DE_FORMAT_X8R8G8B8 0x00000005
+#define DE_FORMAT_A8R8G8B8 0x00000006
+#define DE_FORMAT_YUY2 0x00000007
+#define DE_FORMAT_UYVY 0x00000008
+#define DE_FORMAT_INDEX8 0x00000009
+#define DE_FORMAT_MONOCHROME 0x0000000a
+#define DE_FORMAT_YV12 0x0000000f
+#define DE_FORMAT_A8 0x00000010
+#define DE_FORMAT_NV12 0x00000011
+#define DE_FORMAT_NV16 0x00000012
+#define DE_FORMAT_RG16 0x00000013
+#define DE_SWIZZLE_ARGB 0x00000000
+#define DE_SWIZZLE_RGBA 0x00000001
+#define DE_SWIZZLE_ABGR 0x00000002
+#define DE_SWIZZLE_BGRA 0x00000003
+#define DE_BLENDMODE_ZERO 0x00000000
+#define DE_BLENDMODE_ONE 0x00000001
+#define DE_BLENDMODE_NORMAL 0x00000002
+#define DE_BLENDMODE_INVERSED 0x00000003
+#define DE_BLENDMODE_COLOR 0x00000004
+#define DE_BLENDMODE_COLOR_INVERSED 0x00000005
+#define DE_BLENDMODE_SATURATED_ALPHA 0x00000006
+#define DE_BLENDMODE_SATURATED_DEST_ALPHA 0x00000007
+#define DE_COMPONENT_BLUE 0x00000000
+#define DE_COMPONENT_GREEN 0x00000001
+#define DE_COMPONENT_RED 0x00000002
+#define DE_COMPONENT_ALPHA 0x00000003
+#define DE_ROT_MODE_ROT0 0x00000000
+#define DE_ROT_MODE_FLIP_X 0x00000001
+#define DE_ROT_MODE_FLIP_Y 0x00000002
+#define DE_ROT_MODE_ROT90 0x00000004
+#define DE_ROT_MODE_ROT180 0x00000005
+#define DE_ROT_MODE_ROT270 0x00000006
+#define DE_MIRROR_MODE_NONE 0x00000000
+#define DE_MIRROR_MODE_MIRROR_X 0x00000001
+#define DE_MIRROR_MODE_MIRROR_Y 0x00000002
+#define DE_MIRROR_MODE_MIRROR_XY 0x00000003
+#define DE_COLOR_BLUE__MASK 0x000000ff
+#define DE_COLOR_BLUE__SHIFT 0
+#define DE_COLOR_BLUE(x) (((x) << DE_COLOR_BLUE__SHIFT) & DE_COLOR_BLUE__MASK)
+#define DE_COLOR_GREEN__MASK 0x0000ff00
+#define DE_COLOR_GREEN__SHIFT 8
+#define DE_COLOR_GREEN(x) (((x) << DE_COLOR_GREEN__SHIFT) & DE_COLOR_GREEN__MASK)
+#define DE_COLOR_RED__MASK 0x00ff0000
+#define DE_COLOR_RED__SHIFT 16
+#define DE_COLOR_RED(x) (((x) << DE_COLOR_RED__SHIFT) & DE_COLOR_RED__MASK)
+#define DE_COLOR_ALPHA__MASK 0xff000000
+#define DE_COLOR_ALPHA__SHIFT 24
+#define DE_COLOR_ALPHA(x) (((x) << DE_COLOR_ALPHA__SHIFT) & DE_COLOR_ALPHA__MASK)
+#define VIVS_DE 0x00000000
+
+#define VIVS_DE_SRC_ADDRESS 0x00001200
+
+#define VIVS_DE_SRC_STRIDE 0x00001204
+#define VIVS_DE_SRC_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_SRC_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_SRC_STRIDE_STRIDE(x) (((x) << VIVS_DE_SRC_STRIDE_STRIDE__SHIFT) & VIVS_DE_SRC_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_SRC_ROTATION_CONFIG 0x00001208
+#define VIVS_DE_SRC_ROTATION_CONFIG_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_SRC_ROTATION_CONFIG_WIDTH__SHIFT 0
+#define VIVS_DE_SRC_ROTATION_CONFIG_WIDTH(x) (((x) << VIVS_DE_SRC_ROTATION_CONFIG_WIDTH__SHIFT) & VIVS_DE_SRC_ROTATION_CONFIG_WIDTH__MASK)
+#define VIVS_DE_SRC_ROTATION_CONFIG_ROTATION__MASK 0x00010000
+#define VIVS_DE_SRC_ROTATION_CONFIG_ROTATION__SHIFT 16
+#define VIVS_DE_SRC_ROTATION_CONFIG_ROTATION_DISABLE 0x00000000
+#define VIVS_DE_SRC_ROTATION_CONFIG_ROTATION_ENABLE 0x00010000
+
+#define VIVS_DE_SRC_CONFIG 0x0000120c
+#define VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK 0x0000000f
+#define VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT 0
+#define VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT(x) (((x) << VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT) & VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK)
+#define VIVS_DE_SRC_CONFIG_TRANSPARENCY__MASK 0x00000030
+#define VIVS_DE_SRC_CONFIG_TRANSPARENCY__SHIFT 4
+#define VIVS_DE_SRC_CONFIG_TRANSPARENCY(x) (((x) << VIVS_DE_SRC_CONFIG_TRANSPARENCY__SHIFT) & VIVS_DE_SRC_CONFIG_TRANSPARENCY__MASK)
+#define VIVS_DE_SRC_CONFIG_SRC_RELATIVE__MASK 0x00000040
+#define VIVS_DE_SRC_CONFIG_SRC_RELATIVE__SHIFT 6
+#define VIVS_DE_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x00000000
+#define VIVS_DE_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x00000040
+#define VIVS_DE_SRC_CONFIG_TILED__MASK 0x00000080
+#define VIVS_DE_SRC_CONFIG_TILED__SHIFT 7
+#define VIVS_DE_SRC_CONFIG_TILED_DISABLE 0x00000000
+#define VIVS_DE_SRC_CONFIG_TILED_ENABLE 0x00000080
+#define VIVS_DE_SRC_CONFIG_LOCATION__MASK 0x00000100
+#define VIVS_DE_SRC_CONFIG_LOCATION__SHIFT 8
+#define VIVS_DE_SRC_CONFIG_LOCATION_MEMORY 0x00000000
+#define VIVS_DE_SRC_CONFIG_LOCATION_STREAM 0x00000100
+#define VIVS_DE_SRC_CONFIG_PACK__MASK 0x00003000
+#define VIVS_DE_SRC_CONFIG_PACK__SHIFT 12
+#define VIVS_DE_SRC_CONFIG_PACK_PACKED8 0x00000000
+#define VIVS_DE_SRC_CONFIG_PACK_PACKED16 0x00001000
+#define VIVS_DE_SRC_CONFIG_PACK_PACKED32 0x00002000
+#define VIVS_DE_SRC_CONFIG_PACK_UNPACKED 0x00003000
+#define VIVS_DE_SRC_CONFIG_MONO_TRANSPARENCY__MASK 0x00008000
+#define VIVS_DE_SRC_CONFIG_MONO_TRANSPARENCY__SHIFT 15
+#define VIVS_DE_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x00000000
+#define VIVS_DE_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x00008000
+#define VIVS_DE_SRC_CONFIG_UNK16 0x00010000
+#define VIVS_DE_SRC_CONFIG_SWIZZLE__MASK 0x00300000
+#define VIVS_DE_SRC_CONFIG_SWIZZLE__SHIFT 20
+#define VIVS_DE_SRC_CONFIG_SWIZZLE(x) (((x) << VIVS_DE_SRC_CONFIG_SWIZZLE__SHIFT) & VIVS_DE_SRC_CONFIG_SWIZZLE__MASK)
+#define VIVS_DE_SRC_CONFIG_SOURCE_FORMAT__MASK 0x1f000000
+#define VIVS_DE_SRC_CONFIG_SOURCE_FORMAT__SHIFT 24
+#define VIVS_DE_SRC_CONFIG_SOURCE_FORMAT(x) (((x) << VIVS_DE_SRC_CONFIG_SOURCE_FORMAT__SHIFT) & VIVS_DE_SRC_CONFIG_SOURCE_FORMAT__MASK)
+#define VIVS_DE_SRC_CONFIG_DISABLE420_L2_CACHE 0x20000000
+#define VIVS_DE_SRC_CONFIG_ENDIAN_CONTROL__MASK 0xc0000000
+#define VIVS_DE_SRC_CONFIG_ENDIAN_CONTROL__SHIFT 30
+#define VIVS_DE_SRC_CONFIG_ENDIAN_CONTROL(x) (((x) << VIVS_DE_SRC_CONFIG_ENDIAN_CONTROL__SHIFT) & VIVS_DE_SRC_CONFIG_ENDIAN_CONTROL__MASK)
+
+#define VIVS_DE_SRC_ORIGIN 0x00001210
+#define VIVS_DE_SRC_ORIGIN_X__MASK 0x0000ffff
+#define VIVS_DE_SRC_ORIGIN_X__SHIFT 0
+#define VIVS_DE_SRC_ORIGIN_X(x) (((x) << VIVS_DE_SRC_ORIGIN_X__SHIFT) & VIVS_DE_SRC_ORIGIN_X__MASK)
+#define VIVS_DE_SRC_ORIGIN_Y__MASK 0xffff0000
+#define VIVS_DE_SRC_ORIGIN_Y__SHIFT 16
+#define VIVS_DE_SRC_ORIGIN_Y(x) (((x) << VIVS_DE_SRC_ORIGIN_Y__SHIFT) & VIVS_DE_SRC_ORIGIN_Y__MASK)
+
+#define VIVS_DE_SRC_SIZE 0x00001214
+#define VIVS_DE_SRC_SIZE_X__MASK 0x0000ffff
+#define VIVS_DE_SRC_SIZE_X__SHIFT 0
+#define VIVS_DE_SRC_SIZE_X(x) (((x) << VIVS_DE_SRC_SIZE_X__SHIFT) & VIVS_DE_SRC_SIZE_X__MASK)
+#define VIVS_DE_SRC_SIZE_Y__MASK 0xffff0000
+#define VIVS_DE_SRC_SIZE_Y__SHIFT 16
+#define VIVS_DE_SRC_SIZE_Y(x) (((x) << VIVS_DE_SRC_SIZE_Y__SHIFT) & VIVS_DE_SRC_SIZE_Y__MASK)
+
+#define VIVS_DE_SRC_COLOR_BG 0x00001218
+
+#define VIVS_DE_SRC_COLOR_FG 0x0000121c
+
+#define VIVS_DE_STRETCH_FACTOR_LOW 0x00001220
+#define VIVS_DE_STRETCH_FACTOR_LOW_X__MASK 0x7fffffff
+#define VIVS_DE_STRETCH_FACTOR_LOW_X__SHIFT 0
+#define VIVS_DE_STRETCH_FACTOR_LOW_X(x) (((x) << VIVS_DE_STRETCH_FACTOR_LOW_X__SHIFT) & VIVS_DE_STRETCH_FACTOR_LOW_X__MASK)
+
+#define VIVS_DE_STRETCH_FACTOR_HIGH 0x00001224
+#define VIVS_DE_STRETCH_FACTOR_HIGH_Y__MASK 0x7fffffff
+#define VIVS_DE_STRETCH_FACTOR_HIGH_Y__SHIFT 0
+#define VIVS_DE_STRETCH_FACTOR_HIGH_Y(x) (((x) << VIVS_DE_STRETCH_FACTOR_HIGH_Y__SHIFT) & VIVS_DE_STRETCH_FACTOR_HIGH_Y__MASK)
+
+#define VIVS_DE_DEST_ADDRESS 0x00001228
+
+#define VIVS_DE_DEST_STRIDE 0x0000122c
+#define VIVS_DE_DEST_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_DEST_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_DEST_STRIDE_STRIDE(x) (((x) << VIVS_DE_DEST_STRIDE_STRIDE__SHIFT) & VIVS_DE_DEST_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_DEST_ROTATION_CONFIG 0x00001230
+#define VIVS_DE_DEST_ROTATION_CONFIG_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_DEST_ROTATION_CONFIG_WIDTH__SHIFT 0
+#define VIVS_DE_DEST_ROTATION_CONFIG_WIDTH(x) (((x) << VIVS_DE_DEST_ROTATION_CONFIG_WIDTH__SHIFT) & VIVS_DE_DEST_ROTATION_CONFIG_WIDTH__MASK)
+#define VIVS_DE_DEST_ROTATION_CONFIG_ROTATION__MASK 0x00010000
+#define VIVS_DE_DEST_ROTATION_CONFIG_ROTATION__SHIFT 16
+#define VIVS_DE_DEST_ROTATION_CONFIG_ROTATION_DISABLE 0x00000000
+#define VIVS_DE_DEST_ROTATION_CONFIG_ROTATION_ENABLE 0x00010000
+
+#define VIVS_DE_DEST_CONFIG 0x00001234
+#define VIVS_DE_DEST_CONFIG_FORMAT__MASK 0x0000001f
+#define VIVS_DE_DEST_CONFIG_FORMAT__SHIFT 0
+#define VIVS_DE_DEST_CONFIG_FORMAT(x) (((x) << VIVS_DE_DEST_CONFIG_FORMAT__SHIFT) & VIVS_DE_DEST_CONFIG_FORMAT__MASK)
+#define VIVS_DE_DEST_CONFIG_TILED__MASK 0x00000100
+#define VIVS_DE_DEST_CONFIG_TILED__SHIFT 8
+#define VIVS_DE_DEST_CONFIG_TILED_DISABLE 0x00000000
+#define VIVS_DE_DEST_CONFIG_TILED_ENABLE 0x00000100
+#define VIVS_DE_DEST_CONFIG_COMMAND__MASK 0x0000f000
+#define VIVS_DE_DEST_CONFIG_COMMAND__SHIFT 12
+#define VIVS_DE_DEST_CONFIG_COMMAND_CLEAR 0x00000000
+#define VIVS_DE_DEST_CONFIG_COMMAND_LINE 0x00001000
+#define VIVS_DE_DEST_CONFIG_COMMAND_BIT_BLT 0x00002000
+#define VIVS_DE_DEST_CONFIG_COMMAND_BIT_BLT_REVERSED 0x00003000
+#define VIVS_DE_DEST_CONFIG_COMMAND_STRETCH_BLT 0x00004000
+#define VIVS_DE_DEST_CONFIG_COMMAND_HOR_FILTER_BLT 0x00005000
+#define VIVS_DE_DEST_CONFIG_COMMAND_VER_FILTER_BLT 0x00006000
+#define VIVS_DE_DEST_CONFIG_COMMAND_ONE_PASS_FILTER_BLT 0x00007000
+#define VIVS_DE_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT 0x00008000
+#define VIVS_DE_DEST_CONFIG_SWIZZLE__MASK 0x00030000
+#define VIVS_DE_DEST_CONFIG_SWIZZLE__SHIFT 16
+#define VIVS_DE_DEST_CONFIG_SWIZZLE(x) (((x) << VIVS_DE_DEST_CONFIG_SWIZZLE__SHIFT) & VIVS_DE_DEST_CONFIG_SWIZZLE__MASK)
+#define VIVS_DE_DEST_CONFIG_ENDIAN_CONTROL__MASK 0x00300000
+#define VIVS_DE_DEST_CONFIG_ENDIAN_CONTROL__SHIFT 20
+#define VIVS_DE_DEST_CONFIG_ENDIAN_CONTROL(x) (((x) << VIVS_DE_DEST_CONFIG_ENDIAN_CONTROL__SHIFT) & VIVS_DE_DEST_CONFIG_ENDIAN_CONTROL__MASK)
+#define VIVS_DE_DEST_CONFIG_GDI_STRE__MASK 0x01000000
+#define VIVS_DE_DEST_CONFIG_GDI_STRE__SHIFT 24
+#define VIVS_DE_DEST_CONFIG_GDI_STRE_DISABLE 0x00000000
+#define VIVS_DE_DEST_CONFIG_GDI_STRE_ENABLE 0x01000000
+#define VIVS_DE_DEST_CONFIG_INTER_TILE_PER_FIX__MASK 0x02000000
+#define VIVS_DE_DEST_CONFIG_INTER_TILE_PER_FIX__SHIFT 25
+#define VIVS_DE_DEST_CONFIG_INTER_TILE_PER_FIX_DISABLED 0x02000000
+#define VIVS_DE_DEST_CONFIG_INTER_TILE_PER_FIX_ENABLED 0x00000000
+#define VIVS_DE_DEST_CONFIG_MINOR_TILED__MASK 0x04000000
+#define VIVS_DE_DEST_CONFIG_MINOR_TILED__SHIFT 26
+#define VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE 0x00000000
+#define VIVS_DE_DEST_CONFIG_MINOR_TILED_ENABLE 0x04000000
+
+#define VIVS_DE_PATTERN_ADDRESS 0x00001238
+
+#define VIVS_DE_PATTERN_CONFIG 0x0000123c
+#define VIVS_DE_PATTERN_CONFIG_FORMAT__MASK 0x0000000f
+#define VIVS_DE_PATTERN_CONFIG_FORMAT__SHIFT 0
+#define VIVS_DE_PATTERN_CONFIG_FORMAT(x) (((x) << VIVS_DE_PATTERN_CONFIG_FORMAT__SHIFT) & VIVS_DE_PATTERN_CONFIG_FORMAT__MASK)
+#define VIVS_DE_PATTERN_CONFIG_TYPE__MASK 0x00000010
+#define VIVS_DE_PATTERN_CONFIG_TYPE__SHIFT 4
+#define VIVS_DE_PATTERN_CONFIG_TYPE_SOLID_COLOR 0x00000000
+#define VIVS_DE_PATTERN_CONFIG_TYPE_PATTERN 0x00000010
+#define VIVS_DE_PATTERN_CONFIG_COLOR_CONVERT__MASK 0x00000020
+#define VIVS_DE_PATTERN_CONFIG_COLOR_CONVERT__SHIFT 5
+#define VIVS_DE_PATTERN_CONFIG_COLOR_CONVERT_DISABLE 0x00000000
+#define VIVS_DE_PATTERN_CONFIG_COLOR_CONVERT_ENABLE 0x00000020
+#define VIVS_DE_PATTERN_CONFIG_INIT_TRIGGER__MASK 0x000000c0
+#define VIVS_DE_PATTERN_CONFIG_INIT_TRIGGER__SHIFT 6
+#define VIVS_DE_PATTERN_CONFIG_INIT_TRIGGER(x) (((x) << VIVS_DE_PATTERN_CONFIG_INIT_TRIGGER__SHIFT) & VIVS_DE_PATTERN_CONFIG_INIT_TRIGGER__MASK)
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_X__MASK 0x00070000
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_X__SHIFT 16
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_X(x) (((x) << VIVS_DE_PATTERN_CONFIG_ORIGIN_X__SHIFT) & VIVS_DE_PATTERN_CONFIG_ORIGIN_X__MASK)
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_Y__MASK 0x00700000
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_Y__SHIFT 20
+#define VIVS_DE_PATTERN_CONFIG_ORIGIN_Y(x) (((x) << VIVS_DE_PATTERN_CONFIG_ORIGIN_Y__SHIFT) & VIVS_DE_PATTERN_CONFIG_ORIGIN_Y__MASK)
+
+#define VIVS_DE_PATTERN_LOW 0x00001240
+
+#define VIVS_DE_PATTERN_HIGH 0x00001244
+
+#define VIVS_DE_PATTERN_MASK_LOW 0x00001248
+
+#define VIVS_DE_PATTERN_MASK_HIGH 0x0000124c
+
+#define VIVS_DE_PATTERN_BG_COLOR 0x00001250
+
+#define VIVS_DE_PATTERN_FG_COLOR 0x00001254
+
+#define VIVS_DE_ROP 0x0000125c
+#define VIVS_DE_ROP_ROP_FG__MASK 0x000000ff
+#define VIVS_DE_ROP_ROP_FG__SHIFT 0
+#define VIVS_DE_ROP_ROP_FG(x) (((x) << VIVS_DE_ROP_ROP_FG__SHIFT) & VIVS_DE_ROP_ROP_FG__MASK)
+#define VIVS_DE_ROP_ROP_BG__MASK 0x0000ff00
+#define VIVS_DE_ROP_ROP_BG__SHIFT 8
+#define VIVS_DE_ROP_ROP_BG(x) (((x) << VIVS_DE_ROP_ROP_BG__SHIFT) & VIVS_DE_ROP_ROP_BG__MASK)
+#define VIVS_DE_ROP_TYPE__MASK 0x00300000
+#define VIVS_DE_ROP_TYPE__SHIFT 20
+#define VIVS_DE_ROP_TYPE_ROP2_PATTERN 0x00000000
+#define VIVS_DE_ROP_TYPE_ROP2_SOURCE 0x00100000
+#define VIVS_DE_ROP_TYPE_ROP3 0x00200000
+#define VIVS_DE_ROP_TYPE_ROP4 0x00300000
+
+#define VIVS_DE_CLIP_TOP_LEFT 0x00001260
+#define VIVS_DE_CLIP_TOP_LEFT_X__MASK 0x00007fff
+#define VIVS_DE_CLIP_TOP_LEFT_X__SHIFT 0
+#define VIVS_DE_CLIP_TOP_LEFT_X(x) (((x) << VIVS_DE_CLIP_TOP_LEFT_X__SHIFT) & VIVS_DE_CLIP_TOP_LEFT_X__MASK)
+#define VIVS_DE_CLIP_TOP_LEFT_Y__MASK 0x7fff0000
+#define VIVS_DE_CLIP_TOP_LEFT_Y__SHIFT 16
+#define VIVS_DE_CLIP_TOP_LEFT_Y(x) (((x) << VIVS_DE_CLIP_TOP_LEFT_Y__SHIFT) & VIVS_DE_CLIP_TOP_LEFT_Y__MASK)
+
+#define VIVS_DE_CLIP_BOTTOM_RIGHT 0x00001264
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_X__MASK 0x00007fff
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_X__SHIFT 0
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_X(x) (((x) << VIVS_DE_CLIP_BOTTOM_RIGHT_X__SHIFT) & VIVS_DE_CLIP_BOTTOM_RIGHT_X__MASK)
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_Y__MASK 0x7fff0000
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_Y__SHIFT 16
+#define VIVS_DE_CLIP_BOTTOM_RIGHT_Y(x) (((x) << VIVS_DE_CLIP_BOTTOM_RIGHT_Y__SHIFT) & VIVS_DE_CLIP_BOTTOM_RIGHT_Y__MASK)
+
+#define VIVS_DE_CLEAR_BYTE_MASK 0x00001268
+
+#define VIVS_DE_CONFIG 0x0000126c
+#define VIVS_DE_CONFIG_MIRROR_BLT_ENABLE__MASK 0x00000001
+#define VIVS_DE_CONFIG_MIRROR_BLT_ENABLE__SHIFT 0
+#define VIVS_DE_CONFIG_MIRROR_BLT_ENABLE_OFF 0x00000000
+#define VIVS_DE_CONFIG_MIRROR_BLT_ENABLE_ON 0x00000001
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE__MASK 0x00000030
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE__SHIFT 4
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE_NORMAL 0x00000000
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE_HMIRROR 0x00000010
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE_VMIRROR 0x00000020
+#define VIVS_DE_CONFIG_MIRROR_BLT_MODE_FULL_MIRROR 0x00000030
+#define VIVS_DE_CONFIG_SOURCE_SELECT__MASK 0x00070000
+#define VIVS_DE_CONFIG_SOURCE_SELECT__SHIFT 16
+#define VIVS_DE_CONFIG_SOURCE_SELECT(x) (((x) << VIVS_DE_CONFIG_SOURCE_SELECT__SHIFT) & VIVS_DE_CONFIG_SOURCE_SELECT__MASK)
+#define VIVS_DE_CONFIG_DESTINATION_SELECT__MASK 0x00300000
+#define VIVS_DE_CONFIG_DESTINATION_SELECT__SHIFT 20
+#define VIVS_DE_CONFIG_DESTINATION_SELECT(x) (((x) << VIVS_DE_CONFIG_DESTINATION_SELECT__SHIFT) & VIVS_DE_CONFIG_DESTINATION_SELECT__MASK)
+
+#define VIVS_DE_CLEAR_PIXEL_VALUE_LOW 0x00001270
+
+#define VIVS_DE_CLEAR_PIXEL_VALUE_HIGH 0x00001274
+
+#define VIVS_DE_SRC_ORIGIN_FRACTION 0x00001278
+#define VIVS_DE_SRC_ORIGIN_FRACTION_X__MASK 0x0000ffff
+#define VIVS_DE_SRC_ORIGIN_FRACTION_X__SHIFT 0
+#define VIVS_DE_SRC_ORIGIN_FRACTION_X(x) (((x) << VIVS_DE_SRC_ORIGIN_FRACTION_X__SHIFT) & VIVS_DE_SRC_ORIGIN_FRACTION_X__MASK)
+#define VIVS_DE_SRC_ORIGIN_FRACTION_Y__MASK 0xffff0000
+#define VIVS_DE_SRC_ORIGIN_FRACTION_Y__SHIFT 16
+#define VIVS_DE_SRC_ORIGIN_FRACTION_Y(x) (((x) << VIVS_DE_SRC_ORIGIN_FRACTION_Y__SHIFT) & VIVS_DE_SRC_ORIGIN_FRACTION_Y__MASK)
+
+#define VIVS_DE_ALPHA_CONTROL 0x0000127c
+#define VIVS_DE_ALPHA_CONTROL_ENABLE__MASK 0x00000001
+#define VIVS_DE_ALPHA_CONTROL_ENABLE__SHIFT 0
+#define VIVS_DE_ALPHA_CONTROL_ENABLE_OFF 0x00000000
+#define VIVS_DE_ALPHA_CONTROL_ENABLE_ON 0x00000001
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK 0x00ff0000
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT 16
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA(x) (((x) << VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT) & VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK)
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK 0xff000000
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT 24
+#define VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA(x) (((x) << VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT) & VIVS_DE_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK)
+
+#define VIVS_DE_ALPHA_MODES 0x00001280
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_MODE__MASK 0x00000001
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_MODE__SHIFT 0
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x00000001
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_MODE__MASK 0x00000010
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_MODE__SHIFT 4
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x00000010
+#define VIVS_DE_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__MASK 0x00000300
+#define VIVS_DE_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__SHIFT 8
+#define VIVS_DE_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x00000100
+#define VIVS_DE_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x00000200
+#define VIVS_DE_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__MASK 0x00003000
+#define VIVS_DE_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__SHIFT 12
+#define VIVS_DE_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x00001000
+#define VIVS_DE_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x00002000
+#define VIVS_DE_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__MASK 0x00010000
+#define VIVS_DE_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__SHIFT 16
+#define VIVS_DE_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_ENABLE 0x00010000
+#define VIVS_DE_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__MASK 0x00100000
+#define VIVS_DE_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__SHIFT 20
+#define VIVS_DE_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_ENABLE 0x00100000
+#define VIVS_DE_ALPHA_MODES_SRC_BLENDING_MODE__MASK 0x07000000
+#define VIVS_DE_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT 24
+#define VIVS_DE_ALPHA_MODES_SRC_BLENDING_MODE(x) (((x) << VIVS_DE_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT) & VIVS_DE_ALPHA_MODES_SRC_BLENDING_MODE__MASK)
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_FACTOR__MASK 0x08000000
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_FACTOR__SHIFT 27
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLE 0x08000000
+#define VIVS_DE_ALPHA_MODES_DST_BLENDING_MODE__MASK 0x70000000
+#define VIVS_DE_ALPHA_MODES_DST_BLENDING_MODE__SHIFT 28
+#define VIVS_DE_ALPHA_MODES_DST_BLENDING_MODE(x) (((x) << VIVS_DE_ALPHA_MODES_DST_BLENDING_MODE__SHIFT) & VIVS_DE_ALPHA_MODES_DST_BLENDING_MODE__MASK)
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_FACTOR__MASK 0x80000000
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_FACTOR__SHIFT 31
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLE 0x80000000
+
+#define VIVS_DE_UPLANE_ADDRESS 0x00001284
+
+#define VIVS_DE_UPLANE_STRIDE 0x00001288
+#define VIVS_DE_UPLANE_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_UPLANE_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_UPLANE_STRIDE_STRIDE(x) (((x) << VIVS_DE_UPLANE_STRIDE_STRIDE__SHIFT) & VIVS_DE_UPLANE_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_VPLANE_ADDRESS 0x0000128c
+
+#define VIVS_DE_VPLANE_STRIDE 0x00001290
+#define VIVS_DE_VPLANE_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_VPLANE_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_VPLANE_STRIDE_STRIDE(x) (((x) << VIVS_DE_VPLANE_STRIDE_STRIDE__SHIFT) & VIVS_DE_VPLANE_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_VR_CONFIG 0x00001294
+#define VIVS_DE_VR_CONFIG_START__MASK 0x00000003
+#define VIVS_DE_VR_CONFIG_START__SHIFT 0
+#define VIVS_DE_VR_CONFIG_START_HORIZONTAL_BLIT 0x00000000
+#define VIVS_DE_VR_CONFIG_START_VERTICAL_BLIT 0x00000001
+#define VIVS_DE_VR_CONFIG_START_ONE_PASS_BLIT 0x00000002
+#define VIVS_DE_VR_CONFIG_START_MASK 0x00000008
+
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW 0x00001298
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_LEFT__MASK 0x0000ffff
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_LEFT__SHIFT 0
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_LEFT(x) (((x) << VIVS_DE_VR_SOURCE_IMAGE_LOW_LEFT__SHIFT) & VIVS_DE_VR_SOURCE_IMAGE_LOW_LEFT__MASK)
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_TOP__MASK 0xffff0000
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_TOP__SHIFT 16
+#define VIVS_DE_VR_SOURCE_IMAGE_LOW_TOP(x) (((x) << VIVS_DE_VR_SOURCE_IMAGE_LOW_TOP__SHIFT) & VIVS_DE_VR_SOURCE_IMAGE_LOW_TOP__MASK)
+
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH 0x0000129c
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_RIGHT__MASK 0x0000ffff
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_RIGHT__SHIFT 0
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_RIGHT(x) (((x) << VIVS_DE_VR_SOURCE_IMAGE_HIGH_RIGHT__SHIFT) & VIVS_DE_VR_SOURCE_IMAGE_HIGH_RIGHT__MASK)
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_BOTTOM__MASK 0xffff0000
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_BOTTOM__SHIFT 16
+#define VIVS_DE_VR_SOURCE_IMAGE_HIGH_BOTTOM(x) (((x) << VIVS_DE_VR_SOURCE_IMAGE_HIGH_BOTTOM__SHIFT) & VIVS_DE_VR_SOURCE_IMAGE_HIGH_BOTTOM__MASK)
+
+#define VIVS_DE_VR_SOURCE_ORIGIN_LOW 0x000012a0
+#define VIVS_DE_VR_SOURCE_ORIGIN_LOW_X__MASK 0xffffffff
+#define VIVS_DE_VR_SOURCE_ORIGIN_LOW_X__SHIFT 0
+#define VIVS_DE_VR_SOURCE_ORIGIN_LOW_X(x) (((x) << VIVS_DE_VR_SOURCE_ORIGIN_LOW_X__SHIFT) & VIVS_DE_VR_SOURCE_ORIGIN_LOW_X__MASK)
+
+#define VIVS_DE_VR_SOURCE_ORIGIN_HIGH 0x000012a4
+#define VIVS_DE_VR_SOURCE_ORIGIN_HIGH_Y__MASK 0xffffffff
+#define VIVS_DE_VR_SOURCE_ORIGIN_HIGH_Y__SHIFT 0
+#define VIVS_DE_VR_SOURCE_ORIGIN_HIGH_Y(x) (((x) << VIVS_DE_VR_SOURCE_ORIGIN_HIGH_Y__SHIFT) & VIVS_DE_VR_SOURCE_ORIGIN_HIGH_Y__MASK)
+
+#define VIVS_DE_VR_TARGET_WINDOW_LOW 0x000012a8
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_LEFT__MASK 0x0000ffff
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_LEFT__SHIFT 0
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_LEFT(x) (((x) << VIVS_DE_VR_TARGET_WINDOW_LOW_LEFT__SHIFT) & VIVS_DE_VR_TARGET_WINDOW_LOW_LEFT__MASK)
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_TOP__MASK 0xffff0000
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_TOP__SHIFT 16
+#define VIVS_DE_VR_TARGET_WINDOW_LOW_TOP(x) (((x) << VIVS_DE_VR_TARGET_WINDOW_LOW_TOP__SHIFT) & VIVS_DE_VR_TARGET_WINDOW_LOW_TOP__MASK)
+
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH 0x000012ac
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_RIGHT__MASK 0x0000ffff
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_RIGHT__SHIFT 0
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_RIGHT(x) (((x) << VIVS_DE_VR_TARGET_WINDOW_HIGH_RIGHT__SHIFT) & VIVS_DE_VR_TARGET_WINDOW_HIGH_RIGHT__MASK)
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_BOTTOM__MASK 0xffff0000
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_BOTTOM__SHIFT 16
+#define VIVS_DE_VR_TARGET_WINDOW_HIGH_BOTTOM(x) (((x) << VIVS_DE_VR_TARGET_WINDOW_HIGH_BOTTOM__SHIFT) & VIVS_DE_VR_TARGET_WINDOW_HIGH_BOTTOM__MASK)
+
+#define VIVS_DE_PE_CONFIG 0x000012b0
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH__MASK 0x00000003
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH__SHIFT 0
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH_DISABLE 0x00000000
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH_DEFAULT 0x00000001
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH_ALWAYS 0x00000002
+#define VIVS_DE_PE_CONFIG_DESTINATION_FETCH_MASK 0x00000008
+
+#define VIVS_DE_DEST_ROTATION_HEIGHT 0x000012b4
+#define VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT__MASK 0x0000ffff
+#define VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT__SHIFT 0
+#define VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT(x) (((x) << VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT__SHIFT) & VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT__MASK)
+
+#define VIVS_DE_SRC_ROTATION_HEIGHT 0x000012b8
+#define VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT__MASK 0x0000ffff
+#define VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT 0
+#define VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT(x) (((x) << VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT) & VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT__MASK)
+
+#define VIVS_DE_ROT_ANGLE 0x000012bc
+#define VIVS_DE_ROT_ANGLE_SRC__MASK 0x00000007
+#define VIVS_DE_ROT_ANGLE_SRC__SHIFT 0
+#define VIVS_DE_ROT_ANGLE_SRC(x) (((x) << VIVS_DE_ROT_ANGLE_SRC__SHIFT) & VIVS_DE_ROT_ANGLE_SRC__MASK)
+#define VIVS_DE_ROT_ANGLE_DST__MASK 0x00000038
+#define VIVS_DE_ROT_ANGLE_DST__SHIFT 3
+#define VIVS_DE_ROT_ANGLE_DST(x) (((x) << VIVS_DE_ROT_ANGLE_DST__SHIFT) & VIVS_DE_ROT_ANGLE_DST__MASK)
+#define VIVS_DE_ROT_ANGLE_SRC_MASK 0x00000100
+#define VIVS_DE_ROT_ANGLE_DST_MASK 0x00000200
+#define VIVS_DE_ROT_ANGLE_SRC_MIRROR__MASK 0x00003000
+#define VIVS_DE_ROT_ANGLE_SRC_MIRROR__SHIFT 12
+#define VIVS_DE_ROT_ANGLE_SRC_MIRROR(x) (((x) << VIVS_DE_ROT_ANGLE_SRC_MIRROR__SHIFT) & VIVS_DE_ROT_ANGLE_SRC_MIRROR__MASK)
+#define VIVS_DE_ROT_ANGLE_SRC_MIRROR_MASK 0x00008000
+#define VIVS_DE_ROT_ANGLE_DST_MIRROR__MASK 0x00030000
+#define VIVS_DE_ROT_ANGLE_DST_MIRROR__SHIFT 16
+#define VIVS_DE_ROT_ANGLE_DST_MIRROR(x) (((x) << VIVS_DE_ROT_ANGLE_DST_MIRROR__SHIFT) & VIVS_DE_ROT_ANGLE_DST_MIRROR__MASK)
+#define VIVS_DE_ROT_ANGLE_DST_MIRROR_MASK 0x00080000
+
+#define VIVS_DE_CLEAR_PIXEL_VALUE32 0x000012c0
+
+#define VIVS_DE_DEST_COLOR_KEY 0x000012c4
+
+#define VIVS_DE_GLOBAL_SRC_COLOR 0x000012c8
+
+#define VIVS_DE_GLOBAL_DEST_COLOR 0x000012cc
+
+#define VIVS_DE_COLOR_MULTIPLY_MODES 0x000012d0
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__MASK 0x00000001
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__SHIFT 0
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x00000001
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__MASK 0x00000010
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__SHIFT 4
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x00000010
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__MASK 0x00000300
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__SHIFT 8
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x00000100
+#define VIVS_DE_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x00000200
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__MASK 0x00100000
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__SHIFT 20
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x00100000
+
+#define VIVS_DE_PE_TRANSPARENCY 0x000012d4
+#define VIVS_DE_PE_TRANSPARENCY_SOURCE__MASK 0x00000003
+#define VIVS_DE_PE_TRANSPARENCY_SOURCE__SHIFT 0
+#define VIVS_DE_PE_TRANSPARENCY_SOURCE_OPAQUE 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_SOURCE_MASK 0x00000001
+#define VIVS_DE_PE_TRANSPARENCY_SOURCE_KEY 0x00000002
+#define VIVS_DE_PE_TRANSPARENCY_PATTERN__MASK 0x00000030
+#define VIVS_DE_PE_TRANSPARENCY_PATTERN__SHIFT 4
+#define VIVS_DE_PE_TRANSPARENCY_PATTERN_OPAQUE 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_PATTERN_MASK 0x00000010
+#define VIVS_DE_PE_TRANSPARENCY_PATTERN_KEY 0x00000020
+#define VIVS_DE_PE_TRANSPARENCY_DESTINATION__MASK 0x00000300
+#define VIVS_DE_PE_TRANSPARENCY_DESTINATION__SHIFT 8
+#define VIVS_DE_PE_TRANSPARENCY_DESTINATION_OPAQUE 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_DESTINATION_MASK 0x00000100
+#define VIVS_DE_PE_TRANSPARENCY_DESTINATION_KEY 0x00000200
+#define VIVS_DE_PE_TRANSPARENCY_TRANSPARENCY_MASK 0x00001000
+#define VIVS_DE_PE_TRANSPARENCY_USE_SRC_OVERRIDE__MASK 0x00030000
+#define VIVS_DE_PE_TRANSPARENCY_USE_SRC_OVERRIDE__SHIFT 16
+#define VIVS_DE_PE_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x00010000
+#define VIVS_DE_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x00020000
+#define VIVS_DE_PE_TRANSPARENCY_USE_PAT_OVERRIDE__MASK 0x00300000
+#define VIVS_DE_PE_TRANSPARENCY_USE_PAT_OVERRIDE__SHIFT 20
+#define VIVS_DE_PE_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x00100000
+#define VIVS_DE_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x00200000
+#define VIVS_DE_PE_TRANSPARENCY_USE_DST_OVERRIDE__MASK 0x03000000
+#define VIVS_DE_PE_TRANSPARENCY_USE_DST_OVERRIDE__SHIFT 24
+#define VIVS_DE_PE_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x01000000
+#define VIVS_DE_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x02000000
+#define VIVS_DE_PE_TRANSPARENCY_RESOURCE_OVERRIDE_MASK 0x10000000
+#define VIVS_DE_PE_TRANSPARENCY_DFB_COLOR_KEY__MASK 0x20000000
+#define VIVS_DE_PE_TRANSPARENCY_DFB_COLOR_KEY__SHIFT 29
+#define VIVS_DE_PE_TRANSPARENCY_DFB_COLOR_KEY_DISABLE 0x00000000
+#define VIVS_DE_PE_TRANSPARENCY_DFB_COLOR_KEY_ENABLE 0x20000000
+#define VIVS_DE_PE_TRANSPARENCY_DFB_COLOR_KEY_MASK 0x80000000
+
+#define VIVS_DE_PE_CONTROL 0x000012d8
+#define VIVS_DE_PE_CONTROL_YUV__MASK 0x00000001
+#define VIVS_DE_PE_CONTROL_YUV__SHIFT 0
+#define VIVS_DE_PE_CONTROL_YUV_601 0x00000000
+#define VIVS_DE_PE_CONTROL_YUV_709 0x00000001
+#define VIVS_DE_PE_CONTROL_YUV_MASK 0x00000008
+#define VIVS_DE_PE_CONTROL_UV_SWIZZLE__MASK 0x00000010
+#define VIVS_DE_PE_CONTROL_UV_SWIZZLE__SHIFT 4
+#define VIVS_DE_PE_CONTROL_UV_SWIZZLE_UV 0x00000000
+#define VIVS_DE_PE_CONTROL_UV_SWIZZLE_VU 0x00000010
+#define VIVS_DE_PE_CONTROL_UV_SWIZZLE_MASK 0x00000080
+#define VIVS_DE_PE_CONTROL_YUVRGB__MASK 0x00000100
+#define VIVS_DE_PE_CONTROL_YUVRGB__SHIFT 8
+#define VIVS_DE_PE_CONTROL_YUVRGB_DISABLE 0x00000000
+#define VIVS_DE_PE_CONTROL_YUVRGB_ENABLE 0x00000100
+#define VIVS_DE_PE_CONTROL_YUVRGB_MASK 0x00000800
+
+#define VIVS_DE_SRC_COLOR_KEY_HIGH 0x000012dc
+
+#define VIVS_DE_DEST_COLOR_KEY_HIGH 0x000012e0
+
+#define VIVS_DE_VR_CONFIG_EX 0x000012e4
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH__MASK 0x00000003
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH__SHIFT 0
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_AUTO 0x00000000
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS16 0x00000001
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS32 0x00000002
+#define VIVS_DE_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_MASK 0x00000008
+#define VIVS_DE_VR_CONFIG_EX_FILTER_TAP__MASK 0x000000f0
+#define VIVS_DE_VR_CONFIG_EX_FILTER_TAP__SHIFT 4
+#define VIVS_DE_VR_CONFIG_EX_FILTER_TAP(x) (((x) << VIVS_DE_VR_CONFIG_EX_FILTER_TAP__SHIFT) & VIVS_DE_VR_CONFIG_EX_FILTER_TAP__MASK)
+#define VIVS_DE_VR_CONFIG_EX_FILTER_TAP_MASK 0x00000100
+
+#define VIVS_DE_PE_DITHER_LOW 0x000012e8
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y0__MASK 0x0000000f
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y0__SHIFT 0
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y0(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y0__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y0__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y0__MASK 0x000000f0
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y0__SHIFT 4
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y0(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y0__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y0__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y0__MASK 0x00000f00
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y0__SHIFT 8
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y0(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y0__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y0__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y0__MASK 0x0000f000
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y0__SHIFT 12
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y0(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y0__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y0__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y1__MASK 0x000f0000
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y1__SHIFT 16
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y1(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y1__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X0_Y1__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y1__MASK 0x00f00000
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y1__SHIFT 20
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y1(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y1__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X1_Y1__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y1__MASK 0x0f000000
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y1__SHIFT 24
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y1(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y1__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X2_Y1__MASK)
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y1__MASK 0xf0000000
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y1__SHIFT 28
+#define VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y1(x) (((x) << VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y1__SHIFT) & VIVS_DE_PE_DITHER_LOW_PIXEL_X3_Y1__MASK)
+
+#define VIVS_DE_PE_DITHER_HIGH 0x000012ec
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y2__MASK 0x0000000f
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y2__SHIFT 0
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y2(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y2__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y2__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y2__MASK 0x000000f0
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y2__SHIFT 4
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y2(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y2__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y2__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y2__MASK 0x00000f00
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y2__SHIFT 8
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y2(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y2__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y2__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y2__MASK 0x0000f000
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y2__SHIFT 12
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y2(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y2__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y2__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y3__MASK 0x000f0000
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y3__SHIFT 16
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y3(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y3__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X0_Y3__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y3__MASK 0x00f00000
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y3__SHIFT 20
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y3(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y3__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X1_Y3__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y3__MASK 0x0f000000
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y3__SHIFT 24
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y3(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y3__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X2_Y3__MASK)
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y3__MASK 0xf0000000
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y3__SHIFT 28
+#define VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y3(x) (((x) << VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y3__SHIFT) & VIVS_DE_PE_DITHER_HIGH_PIXEL_X3_Y3__MASK)
+
+#define VIVS_DE_BW_CONFIG 0x000012f0
+#define VIVS_DE_BW_CONFIG_BLOCK_CONFIG__MASK 0x00000001
+#define VIVS_DE_BW_CONFIG_BLOCK_CONFIG__SHIFT 0
+#define VIVS_DE_BW_CONFIG_BLOCK_CONFIG_AUTO 0x00000000
+#define VIVS_DE_BW_CONFIG_BLOCK_CONFIG_CUSTOMIZE 0x00000001
+#define VIVS_DE_BW_CONFIG_BLOCK_CONFIG_MASK 0x00000008
+#define VIVS_DE_BW_CONFIG_BLOCK_WALK_DIRECTION__MASK 0x00000010
+#define VIVS_DE_BW_CONFIG_BLOCK_WALK_DIRECTION__SHIFT 4
+#define VIVS_DE_BW_CONFIG_BLOCK_WALK_DIRECTION_RIGHT_BOTTOM 0x00000000
+#define VIVS_DE_BW_CONFIG_BLOCK_WALK_DIRECTION_BOTTOM_RIGHT 0x00000010
+#define VIVS_DE_BW_CONFIG_BLOCK_WALK_DIRECTION_MASK 0x00000080
+#define VIVS_DE_BW_CONFIG_TILE_WALK_DIRECTION__MASK 0x00000100
+#define VIVS_DE_BW_CONFIG_TILE_WALK_DIRECTION__SHIFT 8
+#define VIVS_DE_BW_CONFIG_TILE_WALK_DIRECTION_RIGHT_BOTTOM 0x00000000
+#define VIVS_DE_BW_CONFIG_TILE_WALK_DIRECTION_BOTTOM_RIGHT 0x00000100
+#define VIVS_DE_BW_CONFIG_TILE_WALK_DIRECTION_MASK 0x00000800
+#define VIVS_DE_BW_CONFIG_PIXEL_WALK_DIRECTION__MASK 0x00001000
+#define VIVS_DE_BW_CONFIG_PIXEL_WALK_DIRECTION__SHIFT 12
+#define VIVS_DE_BW_CONFIG_PIXEL_WALK_DIRECTION_RIGHT_BOTTOM 0x00000000
+#define VIVS_DE_BW_CONFIG_PIXEL_WALK_DIRECTION_BOTTOM_RIGHT 0x00001000
+#define VIVS_DE_BW_CONFIG_PIXEL_WALK_DIRECTION_MASK 0x00008000
+
+#define VIVS_DE_BW_BLOCK_SIZE 0x000012f4
+#define VIVS_DE_BW_BLOCK_SIZE_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_BW_BLOCK_SIZE_WIDTH__SHIFT 0
+#define VIVS_DE_BW_BLOCK_SIZE_WIDTH(x) (((x) << VIVS_DE_BW_BLOCK_SIZE_WIDTH__SHIFT) & VIVS_DE_BW_BLOCK_SIZE_WIDTH__MASK)
+#define VIVS_DE_BW_BLOCK_SIZE_HEIGHT__MASK 0xffff0000
+#define VIVS_DE_BW_BLOCK_SIZE_HEIGHT__SHIFT 16
+#define VIVS_DE_BW_BLOCK_SIZE_HEIGHT(x) (((x) << VIVS_DE_BW_BLOCK_SIZE_HEIGHT__SHIFT) & VIVS_DE_BW_BLOCK_SIZE_HEIGHT__MASK)
+
+#define VIVS_DE_BW_TILE_SIZE 0x000012f8
+#define VIVS_DE_BW_TILE_SIZE_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_BW_TILE_SIZE_WIDTH__SHIFT 0
+#define VIVS_DE_BW_TILE_SIZE_WIDTH(x) (((x) << VIVS_DE_BW_TILE_SIZE_WIDTH__SHIFT) & VIVS_DE_BW_TILE_SIZE_WIDTH__MASK)
+#define VIVS_DE_BW_TILE_SIZE_HEIGHT__MASK 0xffff0000
+#define VIVS_DE_BW_TILE_SIZE_HEIGHT__SHIFT 16
+#define VIVS_DE_BW_TILE_SIZE_HEIGHT(x) (((x) << VIVS_DE_BW_TILE_SIZE_HEIGHT__SHIFT) & VIVS_DE_BW_TILE_SIZE_HEIGHT__MASK)
+
+#define VIVS_DE_BW_BLOCK_MASK 0x000012fc
+#define VIVS_DE_BW_BLOCK_MASK_HORIZONTAL__MASK 0x0000ffff
+#define VIVS_DE_BW_BLOCK_MASK_HORIZONTAL__SHIFT 0
+#define VIVS_DE_BW_BLOCK_MASK_HORIZONTAL(x) (((x) << VIVS_DE_BW_BLOCK_MASK_HORIZONTAL__SHIFT) & VIVS_DE_BW_BLOCK_MASK_HORIZONTAL__MASK)
+#define VIVS_DE_BW_BLOCK_MASK_VERTICAL__MASK 0xffff0000
+#define VIVS_DE_BW_BLOCK_MASK_VERTICAL__SHIFT 16
+#define VIVS_DE_BW_BLOCK_MASK_VERTICAL(x) (((x) << VIVS_DE_BW_BLOCK_MASK_VERTICAL__SHIFT) & VIVS_DE_BW_BLOCK_MASK_VERTICAL__MASK)
+
+#define VIVS_DE_SRC_EX_CONFIG 0x00001300
+#define VIVS_DE_SRC_EX_CONFIG_MULTI_TILED__MASK 0x00000001
+#define VIVS_DE_SRC_EX_CONFIG_MULTI_TILED__SHIFT 0
+#define VIVS_DE_SRC_EX_CONFIG_MULTI_TILED_DISABLE 0x00000000
+#define VIVS_DE_SRC_EX_CONFIG_MULTI_TILED_ENABLE 0x00000001
+#define VIVS_DE_SRC_EX_CONFIG_SUPER_TILED__MASK 0x00000008
+#define VIVS_DE_SRC_EX_CONFIG_SUPER_TILED__SHIFT 3
+#define VIVS_DE_SRC_EX_CONFIG_SUPER_TILED_DISABLE 0x00000000
+#define VIVS_DE_SRC_EX_CONFIG_SUPER_TILED_ENABLE 0x00000008
+#define VIVS_DE_SRC_EX_CONFIG_MINOR_TILED__MASK 0x00000100
+#define VIVS_DE_SRC_EX_CONFIG_MINOR_TILED__SHIFT 8
+#define VIVS_DE_SRC_EX_CONFIG_MINOR_TILED_DISABLE 0x00000000
+#define VIVS_DE_SRC_EX_CONFIG_MINOR_TILED_ENABLE 0x00000100
+
+#define VIVS_DE_SRC_EX_ADDRESS 0x00001304
+
+#define VIVS_DE_DE_MULTI_SOURCE 0x00001308
+#define VIVS_DE_DE_MULTI_SOURCE_MAX_SOURCE__MASK 0x00000007
+#define VIVS_DE_DE_MULTI_SOURCE_MAX_SOURCE__SHIFT 0
+#define VIVS_DE_DE_MULTI_SOURCE_MAX_SOURCE(x) (((x) << VIVS_DE_DE_MULTI_SOURCE_MAX_SOURCE__SHIFT) & VIVS_DE_DE_MULTI_SOURCE_MAX_SOURCE__MASK)
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK__MASK 0x00000700
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK__SHIFT 8
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16 0x00000000
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL32 0x00000100
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL64 0x00000200
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128 0x00000300
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL256 0x00000400
+#define VIVS_DE_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL512 0x00000500
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK__MASK 0x00070000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK__SHIFT 16
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1 0x00000000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE2 0x00010000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE4 0x00020000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE8 0x00030000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE16 0x00040000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE32 0x00050000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64 0x00060000
+#define VIVS_DE_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE128 0x00070000
+
+#define VIVS_DE_DEYUV_CONVERSION 0x0000130c
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE__MASK 0x00000003
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE__SHIFT 0
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE_OFF 0x00000000
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE_PLANE1 0x00000001
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE_PLANE2 0x00000002
+#define VIVS_DE_DEYUV_CONVERSION_ENABLE_PLANE3 0x00000003
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_COUNT__MASK 0x0000000c
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_COUNT__SHIFT 2
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_COUNT(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE1_COUNT__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE1_COUNT__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_COUNT__MASK 0x00000030
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_COUNT__SHIFT 4
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_COUNT(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE2_COUNT__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE2_COUNT__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_COUNT__MASK 0x000000c0
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_COUNT__SHIFT 6
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_COUNT(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE3_COUNT__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE3_COUNT__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_B__MASK 0x00000300
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_B__SHIFT 8
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_B(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_B__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_B__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_G__MASK 0x00000c00
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_G__SHIFT 10
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_G(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_G__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_G__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_R__MASK 0x00003000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_R__SHIFT 12
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_R(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_R__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_R__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_A__MASK 0x0000c000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_A__SHIFT 14
+#define VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_A(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_A__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE1_SWIZZLE_A__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_B__MASK 0x00030000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_B__SHIFT 16
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_B(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_B__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_B__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_G__MASK 0x000c0000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_G__SHIFT 18
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_G(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_G__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_G__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_R__MASK 0x00300000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_R__SHIFT 20
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_R(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_R__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_R__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_A__MASK 0x00c00000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_A__SHIFT 22
+#define VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_A(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_A__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE2_SWIZZLE_A__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_B__MASK 0x03000000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_B__SHIFT 24
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_B(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_B__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_B__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_G__MASK 0x0c000000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_G__SHIFT 26
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_G(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_G__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_G__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_R__MASK 0x30000000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_R__SHIFT 28
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_R(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_R__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_R__MASK)
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_A__MASK 0xc0000000
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_A__SHIFT 30
+#define VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_A(x) (((x) << VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_A__SHIFT) & VIVS_DE_DEYUV_CONVERSION_PLANE3_SWIZZLE_A__MASK)
+
+#define VIVS_DE_DE_PLANE2_ADDRESS 0x00001310
+
+#define VIVS_DE_DE_PLANE2_STRIDE 0x00001314
+#define VIVS_DE_DE_PLANE2_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_DE_PLANE2_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_DE_PLANE2_STRIDE_STRIDE(x) (((x) << VIVS_DE_DE_PLANE2_STRIDE_STRIDE__SHIFT) & VIVS_DE_DE_PLANE2_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_DE_PLANE3_ADDRESS 0x00001318
+
+#define VIVS_DE_DE_PLANE3_STRIDE 0x0000131c
+#define VIVS_DE_DE_PLANE3_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_DE_PLANE3_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_DE_PLANE3_STRIDE_STRIDE(x) (((x) << VIVS_DE_DE_PLANE3_STRIDE_STRIDE__SHIFT) & VIVS_DE_DE_PLANE3_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_DE_STALL_DE 0x00001320
+#define VIVS_DE_DE_STALL_DE_ENABLE__MASK 0x00000001
+#define VIVS_DE_DE_STALL_DE_ENABLE__SHIFT 0
+#define VIVS_DE_DE_STALL_DE_ENABLE_DISABLE 0x00000000
+#define VIVS_DE_DE_STALL_DE_ENABLE_ENABLE 0x00000001
+
+#define VIVS_DE_FILTER_KERNEL(i0) (0x00001800 + 0x4*(i0))
+#define VIVS_DE_FILTER_KERNEL__ESIZE 0x00000004
+#define VIVS_DE_FILTER_KERNEL__LEN 0x00000080
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT0__MASK 0x0000ffff
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT0__SHIFT 0
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT0(x) (((x) << VIVS_DE_FILTER_KERNEL_COEFFICIENT0__SHIFT) & VIVS_DE_FILTER_KERNEL_COEFFICIENT0__MASK)
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT1__MASK 0xffff0000
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT1__SHIFT 16
+#define VIVS_DE_FILTER_KERNEL_COEFFICIENT1(x) (((x) << VIVS_DE_FILTER_KERNEL_COEFFICIENT1__SHIFT) & VIVS_DE_FILTER_KERNEL_COEFFICIENT1__MASK)
+
+#define VIVS_DE_INDEX_COLOR_TABLE(i0) (0x00001c00 + 0x4*(i0))
+#define VIVS_DE_INDEX_COLOR_TABLE__ESIZE 0x00000004
+#define VIVS_DE_INDEX_COLOR_TABLE__LEN 0x00000100
+
+#define VIVS_DE_HORI_FILTER_KERNEL(i0) (0x00002800 + 0x4*(i0))
+#define VIVS_DE_HORI_FILTER_KERNEL__ESIZE 0x00000004
+#define VIVS_DE_HORI_FILTER_KERNEL__LEN 0x00000080
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT0__MASK 0x0000ffff
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT0__SHIFT 0
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT0(x) (((x) << VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT0__SHIFT) & VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT0__MASK)
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT1__MASK 0xffff0000
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT1__SHIFT 16
+#define VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT1(x) (((x) << VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT1__SHIFT) & VIVS_DE_HORI_FILTER_KERNEL_COEFFICIENT1__MASK)
+
+#define VIVS_DE_VERTI_FILTER_KERNEL(i0) (0x00002a00 + 0x4*(i0))
+#define VIVS_DE_VERTI_FILTER_KERNEL__ESIZE 0x00000004
+#define VIVS_DE_VERTI_FILTER_KERNEL__LEN 0x00000080
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT0__MASK 0x0000ffff
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT0__SHIFT 0
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT0(x) (((x) << VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT0__SHIFT) & VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT0__MASK)
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT1__MASK 0xffff0000
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT1__SHIFT 16
+#define VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT1(x) (((x) << VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT1__SHIFT) & VIVS_DE_VERTI_FILTER_KERNEL_COEFFICIENT1__MASK)
+
+#define VIVS_DE_INDEX_COLOR_TABLE32(i0) (0x00003400 + 0x4*(i0))
+#define VIVS_DE_INDEX_COLOR_TABLE32__ESIZE 0x00000004
+#define VIVS_DE_INDEX_COLOR_TABLE32__LEN 0x00000100
+
+#define VIVS_DE_BLOCK4 0x00000000
+
+#define VIVS_DE_BLOCK4_SRC_ADDRESS(i0) (0x00012800 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_ADDRESS__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ADDRESS__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_SRC_STRIDE(i0) (0x00012810 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_STRIDE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_STRIDE__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK4_SRC_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_STRIDE_STRIDE(x) (((x) << VIVS_DE_BLOCK4_SRC_STRIDE_STRIDE__SHIFT) & VIVS_DE_BLOCK4_SRC_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG(i0) (0x00012820 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_WIDTH__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_WIDTH(x) (((x) << VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_WIDTH__SHIFT) & VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_WIDTH__MASK)
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_ROTATION__MASK 0x00010000
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_ROTATION__SHIFT 16
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_ENABLE 0x00010000
+
+#define VIVS_DE_BLOCK4_SRC_CONFIG(i0) (0x00012830 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_CONFIG__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK 0x0000000f
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PE10_SOURCE_FORMAT(x) (((x) << VIVS_DE_BLOCK4_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT) & VIVS_DE_BLOCK4_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK)
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TRANSPARENCY__MASK 0x00000030
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TRANSPARENCY__SHIFT 4
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TRANSPARENCY(x) (((x) << VIVS_DE_BLOCK4_SRC_CONFIG_TRANSPARENCY__SHIFT) & VIVS_DE_BLOCK4_SRC_CONFIG_TRANSPARENCY__MASK)
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SRC_RELATIVE__MASK 0x00000040
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SRC_RELATIVE__SHIFT 6
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x00000040
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TILED__MASK 0x00000080
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TILED__SHIFT 7
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_TILED_ENABLE 0x00000080
+#define VIVS_DE_BLOCK4_SRC_CONFIG_LOCATION__MASK 0x00000100
+#define VIVS_DE_BLOCK4_SRC_CONFIG_LOCATION__SHIFT 8
+#define VIVS_DE_BLOCK4_SRC_CONFIG_LOCATION_MEMORY 0x00000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_LOCATION_STREAM 0x00000100
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK__MASK 0x00003000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK__SHIFT 12
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK_PACKED8 0x00000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK_PACKED16 0x00001000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK_PACKED32 0x00002000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_PACK_UNPACKED 0x00003000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY__MASK 0x00008000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY__SHIFT 15
+#define VIVS_DE_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x00000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x00008000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_UNK16 0x00010000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SWIZZLE__MASK 0x00300000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SWIZZLE__SHIFT 20
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SWIZZLE(x) (((x) << VIVS_DE_BLOCK4_SRC_CONFIG_SWIZZLE__SHIFT) & VIVS_DE_BLOCK4_SRC_CONFIG_SWIZZLE__MASK)
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SOURCE_FORMAT__MASK 0x1f000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SOURCE_FORMAT__SHIFT 24
+#define VIVS_DE_BLOCK4_SRC_CONFIG_SOURCE_FORMAT(x) (((x) << VIVS_DE_BLOCK4_SRC_CONFIG_SOURCE_FORMAT__SHIFT) & VIVS_DE_BLOCK4_SRC_CONFIG_SOURCE_FORMAT__MASK)
+#define VIVS_DE_BLOCK4_SRC_CONFIG_DISABLE420_L2_CACHE 0x20000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL__MASK 0xc0000000
+#define VIVS_DE_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL__SHIFT 30
+#define VIVS_DE_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL(x) (((x) << VIVS_DE_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL__SHIFT) & VIVS_DE_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL__MASK)
+
+#define VIVS_DE_BLOCK4_SRC_ORIGIN(i0) (0x00012840 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_ORIGIN__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ORIGIN__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_X__MASK 0x0000ffff
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_X__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_X(x) (((x) << VIVS_DE_BLOCK4_SRC_ORIGIN_X__SHIFT) & VIVS_DE_BLOCK4_SRC_ORIGIN_X__MASK)
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_Y__MASK 0xffff0000
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_Y__SHIFT 16
+#define VIVS_DE_BLOCK4_SRC_ORIGIN_Y(x) (((x) << VIVS_DE_BLOCK4_SRC_ORIGIN_Y__SHIFT) & VIVS_DE_BLOCK4_SRC_ORIGIN_Y__MASK)
+
+#define VIVS_DE_BLOCK4_SRC_SIZE(i0) (0x00012850 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_SIZE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_SIZE__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_SIZE_X__MASK 0x0000ffff
+#define VIVS_DE_BLOCK4_SRC_SIZE_X__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_SIZE_X(x) (((x) << VIVS_DE_BLOCK4_SRC_SIZE_X__SHIFT) & VIVS_DE_BLOCK4_SRC_SIZE_X__MASK)
+#define VIVS_DE_BLOCK4_SRC_SIZE_Y__MASK 0xffff0000
+#define VIVS_DE_BLOCK4_SRC_SIZE_Y__SHIFT 16
+#define VIVS_DE_BLOCK4_SRC_SIZE_Y(x) (((x) << VIVS_DE_BLOCK4_SRC_SIZE_Y__SHIFT) & VIVS_DE_BLOCK4_SRC_SIZE_Y__MASK)
+
+#define VIVS_DE_BLOCK4_SRC_COLOR_BG(i0) (0x00012860 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_COLOR_BG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_COLOR_BG__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_ROP(i0) (0x00012870 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ROP__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ROP__LEN 0x00000004
+#define VIVS_DE_BLOCK4_ROP_ROP_FG__MASK 0x000000ff
+#define VIVS_DE_BLOCK4_ROP_ROP_FG__SHIFT 0
+#define VIVS_DE_BLOCK4_ROP_ROP_FG(x) (((x) << VIVS_DE_BLOCK4_ROP_ROP_FG__SHIFT) & VIVS_DE_BLOCK4_ROP_ROP_FG__MASK)
+#define VIVS_DE_BLOCK4_ROP_ROP_BG__MASK 0x0000ff00
+#define VIVS_DE_BLOCK4_ROP_ROP_BG__SHIFT 8
+#define VIVS_DE_BLOCK4_ROP_ROP_BG(x) (((x) << VIVS_DE_BLOCK4_ROP_ROP_BG__SHIFT) & VIVS_DE_BLOCK4_ROP_ROP_BG__MASK)
+#define VIVS_DE_BLOCK4_ROP_TYPE__MASK 0x00300000
+#define VIVS_DE_BLOCK4_ROP_TYPE__SHIFT 20
+#define VIVS_DE_BLOCK4_ROP_TYPE_ROP2_PATTERN 0x00000000
+#define VIVS_DE_BLOCK4_ROP_TYPE_ROP2_SOURCE 0x00100000
+#define VIVS_DE_BLOCK4_ROP_TYPE_ROP3 0x00200000
+#define VIVS_DE_BLOCK4_ROP_TYPE_ROP4 0x00300000
+
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL(i0) (0x00012880 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL__LEN 0x00000004
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_ENABLE__MASK 0x00000001
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_ENABLE__SHIFT 0
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_ENABLE_OFF 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_ENABLE_ON 0x00000001
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK 0x00ff0000
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT 16
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA(x) (((x) << VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT) & VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK)
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK 0xff000000
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT 24
+#define VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA(x) (((x) << VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT) & VIVS_DE_BLOCK4_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK)
+
+#define VIVS_DE_BLOCK4_ALPHA_MODES(i0) (0x00012890 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ALPHA_MODES__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ALPHA_MODES__LEN 0x00000004
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE__MASK 0x00000001
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE__SHIFT 0
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x00000001
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE__MASK 0x00000010
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE__SHIFT 4
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x00000010
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__MASK 0x00000300
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__SHIFT 8
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x00000100
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x00000200
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__MASK 0x00003000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__SHIFT 12
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x00001000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x00002000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__MASK 0x00010000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__SHIFT 16
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_ENABLE 0x00010000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__MASK 0x00100000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__SHIFT 20
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_ENABLE 0x00100000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE__MASK 0x07000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT 24
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE(x) (((x) << VIVS_DE_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT) & VIVS_DE_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE__MASK)
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR__MASK 0x08000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR__SHIFT 27
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLE 0x08000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE__MASK 0x70000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE__SHIFT 28
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE(x) (((x) << VIVS_DE_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE__SHIFT) & VIVS_DE_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE__MASK)
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR__MASK 0x80000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR__SHIFT 31
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLE 0x80000000
+
+#define VIVS_DE_BLOCK4_ADDRESS_U(i0) (0x000128a0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ADDRESS_U__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ADDRESS_U__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_STRIDE_U(i0) (0x000128b0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_STRIDE_U__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_STRIDE_U__LEN 0x00000004
+#define VIVS_DE_BLOCK4_STRIDE_U_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK4_STRIDE_U_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK4_STRIDE_U_STRIDE(x) (((x) << VIVS_DE_BLOCK4_STRIDE_U_STRIDE__SHIFT) & VIVS_DE_BLOCK4_STRIDE_U_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK4_ADDRESS_V(i0) (0x000128c0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ADDRESS_V__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ADDRESS_V__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_STRIDE_V(i0) (0x000128d0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_STRIDE_V__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_STRIDE_V__LEN 0x00000004
+#define VIVS_DE_BLOCK4_STRIDE_V_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK4_STRIDE_V_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK4_STRIDE_V_STRIDE(x) (((x) << VIVS_DE_BLOCK4_STRIDE_V_STRIDE__SHIFT) & VIVS_DE_BLOCK4_STRIDE_V_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT(i0) (0x000128e0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT__MASK 0x0000ffff
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT(x) (((x) << VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT) & VIVS_DE_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT__MASK)
+
+#define VIVS_DE_BLOCK4_ROT_ANGLE(i0) (0x000128f0 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_ROT_ANGLE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_ROT_ANGLE__LEN 0x00000004
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC__MASK 0x00000007
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC__SHIFT 0
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC(x) (((x) << VIVS_DE_BLOCK4_ROT_ANGLE_SRC__SHIFT) & VIVS_DE_BLOCK4_ROT_ANGLE_SRC__MASK)
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST__MASK 0x00000038
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST__SHIFT 3
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST(x) (((x) << VIVS_DE_BLOCK4_ROT_ANGLE_DST__SHIFT) & VIVS_DE_BLOCK4_ROT_ANGLE_DST__MASK)
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MASK 0x00000100
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST_MASK 0x00000200
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR__MASK 0x00003000
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR__SHIFT 12
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR(x) (((x) << VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR__SHIFT) & VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR__MASK)
+#define VIVS_DE_BLOCK4_ROT_ANGLE_SRC_MIRROR_MASK 0x00008000
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR__MASK 0x00030000
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR__SHIFT 16
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR(x) (((x) << VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR__SHIFT) & VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR__MASK)
+#define VIVS_DE_BLOCK4_ROT_ANGLE_DST_MIRROR_MASK 0x00080000
+
+#define VIVS_DE_BLOCK4_GLOBAL_SRC_COLOR(i0) (0x00012900 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_GLOBAL_SRC_COLOR__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_GLOBAL_SRC_COLOR__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_GLOBAL_DEST_COLOR(i0) (0x00012910 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_GLOBAL_DEST_COLOR__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_GLOBAL_DEST_COLOR__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES(i0) (0x00012920 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES__LEN 0x00000004
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__MASK 0x00000001
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__SHIFT 0
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x00000001
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__MASK 0x00000010
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__SHIFT 4
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x00000010
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__MASK 0x00000300
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__SHIFT 8
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x00000100
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x00000200
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__MASK 0x00100000
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__SHIFT 20
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x00100000
+
+#define VIVS_DE_BLOCK4_TRANSPARENCY(i0) (0x00012930 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_TRANSPARENCY__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_TRANSPARENCY__LEN 0x00000004
+#define VIVS_DE_BLOCK4_TRANSPARENCY_SOURCE__MASK 0x00000003
+#define VIVS_DE_BLOCK4_TRANSPARENCY_SOURCE__SHIFT 0
+#define VIVS_DE_BLOCK4_TRANSPARENCY_SOURCE_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_SOURCE_MASK 0x00000001
+#define VIVS_DE_BLOCK4_TRANSPARENCY_SOURCE_KEY 0x00000002
+#define VIVS_DE_BLOCK4_TRANSPARENCY_PATTERN__MASK 0x00000030
+#define VIVS_DE_BLOCK4_TRANSPARENCY_PATTERN__SHIFT 4
+#define VIVS_DE_BLOCK4_TRANSPARENCY_PATTERN_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_PATTERN_MASK 0x00000010
+#define VIVS_DE_BLOCK4_TRANSPARENCY_PATTERN_KEY 0x00000020
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DESTINATION__MASK 0x00000300
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DESTINATION__SHIFT 8
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DESTINATION_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DESTINATION_MASK 0x00000100
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DESTINATION_KEY 0x00000200
+#define VIVS_DE_BLOCK4_TRANSPARENCY_TRANSPARENCY_MASK 0x00001000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE__MASK 0x00030000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE__SHIFT 16
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x00010000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x00020000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE__MASK 0x00300000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE__SHIFT 20
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x00100000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x00200000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE__MASK 0x03000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE__SHIFT 24
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x01000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x02000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_RESOURCE_OVERRIDE_MASK 0x10000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY__MASK 0x20000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY__SHIFT 29
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_ENABLE 0x20000000
+#define VIVS_DE_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_MASK 0x80000000
+
+#define VIVS_DE_BLOCK4_CONTROL(i0) (0x00012940 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_CONTROL__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_CONTROL__LEN 0x00000004
+#define VIVS_DE_BLOCK4_CONTROL_YUV__MASK 0x00000001
+#define VIVS_DE_BLOCK4_CONTROL_YUV__SHIFT 0
+#define VIVS_DE_BLOCK4_CONTROL_YUV_601 0x00000000
+#define VIVS_DE_BLOCK4_CONTROL_YUV_709 0x00000001
+#define VIVS_DE_BLOCK4_CONTROL_YUV_MASK 0x00000008
+#define VIVS_DE_BLOCK4_CONTROL_UV_SWIZZLE__MASK 0x00000010
+#define VIVS_DE_BLOCK4_CONTROL_UV_SWIZZLE__SHIFT 4
+#define VIVS_DE_BLOCK4_CONTROL_UV_SWIZZLE_UV 0x00000000
+#define VIVS_DE_BLOCK4_CONTROL_UV_SWIZZLE_VU 0x00000010
+#define VIVS_DE_BLOCK4_CONTROL_UV_SWIZZLE_MASK 0x00000080
+#define VIVS_DE_BLOCK4_CONTROL_YUVRGB__MASK 0x00000100
+#define VIVS_DE_BLOCK4_CONTROL_YUVRGB__SHIFT 8
+#define VIVS_DE_BLOCK4_CONTROL_YUVRGB_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_CONTROL_YUVRGB_ENABLE 0x00000100
+#define VIVS_DE_BLOCK4_CONTROL_YUVRGB_MASK 0x00000800
+
+#define VIVS_DE_BLOCK4_SRC_COLOR_KEY_HIGH(i0) (0x00012950 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_COLOR_KEY_HIGH__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_COLOR_KEY_HIGH__LEN 0x00000004
+
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG(i0) (0x00012960 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG__LEN 0x00000004
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MULTI_TILED__MASK 0x00000001
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MULTI_TILED__SHIFT 0
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_ENABLE 0x00000001
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_SUPER_TILED__MASK 0x00000008
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_SUPER_TILED__SHIFT 3
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_ENABLE 0x00000008
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MINOR_TILED__MASK 0x00000100
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MINOR_TILED__SHIFT 8
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_ENABLE 0x00000100
+
+#define VIVS_DE_BLOCK4_SRC_EX_ADDRESS(i0) (0x00012970 + 0x4*(i0))
+#define VIVS_DE_BLOCK4_SRC_EX_ADDRESS__ESIZE 0x00000004
+#define VIVS_DE_BLOCK4_SRC_EX_ADDRESS__LEN 0x00000004
+
+#define VIVS_DE_BLOCK8 0x00000000
+
+#define VIVS_DE_BLOCK8_SRC_ADDRESS(i0) (0x00012a00 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_ADDRESS__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_ADDRESS__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_SRC_STRIDE(i0) (0x00012a20 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_STRIDE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_STRIDE__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_STRIDE_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK8_SRC_STRIDE_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_STRIDE_STRIDE(x) (((x) << VIVS_DE_BLOCK8_SRC_STRIDE_STRIDE__SHIFT) & VIVS_DE_BLOCK8_SRC_STRIDE_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG(i0) (0x00012a40 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_WIDTH__MASK 0x0000ffff
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_WIDTH__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_WIDTH(x) (((x) << VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_WIDTH__SHIFT) & VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_WIDTH__MASK)
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_ROTATION__MASK 0x00010000
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_ROTATION__SHIFT 16
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_ENABLE 0x00010000
+
+#define VIVS_DE_BLOCK8_SRC_CONFIG(i0) (0x00012a60 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_CONFIG__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK 0x0000000f
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PE10_SOURCE_FORMAT(x) (((x) << VIVS_DE_BLOCK8_SRC_CONFIG_PE10_SOURCE_FORMAT__SHIFT) & VIVS_DE_BLOCK8_SRC_CONFIG_PE10_SOURCE_FORMAT__MASK)
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TRANSPARENCY__MASK 0x00000030
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TRANSPARENCY__SHIFT 4
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TRANSPARENCY(x) (((x) << VIVS_DE_BLOCK8_SRC_CONFIG_TRANSPARENCY__SHIFT) & VIVS_DE_BLOCK8_SRC_CONFIG_TRANSPARENCY__MASK)
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SRC_RELATIVE__MASK 0x00000040
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SRC_RELATIVE__SHIFT 6
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x00000040
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TILED__MASK 0x00000080
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TILED__SHIFT 7
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_TILED_ENABLE 0x00000080
+#define VIVS_DE_BLOCK8_SRC_CONFIG_LOCATION__MASK 0x00000100
+#define VIVS_DE_BLOCK8_SRC_CONFIG_LOCATION__SHIFT 8
+#define VIVS_DE_BLOCK8_SRC_CONFIG_LOCATION_MEMORY 0x00000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_LOCATION_STREAM 0x00000100
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK__MASK 0x00003000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK__SHIFT 12
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK_PACKED8 0x00000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK_PACKED16 0x00001000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK_PACKED32 0x00002000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_PACK_UNPACKED 0x00003000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY__MASK 0x00008000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY__SHIFT 15
+#define VIVS_DE_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x00000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x00008000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_UNK16 0x00010000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SWIZZLE__MASK 0x00300000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SWIZZLE__SHIFT 20
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SWIZZLE(x) (((x) << VIVS_DE_BLOCK8_SRC_CONFIG_SWIZZLE__SHIFT) & VIVS_DE_BLOCK8_SRC_CONFIG_SWIZZLE__MASK)
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SOURCE_FORMAT__MASK 0x1f000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SOURCE_FORMAT__SHIFT 24
+#define VIVS_DE_BLOCK8_SRC_CONFIG_SOURCE_FORMAT(x) (((x) << VIVS_DE_BLOCK8_SRC_CONFIG_SOURCE_FORMAT__SHIFT) & VIVS_DE_BLOCK8_SRC_CONFIG_SOURCE_FORMAT__MASK)
+#define VIVS_DE_BLOCK8_SRC_CONFIG_DISABLE420_L2_CACHE 0x20000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL__MASK 0xc0000000
+#define VIVS_DE_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL__SHIFT 30
+#define VIVS_DE_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL(x) (((x) << VIVS_DE_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL__SHIFT) & VIVS_DE_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL__MASK)
+
+#define VIVS_DE_BLOCK8_SRC_ORIGIN(i0) (0x00012a80 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_ORIGIN__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_ORIGIN__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_X__MASK 0x0000ffff
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_X__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_X(x) (((x) << VIVS_DE_BLOCK8_SRC_ORIGIN_X__SHIFT) & VIVS_DE_BLOCK8_SRC_ORIGIN_X__MASK)
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_Y__MASK 0xffff0000
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_Y__SHIFT 16
+#define VIVS_DE_BLOCK8_SRC_ORIGIN_Y(x) (((x) << VIVS_DE_BLOCK8_SRC_ORIGIN_Y__SHIFT) & VIVS_DE_BLOCK8_SRC_ORIGIN_Y__MASK)
+
+#define VIVS_DE_BLOCK8_SRC_SIZE(i0) (0x00012aa0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_SIZE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_SIZE__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_SIZE_X__MASK 0x0000ffff
+#define VIVS_DE_BLOCK8_SRC_SIZE_X__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_SIZE_X(x) (((x) << VIVS_DE_BLOCK8_SRC_SIZE_X__SHIFT) & VIVS_DE_BLOCK8_SRC_SIZE_X__MASK)
+#define VIVS_DE_BLOCK8_SRC_SIZE_Y__MASK 0xffff0000
+#define VIVS_DE_BLOCK8_SRC_SIZE_Y__SHIFT 16
+#define VIVS_DE_BLOCK8_SRC_SIZE_Y(x) (((x) << VIVS_DE_BLOCK8_SRC_SIZE_Y__SHIFT) & VIVS_DE_BLOCK8_SRC_SIZE_Y__MASK)
+
+#define VIVS_DE_BLOCK8_SRC_COLOR_BG(i0) (0x00012ac0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_COLOR_BG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_COLOR_BG__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_ROP(i0) (0x00012ae0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ROP__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ROP__LEN 0x00000008
+#define VIVS_DE_BLOCK8_ROP_ROP_FG__MASK 0x000000ff
+#define VIVS_DE_BLOCK8_ROP_ROP_FG__SHIFT 0
+#define VIVS_DE_BLOCK8_ROP_ROP_FG(x) (((x) << VIVS_DE_BLOCK8_ROP_ROP_FG__SHIFT) & VIVS_DE_BLOCK8_ROP_ROP_FG__MASK)
+#define VIVS_DE_BLOCK8_ROP_ROP_BG__MASK 0x0000ff00
+#define VIVS_DE_BLOCK8_ROP_ROP_BG__SHIFT 8
+#define VIVS_DE_BLOCK8_ROP_ROP_BG(x) (((x) << VIVS_DE_BLOCK8_ROP_ROP_BG__SHIFT) & VIVS_DE_BLOCK8_ROP_ROP_BG__MASK)
+#define VIVS_DE_BLOCK8_ROP_TYPE__MASK 0x00300000
+#define VIVS_DE_BLOCK8_ROP_TYPE__SHIFT 20
+#define VIVS_DE_BLOCK8_ROP_TYPE_ROP2_PATTERN 0x00000000
+#define VIVS_DE_BLOCK8_ROP_TYPE_ROP2_SOURCE 0x00100000
+#define VIVS_DE_BLOCK8_ROP_TYPE_ROP3 0x00200000
+#define VIVS_DE_BLOCK8_ROP_TYPE_ROP4 0x00300000
+
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL(i0) (0x00012b00 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL__LEN 0x00000008
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_ENABLE__MASK 0x00000001
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_ENABLE__SHIFT 0
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_ENABLE_OFF 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_ENABLE_ON 0x00000001
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK 0x00ff0000
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT 16
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA(x) (((x) << VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__SHIFT) & VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_SRC_ALPHA__MASK)
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK 0xff000000
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT 24
+#define VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA(x) (((x) << VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__SHIFT) & VIVS_DE_BLOCK8_ALPHA_CONTROL_PE10_GLOBAL_DST_ALPHA__MASK)
+
+#define VIVS_DE_BLOCK8_ALPHA_MODES(i0) (0x00012b20 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ALPHA_MODES__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ALPHA_MODES__LEN 0x00000008
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE__MASK 0x00000001
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE__SHIFT 0
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x00000001
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE__MASK 0x00000010
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE__SHIFT 4
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x00000010
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__MASK 0x00000300
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE__SHIFT 8
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x00000100
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x00000200
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__MASK 0x00003000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE__SHIFT 12
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x00001000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x00002000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__MASK 0x00010000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY__SHIFT 16
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_SRC_COLOR_MULTIPLY_ENABLE 0x00010000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__MASK 0x00100000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY__SHIFT 20
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_PE10_DST_COLOR_MULTIPLY_ENABLE 0x00100000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE__MASK 0x07000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT 24
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE(x) (((x) << VIVS_DE_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE__SHIFT) & VIVS_DE_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE__MASK)
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR__MASK 0x08000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR__SHIFT 27
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLE 0x08000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE__MASK 0x70000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE__SHIFT 28
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE(x) (((x) << VIVS_DE_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE__SHIFT) & VIVS_DE_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE__MASK)
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR__MASK 0x80000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR__SHIFT 31
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLE 0x80000000
+
+#define VIVS_DE_BLOCK8_ADDRESS_U(i0) (0x00012b40 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ADDRESS_U__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ADDRESS_U__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_STRIDE_U(i0) (0x00012b60 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_STRIDE_U__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_STRIDE_U__LEN 0x00000008
+#define VIVS_DE_BLOCK8_STRIDE_U_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK8_STRIDE_U_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK8_STRIDE_U_STRIDE(x) (((x) << VIVS_DE_BLOCK8_STRIDE_U_STRIDE__SHIFT) & VIVS_DE_BLOCK8_STRIDE_U_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK8_ADDRESS_V(i0) (0x00012b80 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ADDRESS_V__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ADDRESS_V__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_STRIDE_V(i0) (0x00012ba0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_STRIDE_V__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_STRIDE_V__LEN 0x00000008
+#define VIVS_DE_BLOCK8_STRIDE_V_STRIDE__MASK 0x0003ffff
+#define VIVS_DE_BLOCK8_STRIDE_V_STRIDE__SHIFT 0
+#define VIVS_DE_BLOCK8_STRIDE_V_STRIDE(x) (((x) << VIVS_DE_BLOCK8_STRIDE_V_STRIDE__SHIFT) & VIVS_DE_BLOCK8_STRIDE_V_STRIDE__MASK)
+
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT(i0) (0x00012bc0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT__MASK 0x0000ffff
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT(x) (((x) << VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT__SHIFT) & VIVS_DE_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT__MASK)
+
+#define VIVS_DE_BLOCK8_ROT_ANGLE(i0) (0x00012be0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_ROT_ANGLE__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_ROT_ANGLE__LEN 0x00000008
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC__MASK 0x00000007
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC__SHIFT 0
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC(x) (((x) << VIVS_DE_BLOCK8_ROT_ANGLE_SRC__SHIFT) & VIVS_DE_BLOCK8_ROT_ANGLE_SRC__MASK)
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST__MASK 0x00000038
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST__SHIFT 3
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST(x) (((x) << VIVS_DE_BLOCK8_ROT_ANGLE_DST__SHIFT) & VIVS_DE_BLOCK8_ROT_ANGLE_DST__MASK)
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MASK 0x00000100
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST_MASK 0x00000200
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR__MASK 0x00003000
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR__SHIFT 12
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR(x) (((x) << VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR__SHIFT) & VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR__MASK)
+#define VIVS_DE_BLOCK8_ROT_ANGLE_SRC_MIRROR_MASK 0x00008000
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR__MASK 0x00030000
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR__SHIFT 16
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR(x) (((x) << VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR__SHIFT) & VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR__MASK)
+#define VIVS_DE_BLOCK8_ROT_ANGLE_DST_MIRROR_MASK 0x00080000
+
+#define VIVS_DE_BLOCK8_GLOBAL_SRC_COLOR(i0) (0x00012c00 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_GLOBAL_SRC_COLOR__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_GLOBAL_SRC_COLOR__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_GLOBAL_DEST_COLOR(i0) (0x00012c20 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_GLOBAL_DEST_COLOR__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_GLOBAL_DEST_COLOR__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES(i0) (0x00012c40 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES__LEN 0x00000008
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__MASK 0x00000001
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY__SHIFT 0
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x00000001
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__MASK 0x00000010
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY__SHIFT 4
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x00000010
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__MASK 0x00000300
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY__SHIFT 8
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x00000100
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x00000200
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__MASK 0x00100000
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY__SHIFT 20
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x00100000
+
+#define VIVS_DE_BLOCK8_TRANSPARENCY(i0) (0x00012c60 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_TRANSPARENCY__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_TRANSPARENCY__LEN 0x00000008
+#define VIVS_DE_BLOCK8_TRANSPARENCY_SOURCE__MASK 0x00000003
+#define VIVS_DE_BLOCK8_TRANSPARENCY_SOURCE__SHIFT 0
+#define VIVS_DE_BLOCK8_TRANSPARENCY_SOURCE_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_SOURCE_MASK 0x00000001
+#define VIVS_DE_BLOCK8_TRANSPARENCY_SOURCE_KEY 0x00000002
+#define VIVS_DE_BLOCK8_TRANSPARENCY_PATTERN__MASK 0x00000030
+#define VIVS_DE_BLOCK8_TRANSPARENCY_PATTERN__SHIFT 4
+#define VIVS_DE_BLOCK8_TRANSPARENCY_PATTERN_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_PATTERN_MASK 0x00000010
+#define VIVS_DE_BLOCK8_TRANSPARENCY_PATTERN_KEY 0x00000020
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DESTINATION__MASK 0x00000300
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DESTINATION__SHIFT 8
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DESTINATION_OPAQUE 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DESTINATION_MASK 0x00000100
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DESTINATION_KEY 0x00000200
+#define VIVS_DE_BLOCK8_TRANSPARENCY_TRANSPARENCY_MASK 0x00001000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE__MASK 0x00030000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE__SHIFT 16
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x00010000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x00020000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE__MASK 0x00300000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE__SHIFT 20
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x00100000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x00200000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE__MASK 0x03000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE__SHIFT 24
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x01000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x02000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_RESOURCE_OVERRIDE_MASK 0x10000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY__MASK 0x20000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY__SHIFT 29
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_ENABLE 0x20000000
+#define VIVS_DE_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_MASK 0x80000000
+
+#define VIVS_DE_BLOCK8_CONTROL(i0) (0x00012c80 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_CONTROL__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_CONTROL__LEN 0x00000008
+#define VIVS_DE_BLOCK8_CONTROL_YUV__MASK 0x00000001
+#define VIVS_DE_BLOCK8_CONTROL_YUV__SHIFT 0
+#define VIVS_DE_BLOCK8_CONTROL_YUV_601 0x00000000
+#define VIVS_DE_BLOCK8_CONTROL_YUV_709 0x00000001
+#define VIVS_DE_BLOCK8_CONTROL_YUV_MASK 0x00000008
+#define VIVS_DE_BLOCK8_CONTROL_UV_SWIZZLE__MASK 0x00000010
+#define VIVS_DE_BLOCK8_CONTROL_UV_SWIZZLE__SHIFT 4
+#define VIVS_DE_BLOCK8_CONTROL_UV_SWIZZLE_UV 0x00000000
+#define VIVS_DE_BLOCK8_CONTROL_UV_SWIZZLE_VU 0x00000010
+#define VIVS_DE_BLOCK8_CONTROL_UV_SWIZZLE_MASK 0x00000080
+#define VIVS_DE_BLOCK8_CONTROL_YUVRGB__MASK 0x00000100
+#define VIVS_DE_BLOCK8_CONTROL_YUVRGB__SHIFT 8
+#define VIVS_DE_BLOCK8_CONTROL_YUVRGB_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_CONTROL_YUVRGB_ENABLE 0x00000100
+#define VIVS_DE_BLOCK8_CONTROL_YUVRGB_MASK 0x00000800
+
+#define VIVS_DE_BLOCK8_SRC_COLOR_KEY_HIGH(i0) (0x00012ca0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_COLOR_KEY_HIGH__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_COLOR_KEY_HIGH__LEN 0x00000008
+
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG(i0) (0x00012cc0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG__LEN 0x00000008
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MULTI_TILED__MASK 0x00000001
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MULTI_TILED__SHIFT 0
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_ENABLE 0x00000001
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_SUPER_TILED__MASK 0x00000008
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_SUPER_TILED__SHIFT 3
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_ENABLE 0x00000008
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MINOR_TILED__MASK 0x00000100
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MINOR_TILED__SHIFT 8
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_DISABLE 0x00000000
+#define VIVS_DE_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_ENABLE 0x00000100
+
+#define VIVS_DE_BLOCK8_SRC_EX_ADDRESS(i0) (0x00012ce0 + 0x4*(i0))
+#define VIVS_DE_BLOCK8_SRC_EX_ADDRESS__ESIZE 0x00000004
+#define VIVS_DE_BLOCK8_SRC_EX_ADDRESS__LEN 0x00000008
+
+
+#endif /* STATE_2D_XML */
diff --git a/tests/etnaviv/write_bmp.c b/tests/etnaviv/write_bmp.c
new file mode 100644
index 0000000..f7b6bc6
--- /dev/null
+++ b/tests/etnaviv/write_bmp.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011 Luc Verhaegen <libv@codethink.co.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+/*
+ * Quick 'n Dirty bitmap dumper.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "write_bmp.h"
+
+#define FILENAME_SIZE 1024
+
+struct bmp_header {
+ unsigned short magic;
+ unsigned int size;
+ unsigned int unused;
+ unsigned int start;
+} __attribute__((__packed__));
+
+struct dib_header {
+ unsigned int size;
+ unsigned int width;
+ unsigned int height;
+ unsigned short planes;
+ unsigned short bpp;
+ unsigned int compression;
+ unsigned int data_size;
+ unsigned int h_res;
+ unsigned int v_res;
+ unsigned int colours;
+ unsigned int important_colours;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+ unsigned int alpha_mask;
+ unsigned int colour_space;
+ unsigned int unused[12];
+} __attribute__((__packed__));
+
+static void
+bmp_header_write(int fd, int width, int height, int bgra, int noflip, int alpha)
+{
+ struct bmp_header bmp_header = {
+ .magic = 0x4d42,
+ .size = (width * height * 4) +
+ sizeof(struct bmp_header) + sizeof(struct dib_header),
+ .start = sizeof(struct bmp_header) + sizeof(struct dib_header),
+ };
+ struct dib_header dib_header = {
+ .size = sizeof(struct dib_header),
+ .width = width,
+ .height = noflip ? -height : height,
+ .planes = 1,
+ .bpp = 32,
+ .compression = 3,
+ .data_size = 4 * width * height,
+ .h_res = 0xB13,
+ .v_res = 0xB13,
+ .colours = 0,
+ .important_colours = 0,
+ .red_mask = 0x000000FF,
+ .green_mask = 0x0000FF00,
+ .blue_mask = 0x00FF0000,
+ .alpha_mask = alpha ? 0xFF000000 : 0x00000000,
+ .colour_space = 0x57696E20,
+ };
+
+ if (bgra) {
+ dib_header.red_mask = 0x00FF0000;
+ dib_header.blue_mask = 0x000000FF;
+ }
+
+ write(fd, &bmp_header, sizeof(struct bmp_header));
+ write(fd, &dib_header, sizeof(struct dib_header));
+}
+
+void
+bmp_dump32(char *buffer, unsigned width, unsigned height, bool bgra, const char *filename)
+{
+ int fd;
+
+ fd = open(filename, O_WRONLY| O_TRUNC | O_CREAT, 0666);
+ if (fd == -1) {
+ printf("Failed to open %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ bmp_header_write(fd, width, height, bgra, false, true);
+
+ write(fd, buffer, width * height * 4);
+}
+
+void
+bmp_dump32_noflip(char *buffer, unsigned width, unsigned height, bool bgra, const char *filename)
+{
+ int fd;
+
+ fd = open(filename, O_WRONLY| O_TRUNC | O_CREAT, 0666);
+ if (fd == -1) {
+ printf("Failed to open %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ bmp_header_write(fd, width, height, bgra, true, true);
+
+ write(fd, buffer, width * height * 4);
+}
+
+void
+bmp_dump32_ex(char *buffer, unsigned width, unsigned height, bool flip, bool bgra, bool alpha, const char *filename)
+{
+ int fd;
+
+ fd = open(filename, O_WRONLY| O_TRUNC | O_CREAT, 0666);
+ if (fd == -1) {
+ printf("Failed to open %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ bmp_header_write(fd, width, height, bgra, flip, alpha);
+
+ write(fd, buffer, width * height * 4);
+}
diff --git a/tests/etnaviv/write_bmp.h b/tests/etnaviv/write_bmp.h
new file mode 100644
index 0000000..667fa87
--- /dev/null
+++ b/tests/etnaviv/write_bmp.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Luc Verhaegen <libv@codethink.co.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef BMP_DUMP_H
+#define BMP_DUMP_H 1
+#include <stdbool.h>
+/* write 32-bit image (y axis upwards) */
+void bmp_dump32(char *buffer, unsigned width, unsigned height, bool bgra, const char *filename);
+/* write 32-bit image (y axis downwards) */
+void bmp_dump32_noflip(char *buffer, unsigned width, unsigned height, bool bgra, const char *filename);
+/* write 32-bit image */
+void bmp_dump32_ex(char *buffer, unsigned width, unsigned height, bool flip, bool bgra, bool alpha, const char *filename);
+
+#endif /* BMP_DUMP_H */
diff --git a/tests/exynos/exynos_fimg2d_event.c b/tests/exynos/exynos_fimg2d_event.c
new file mode 100644
index 0000000..353e087
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_event.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2015 - Tobias Jakobi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <poll.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <getopt.h>
+
+#include <pthread.h>
+
+#include <xf86drm.h>
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+struct g2d_job {
+ unsigned int id;
+ unsigned int busy;
+};
+
+struct exynos_evhandler {
+ struct pollfd fds;
+ struct exynos_event_context evctx;
+};
+
+struct threaddata {
+ unsigned int stop;
+ struct exynos_device *dev;
+ struct exynos_evhandler evhandler;
+};
+
+static void g2d_event_handler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
+ unsigned int tv_usec, void *user_data)
+{
+ struct g2d_job *job = user_data;
+
+ fprintf(stderr, "info: g2d job (id = %u, cmdlist number = %u) finished!\n",
+ job->id, cmdlist_no);
+
+ job->busy = 0;
+}
+
+static void setup_g2d_event_handler(struct exynos_evhandler *evhandler, int fd)
+{
+ evhandler->fds.fd = fd;
+ evhandler->fds.events = POLLIN;
+ evhandler->evctx.base.version = 2;
+ evhandler->evctx.version = 1;
+ evhandler->evctx.g2d_event_handler = g2d_event_handler;
+}
+
+static void* threadfunc(void *arg) {
+ const int timeout = 0;
+ struct threaddata *data;
+
+ data = arg;
+
+ while (1) {
+ if (data->stop) break;
+
+ usleep(500);
+
+ data->evhandler.fds.revents = 0;
+
+ if (poll(&data->evhandler.fds, 1, timeout) < 0)
+ continue;
+
+ if (data->evhandler.fds.revents & (POLLHUP | POLLERR))
+ continue;
+
+ if (data->evhandler.fds.revents & POLLIN)
+ exynos_handle_event(data->dev, &data->evhandler.evctx);
+ }
+
+ pthread_exit(0);
+}
+
+/*
+ * We need to wait until all G2D jobs are finished, otherwise we
+ * potentially remove a BO which the engine still operates on.
+ * This results in the following kernel message:
+ * [drm:exynos_drm_gem_put_dma_addr] *ERROR* failed to lookup gem object.
+ * Also any subsequent BO allocations fail then with:
+ * [drm:exynos_drm_alloc_buf] *ERROR* failed to allocate buffer.
+ */
+static void wait_all_jobs(struct g2d_job* jobs, unsigned num_jobs)
+{
+ unsigned i;
+
+ for (i = 0; i < num_jobs; ++i) {
+ while (jobs[i].busy)
+ usleep(500);
+ }
+
+}
+
+static struct g2d_job* free_job(struct g2d_job* jobs, unsigned num_jobs)
+{
+ unsigned i;
+
+ for (i = 0; i < num_jobs; ++i) {
+ if (jobs[i].busy == 0)
+ return &jobs[i];
+ }
+
+ return NULL;
+}
+
+static int g2d_work(struct g2d_context *ctx, struct g2d_image *img,
+ unsigned num_jobs, unsigned iterations)
+{
+ struct g2d_job *jobs = calloc(num_jobs, sizeof(struct g2d_job));
+ int ret;
+ unsigned i;
+
+ /* setup job ids */
+ for (i = 0; i < num_jobs; ++i)
+ jobs[i].id = i;
+
+ for (i = 0; i < iterations; ++i) {
+ unsigned x, y, w, h;
+
+ struct g2d_job *j = NULL;
+
+ while (1) {
+ j = free_job(jobs, num_jobs);
+
+ if (j)
+ break;
+ else
+ usleep(500);
+ }
+
+ x = rand() % img->width;
+ y = rand() % img->height;
+
+ if (x == (img->width - 1))
+ x -= 1;
+ if (y == (img->height - 1))
+ y -= 1;
+
+ w = rand() % (img->width - x);
+ h = rand() % (img->height - y);
+
+ if (w == 0) w = 1;
+ if (h == 0) h = 1;
+
+ img->color = rand();
+
+ j->busy = 1;
+ g2d_config_event(ctx, j);
+
+ ret = g2d_solid_fill(ctx, img, x, y, w, h);
+
+ if (ret == 0)
+ g2d_exec(ctx);
+
+ if (ret != 0) {
+ fprintf(stderr, "error: iteration %u (x = %u, x = %u, x = %u, x = %u) failed\n",
+ i, x, y, w, h);
+ break;
+ }
+ }
+
+ wait_all_jobs(jobs, num_jobs);
+ free(jobs);
+
+ return 0;
+}
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s [-ijwh]\n\n", name);
+
+ fprintf(stderr, "\t-i <number of iterations>\n");
+ fprintf(stderr, "\t-j <number of G2D jobs> (default = 4)\n\n");
+
+ fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
+ fprintf(stderr, "\t-h <buffer height> (default = 4096)\n");
+
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ int fd, ret, c, parsefail;
+
+ pthread_t event_thread;
+ struct threaddata event_data = {0};
+
+ struct exynos_device *dev;
+ struct g2d_context *ctx;
+ struct exynos_bo *bo;
+
+ struct g2d_image img = {0};
+
+ unsigned int iters = 0, njobs = 4;
+ unsigned int bufw = 4096, bufh = 4096;
+
+ ret = 0;
+ parsefail = 0;
+
+ while ((c = getopt(argc, argv, "i:j:w:h:")) != -1) {
+ switch (c) {
+ case 'i':
+ if (sscanf(optarg, "%u", &iters) != 1)
+ parsefail = 1;
+ break;
+ case 'j':
+ if (sscanf(optarg, "%u", &njobs) != 1)
+ parsefail = 1;
+ break;
+ case 'w':
+ if (sscanf(optarg, "%u", &bufw) != 1)
+ parsefail = 1;
+ break;
+ case 'h':
+ if (sscanf(optarg, "%u", &bufh) != 1)
+ parsefail = 1;
+ break;
+ default:
+ parsefail = 1;
+ break;
+ }
+ }
+
+ if (parsefail || (argc == 1) || (iters == 0))
+ usage(argv[0]);
+
+ if (bufw > 4096 || bufh > 4096) {
+ fprintf(stderr, "error: buffer width/height should be less than 4096.\n");
+ ret = -1;
+
+ goto out;
+ }
+
+ if (bufw == 0 || bufh == 0) {
+ fprintf(stderr, "error: buffer width/height should be non-zero.\n");
+ ret = -1;
+
+ goto out;
+ }
+
+ fd = drmOpen("exynos", NULL);
+ if (fd < 0) {
+ fprintf(stderr, "error: failed to open drm\n");
+ ret = -1;
+
+ goto out;
+ }
+
+ dev = exynos_device_create(fd);
+ if (dev == NULL) {
+ fprintf(stderr, "error: failed to create device\n");
+ ret = -2;
+
+ goto fail;
+ }
+
+ ctx = g2d_init(fd);
+ if (ctx == NULL) {
+ fprintf(stderr, "error: failed to init G2D\n");
+ ret = -3;
+
+ goto g2d_fail;
+ }
+
+ bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
+ if (bo == NULL) {
+ fprintf(stderr, "error: failed to create bo\n");
+ ret = -4;
+
+ goto bo_fail;
+ }
+
+ /* setup g2d image object */
+ img.width = bufw;
+ img.height = bufh;
+ img.stride = bufw * 4;
+ img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ img.buf_type = G2D_IMGBUF_GEM;
+ img.bo[0] = bo->handle;
+
+ event_data.dev = dev;
+ setup_g2d_event_handler(&event_data.evhandler, fd);
+
+ pthread_create(&event_thread, NULL, threadfunc, &event_data);
+
+ ret = g2d_work(ctx, &img, njobs, iters);
+ if (ret != 0)
+ fprintf(stderr, "error: g2d_work failed\n");
+
+ event_data.stop = 1;
+ pthread_join(event_thread, NULL);
+
+ exynos_bo_destroy(bo);
+
+bo_fail:
+ g2d_fini(ctx);
+
+g2d_fail:
+ exynos_device_destroy(dev);
+
+fail:
+ drmClose(fd);
+
+out:
+ return ret;
+}
diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c
new file mode 100644
index 0000000..97691a7
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_perf.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2015 - Tobias Jakobi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+static int output_mathematica = 0;
+
+static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
+ unsigned buf_width, unsigned buf_height, unsigned iterations)
+{
+ struct timespec tspec = { 0 };
+ struct g2d_image img = { 0 };
+
+ unsigned long long g2d_time;
+ unsigned i;
+ int ret = 0;
+
+ img.width = buf_width;
+ img.height = buf_height;
+ img.stride = buf_width * 4;
+ img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ img.buf_type = G2D_IMGBUF_GEM;
+ img.bo[0] = bo->handle;
+
+ srand(time(NULL));
+
+ printf("starting simple G2D performance test\n");
+ printf("buffer width = %u, buffer height = %u, iterations = %u\n",
+ buf_width, buf_height, iterations);
+
+ if (output_mathematica)
+ putchar('{');
+
+ for (i = 0; i < iterations; ++i) {
+ unsigned x, y, w, h;
+
+ x = rand() % buf_width;
+ y = rand() % buf_height;
+
+ if (x == (buf_width - 1))
+ x -= 1;
+ if (y == (buf_height - 1))
+ y -= 1;
+
+ w = rand() % (buf_width - x);
+ h = rand() % (buf_height - y);
+
+ if (w == 0) w = 1;
+ if (h == 0) h = 1;
+
+ img.color = rand();
+
+ ret = g2d_solid_fill(ctx, &img, x, y, w, h);
+
+ clock_gettime(CLOCK_MONOTONIC, &tspec);
+
+ if (ret == 0)
+ ret = g2d_exec(ctx);
+
+ if (ret != 0) {
+ fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n",
+ i, x, y, w, h);
+ break;
+ } else {
+ struct timespec end = { 0 };
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
+ g2d_time += (end.tv_nsec - tspec.tv_nsec);
+
+ if (output_mathematica) {
+ if (i != 0) putchar(',');
+ printf("{%u,%llu}", w * h, g2d_time);
+ } else {
+ printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time);
+ }
+ }
+ }
+
+ if (output_mathematica)
+ printf("}\n");
+
+ return ret;
+}
+
+static int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx,
+ unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch)
+{
+ struct timespec tspec = { 0 };
+ struct g2d_image *images;
+
+ unsigned long long g2d_time;
+ unsigned i, j;
+ int ret = 0;
+
+ images = calloc(batch, sizeof(struct g2d_image));
+ if (images == NULL) {
+ fprintf(stderr, "error: failed to allocate G2D images.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < batch; ++i) {
+ images[i].width = buf_width;
+ images[i].height = buf_height;
+ images[i].stride = buf_width * 4;
+ images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ images[i].buf_type = G2D_IMGBUF_GEM;
+ images[i].bo[0] = bo->handle;
+ }
+
+ srand(time(NULL));
+
+ printf("starting multi G2D performance test (batch size = %u)\n", batch);
+ printf("buffer width = %u, buffer height = %u, iterations = %u\n",
+ buf_width, buf_height, iterations);
+
+ if (output_mathematica)
+ putchar('{');
+
+ for (i = 0; i < iterations; ++i) {
+ unsigned num_pixels = 0;
+
+ for (j = 0; j < batch; ++j) {
+ unsigned x, y, w, h;
+
+ x = rand() % buf_width;
+ y = rand() % buf_height;
+
+ if (x == (buf_width - 1))
+ x -= 1;
+ if (y == (buf_height - 1))
+ y -= 1;
+
+ w = rand() % (buf_width - x);
+ h = rand() % (buf_height - y);
+
+ if (w == 0) w = 1;
+ if (h == 0) h = 1;
+
+ images[j].color = rand();
+
+ num_pixels += w * h;
+
+ ret = g2d_solid_fill(ctx, &images[j], x, y, w, h);
+ if (ret != 0)
+ break;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &tspec);
+
+ if (ret == 0)
+ ret = g2d_exec(ctx);
+
+ if (ret != 0) {
+ fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels);
+ break;
+ } else {
+ struct timespec end = { 0 };
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
+ g2d_time += (end.tv_nsec - tspec.tv_nsec);
+
+ if (output_mathematica) {
+ if (i != 0) putchar(',');
+ printf("{%u,%llu}", num_pixels, g2d_time);
+ } else {
+ printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time);
+ }
+ }
+ }
+
+ if (output_mathematica)
+ printf("}\n");
+
+ free(images);
+
+ return ret;
+}
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s [-ibwh]\n\n", name);
+
+ fprintf(stderr, "\t-i <number of iterations>\n");
+ fprintf(stderr, "\t-b <size of a batch> (default = 3)\n\n");
+
+ fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
+ fprintf(stderr, "\t-h <buffer height> (default = 4096)\n\n");
+
+ fprintf(stderr, "\t-M <enable Mathematica styled output>\n");
+
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ int fd, ret, c, parsefail;
+
+ struct exynos_device *dev;
+ struct g2d_context *ctx;
+ struct exynos_bo *bo;
+
+ unsigned int iters = 0, batch = 3;
+ unsigned int bufw = 4096, bufh = 4096;
+
+ ret = 0;
+ parsefail = 0;
+
+ while ((c = getopt(argc, argv, "i:b:w:h:M")) != -1) {
+ switch (c) {
+ case 'i':
+ if (sscanf(optarg, "%u", &iters) != 1)
+ parsefail = 1;
+ break;
+ case 'b':
+ if (sscanf(optarg, "%u", &batch) != 1)
+ parsefail = 1;
+ break;
+ case 'w':
+ if (sscanf(optarg, "%u", &bufw) != 1)
+ parsefail = 1;
+ break;
+ case 'h':
+ if (sscanf(optarg, "%u", &bufh) != 1)
+ parsefail = 1;
+ break;
+ case 'M':
+ output_mathematica = 1;
+ break;
+ default:
+ parsefail = 1;
+ break;
+ }
+ }
+
+ if (parsefail || (argc == 1) || (iters == 0))
+ usage(argv[0]);
+
+ if (bufw < 2 || bufw > 4096 || bufh < 2 || bufh > 4096) {
+ fprintf(stderr, "error: buffer width/height should be in the range 2 to 4096.\n");
+ ret = -1;
+
+ goto out;
+ }
+
+ fd = drmOpen("exynos", NULL);
+ if (fd < 0) {
+ fprintf(stderr, "error: failed to open drm\n");
+ ret = -1;
+
+ goto out;
+ }
+
+ dev = exynos_device_create(fd);
+ if (dev == NULL) {
+ fprintf(stderr, "error: failed to create device\n");
+ ret = -2;
+
+ goto fail;
+ }
+
+ ctx = g2d_init(fd);
+ if (ctx == NULL) {
+ fprintf(stderr, "error: failed to init G2D\n");
+ ret = -3;
+
+ goto g2d_fail;
+ }
+
+ bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
+ if (bo == NULL) {
+ fprintf(stderr, "error: failed to create bo\n");
+ ret = -4;
+
+ goto bo_fail;
+ }
+
+ ret = fimg2d_perf_simple(bo, ctx, bufw, bufh, iters);
+
+ if (ret == 0)
+ ret = fimg2d_perf_multi(bo, ctx, bufw, bufh, iters, batch);
+
+ exynos_bo_destroy(bo);
+
+bo_fail:
+ g2d_fini(ctx);
+
+g2d_fail:
+ exynos_device_destroy(dev);
+
+fail:
+ drmClose(fd);
+
+out:
+ return ret;
+}
diff --git a/tests/exynos/exynos_fimg2d_test.c b/tests/exynos/exynos_fimg2d_test.c
new file mode 100644
index 0000000..d85e2f6
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_test.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <linux/stddef.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+#define DRM_MODULE_NAME "exynos"
+
+static unsigned int screen_width, screen_height;
+
+struct connector {
+ uint32_t id;
+ char mode_str[64];
+ drmModeModeInfo *mode;
+ drmModeEncoder *encoder;
+ int crtc;
+};
+
+static void connector_find_mode(int fd, struct connector *c,
+ drmModeRes *resources)
+{
+ drmModeConnector *connector;
+ int i, j;
+
+ /* First, find the connector & mode */
+ c->mode = NULL;
+ for (i = 0; i < resources->count_connectors; i++) {
+ connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+ if (!connector) {
+ fprintf(stderr, "could not get connector %i: %s\n",
+ resources->connectors[i], strerror(errno));
+ continue;
+ }
+
+ if (!connector->count_modes) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ if (connector->connector_id != c->id) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ for (j = 0; j < connector->count_modes; j++) {
+ c->mode = &connector->modes[j];
+ if (!strcmp(c->mode->name, c->mode_str))
+ break;
+ }
+
+ /* Found it, break out */
+ if (c->mode)
+ break;
+
+ drmModeFreeConnector(connector);
+ }
+
+ if (!c->mode) {
+ fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
+ return;
+ }
+
+ /* Now get the encoder */
+ for (i = 0; i < resources->count_encoders; i++) {
+ c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+ if (!c->encoder) {
+ fprintf(stderr, "could not get encoder %i: %s\n",
+ resources->encoders[i], strerror(errno));
+ continue;
+ }
+
+ if (c->encoder->encoder_id == connector->encoder_id)
+ break;
+
+ drmModeFreeEncoder(c->encoder);
+ }
+
+ if (c->crtc == -1)
+ c->crtc = c->encoder->crtc_id;
+}
+
+static int drm_set_crtc(struct exynos_device *dev, struct connector *c,
+ unsigned int fb_id)
+{
+ int ret;
+
+ ret = drmModeSetCrtc(dev->fd, c->crtc,
+ fb_id, 0, 0, &c->id, 1, c->mode);
+ if (ret)
+ drmMsg("failed to set mode: %s\n", strerror(errno));
+
+ return ret;
+}
+
+static struct exynos_bo *exynos_create_buffer(struct exynos_device *dev,
+ unsigned long size,
+ unsigned int flags)
+{
+ struct exynos_bo *bo;
+
+ bo = exynos_bo_create(dev, size, flags);
+ if (!bo)
+ return bo;
+
+ if (!exynos_bo_map(bo)) {
+ exynos_bo_destroy(bo);
+ return NULL;
+ }
+
+ return bo;
+}
+
+/* Allocate buffer and fill it with checkerboard pattern, where the tiles *
+ * have a random color. The caller has to free the buffer. */
+static void *create_checkerboard_pattern(unsigned int num_tiles_x,
+ unsigned int num_tiles_y, unsigned int tile_size)
+{
+ unsigned int *buf;
+ unsigned int x, y, i, j;
+ const unsigned int stride = num_tiles_x * tile_size;
+
+ if (posix_memalign((void*)&buf, 64, num_tiles_y * tile_size * stride * 4) != 0)
+ return NULL;
+
+ for (x = 0; x < num_tiles_x; ++x) {
+ for (y = 0; y < num_tiles_y; ++y) {
+ const unsigned int color = 0xff000000 + (random() & 0xffffff);
+
+ for (i = 0; i < tile_size; ++i) {
+ for (j = 0; j < tile_size; ++j) {
+ buf[x * tile_size + y * stride * tile_size + i + j * stride] = color;
+ }
+ }
+ }
+ }
+
+ return buf;
+}
+
+static void exynos_destroy_buffer(struct exynos_bo *bo)
+{
+ exynos_bo_destroy(bo);
+}
+
+static void wait_for_user_input(int last)
+{
+ printf("press <ENTER> to %s\n", last ? "exit test application" :
+ "skip to next test");
+
+ getchar();
+}
+
+static int g2d_solid_fill_test(struct exynos_device *dev, struct exynos_bo *dst)
+{
+ struct g2d_context *ctx;
+ struct g2d_image img = {0};
+ unsigned int count, img_w, img_h;
+ int ret = 0;
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ img.bo[0] = dst->handle;
+
+ printf("solid fill test.\n");
+
+ srand(time(NULL));
+ img_w = screen_width;
+ img_h = screen_height;
+
+ for (count = 0; count < 2; count++) {
+ unsigned int x, y, w, h;
+
+ x = rand() % (img_w / 2);
+ y = rand() % (img_h / 2);
+ w = rand() % (img_w - x);
+ h = rand() % (img_h - y);
+
+ img.width = img_w;
+ img.height = img_h;
+ img.stride = img.width * 4;
+ img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ img.color = 0xff000000 + (random() & 0xffffff);
+
+ ret = g2d_solid_fill(ctx, &img, x, y, w, h);
+ if (ret < 0)
+ goto err_fini;
+
+ ret = g2d_exec(ctx);
+ if (ret < 0)
+ break;
+ }
+
+err_fini:
+ g2d_fini(ctx);
+
+ return ret;
+}
+
+static int g2d_copy_test(struct exynos_device *dev, struct exynos_bo *src,
+ struct exynos_bo *dst,
+ enum e_g2d_buf_type type)
+{
+ struct g2d_context *ctx;
+ struct g2d_image src_img = {0}, dst_img = {0};
+ unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
+ unsigned long userptr, size;
+ int ret;
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ dst_img.bo[0] = dst->handle;
+
+ src_x = 0;
+ src_y = 0;
+ dst_x = 0;
+ dst_y = 0;
+ img_w = screen_width;
+ img_h = screen_height;
+
+ switch (type) {
+ case G2D_IMGBUF_GEM:
+ src_img.bo[0] = src->handle;
+ break;
+ case G2D_IMGBUF_USERPTR:
+ size = img_w * img_h * 4;
+
+ userptr = (unsigned long)malloc(size);
+ if (!userptr) {
+ fprintf(stderr, "failed to allocate userptr.\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ src_img.user_ptr[0].userptr = userptr;
+ src_img.user_ptr[0].size = size;
+ break;
+ case G2D_IMGBUF_COLOR:
+ default:
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ printf("copy test with %s.\n",
+ type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+ src_img.width = img_w;
+ src_img.height = img_h;
+ src_img.stride = src_img.width * 4;
+ src_img.buf_type = type;
+ src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ src_img.color = 0xffff0000;
+ ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ dst_img.width = img_w;
+ dst_img.height = img_h;
+ dst_img.stride = dst_img.width * 4;
+ dst_img.buf_type = G2D_IMGBUF_GEM;
+ dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+
+ ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y,
+ img_w - 4, img_h - 4);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ g2d_exec(ctx);
+
+err_free_userptr:
+ if (type == G2D_IMGBUF_USERPTR)
+ if (userptr)
+ free((void *)userptr);
+
+fail:
+ g2d_fini(ctx);
+
+ return ret;
+}
+
+static int g2d_move_test(struct exynos_device *dev,
+ struct exynos_bo *tmp,
+ struct exynos_bo *buf,
+ enum e_g2d_buf_type type)
+{
+ struct g2d_context *ctx;
+ struct g2d_image img = {0}, tmp_img = {0};
+ unsigned int img_w, img_h, count;
+ int cur_x, cur_y;
+ void *checkerboard;
+ int ret;
+
+ static const struct g2d_step {
+ int x, y;
+ } steps[] = {
+ { 1, 0}, { 0, 1},
+ {-1, 0}, { 0, -1},
+ { 1, 1}, {-1, -1},
+ { 1, -1}, {-1, 1},
+ { 2, 1}, { 1, 2},
+ {-2, -1}, {-1, -2},
+ { 2, -1}, { 1, -2},
+ {-2, 1}, {-1, 2}
+ };
+ static const unsigned int num_steps =
+ sizeof(steps) / sizeof(struct g2d_step);
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ img.bo[0] = buf->handle;
+
+ /* create pattern of half the screen size */
+ checkerboard = create_checkerboard_pattern(screen_width / 64, screen_height / 64, 32);
+ if (!checkerboard) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ img_w = (screen_width / 64) * 32;
+ img_h = (screen_height / 64) * 32;
+
+ switch (type) {
+ case G2D_IMGBUF_GEM:
+ memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4);
+ tmp_img.bo[0] = tmp->handle;
+ break;
+ case G2D_IMGBUF_USERPTR:
+ tmp_img.user_ptr[0].userptr = (unsigned long)checkerboard;
+ tmp_img.user_ptr[0].size = img_w * img_h * 4;
+ break;
+ case G2D_IMGBUF_COLOR:
+ default:
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ /* solid fill framebuffer with white color */
+ img.width = screen_width;
+ img.height = screen_height;
+ img.stride = screen_width * 4;
+ img.buf_type = G2D_IMGBUF_GEM;
+ img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ img.color = 0xffffffff;
+
+ /* put checkerboard pattern in the center of the framebuffer */
+ cur_x = (screen_width - img_w) / 2;
+ cur_y = (screen_height - img_h) / 2;
+ tmp_img.width = img_w;
+ tmp_img.height = img_h;
+ tmp_img.stride = img_w * 4;
+ tmp_img.buf_type = type;
+ tmp_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+
+ ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width, screen_height) ||
+ g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y, img_w, img_h);
+
+ if (!ret)
+ ret = g2d_exec(ctx);
+ if (ret < 0)
+ goto fail;
+
+ printf("move test with %s.\n",
+ type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+ srand(time(NULL));
+ for (count = 0; count < 256; ++count) {
+ const struct g2d_step *s;
+
+ /* select step and validate it */
+ while (1) {
+ s = &steps[random() % num_steps];
+
+ if (cur_x + s->x < 0 || cur_y + s->y < 0 ||
+ cur_x + img_w + s->x >= screen_width ||
+ cur_y + img_h + s->y >= screen_height)
+ continue;
+ else
+ break;
+ }
+
+ ret = g2d_move(ctx, &img, cur_x, cur_y, cur_x + s->x, cur_y + s->y,
+ img_w, img_h);
+ if (!ret)
+ ret = g2d_exec(ctx);
+
+ if (ret < 0)
+ goto fail;
+
+ cur_x += s->x;
+ cur_y += s->y;
+
+ usleep(100000);
+ }
+
+fail:
+ g2d_fini(ctx);
+
+ free(checkerboard);
+
+ return ret;
+}
+
+static int g2d_copy_with_scale_test(struct exynos_device *dev,
+ struct exynos_bo *src,
+ struct exynos_bo *dst,
+ enum e_g2d_buf_type type)
+{
+ struct g2d_context *ctx;
+ struct g2d_image src_img = {0}, dst_img = {0};
+ unsigned int src_x, src_y, img_w, img_h;
+ unsigned long userptr, size;
+ int ret;
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ dst_img.bo[0] = dst->handle;
+
+ src_x = 0;
+ src_y = 0;
+ img_w = screen_width;
+ img_h = screen_height;
+
+ switch (type) {
+ case G2D_IMGBUF_GEM:
+ src_img.bo[0] = src->handle;
+ break;
+ case G2D_IMGBUF_USERPTR:
+ size = img_w * img_h * 4;
+
+ userptr = (unsigned long)malloc(size);
+ if (!userptr) {
+ fprintf(stderr, "failed to allocate userptr.\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ src_img.user_ptr[0].userptr = userptr;
+ src_img.user_ptr[0].size = size;
+ break;
+ case G2D_IMGBUF_COLOR:
+ default:
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ printf("copy and scale test with %s.\n",
+ type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+ src_img.width = img_w;
+ src_img.height = img_h;
+ src_img.stride = src_img.width * 4;
+ src_img.buf_type = type;
+ src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ src_img.color = 0xffffffff;
+ ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w , img_h);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ src_img.color = 0xff00ff00;
+ ret = g2d_solid_fill(ctx, &src_img, 5, 5, 100, 100);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ dst_img.width = img_w;
+ dst_img.height = img_h;
+ dst_img.buf_type = G2D_IMGBUF_GEM;
+ dst_img.stride = dst_img.width * 4;
+ dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+
+ ret = g2d_copy_with_scale(ctx, &src_img, &dst_img, 5, 5, 100, 100,
+ 100, 100, 200, 200, 0);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ g2d_exec(ctx);
+
+err_free_userptr:
+ if (type == G2D_IMGBUF_USERPTR)
+ if (userptr)
+ free((void *)userptr);
+
+fail:
+ g2d_fini(ctx);
+
+ return ret;
+}
+
+#ifdef EXYNOS_G2D_USERPTR_TEST
+static int g2d_blend_test(struct exynos_device *dev,
+ struct exynos_bo *src,
+ struct exynos_bo *dst,
+ enum e_g2d_buf_type type)
+{
+ struct g2d_context *ctx;
+ struct g2d_image src_img = {0}, dst_img = {0};
+ unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
+ unsigned long userptr, size;
+ int ret;
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ dst_img.bo[0] = dst->handle;
+
+ src_x = 0;
+ src_y = 0;
+ dst_x = 0;
+ dst_y = 0;
+ img_w = screen_width;
+ img_h = screen_height;
+
+ switch (type) {
+ case G2D_IMGBUF_GEM:
+ src_img.bo[0] = src->handle;
+ break;
+ case G2D_IMGBUF_USERPTR:
+ size = img_w * img_h * 4;
+
+ userptr = (unsigned long)malloc(size);
+ if (!userptr) {
+ fprintf(stderr, "failed to allocate userptr.\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ src_img.user_ptr[0].userptr = userptr;
+ src_img.user_ptr[0].size = size;
+ break;
+ case G2D_IMGBUF_COLOR:
+ default:
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ printf("blend test with %s.\n",
+ type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+ src_img.width = img_w;
+ src_img.height = img_h;
+ src_img.stride = src_img.width * 4;
+ src_img.buf_type = type;
+ src_img.select_mode = G2D_SELECT_MODE_NORMAL;
+ src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ src_img.color = 0xffffffff;
+ ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ src_img.color = 0x770000ff;
+ ret = g2d_solid_fill(ctx, &src_img, 5, 5, 200, 200);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ dst_img.width = img_w;
+ dst_img.height = img_h;
+ dst_img.stride = dst_img.width * 4;
+ dst_img.buf_type = G2D_IMGBUF_GEM;
+ dst_img.select_mode = G2D_SELECT_MODE_NORMAL;
+ dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ dst_img.color = 0xffffffff;
+ ret = g2d_solid_fill(ctx, &dst_img, dst_x, dst_y, img_w, img_h);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ dst_img.color = 0x77ff0000;
+ ret = g2d_solid_fill(ctx, &dst_img, 105, 105, 200, 200);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ ret = g2d_blend(ctx, &src_img, &dst_img, 5, 5, 105, 105, 200, 200,
+ G2D_OP_OVER);
+ if (ret < 0)
+ goto err_free_userptr;
+
+ g2d_exec(ctx);
+
+err_free_userptr:
+ if (type == G2D_IMGBUF_USERPTR)
+ if (userptr)
+ free((void *)userptr);
+
+fail:
+ g2d_fini(ctx);
+
+ return ret;
+}
+#endif
+
+static int g2d_checkerboard_test(struct exynos_device *dev,
+ struct exynos_bo *src,
+ struct exynos_bo *dst,
+ enum e_g2d_buf_type type)
+{
+ struct g2d_context *ctx;
+ struct g2d_image src_img = {0}, dst_img = {0};
+ unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
+ void *checkerboard = NULL;
+ int ret;
+
+ ctx = g2d_init(dev->fd);
+ if (!ctx)
+ return -EFAULT;
+
+ dst_img.bo[0] = dst->handle;
+
+ src_x = 0;
+ src_y = 0;
+ dst_x = 0;
+ dst_y = 0;
+
+ checkerboard = create_checkerboard_pattern(screen_width / 32, screen_height / 32, 32);
+ if (!checkerboard) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ img_w = screen_width - (screen_width % 32);
+ img_h = screen_height - (screen_height % 32);
+
+ switch (type) {
+ case G2D_IMGBUF_GEM:
+ memcpy(src->vaddr, checkerboard, img_w * img_h * 4);
+ src_img.bo[0] = src->handle;
+ break;
+ case G2D_IMGBUF_USERPTR:
+ src_img.user_ptr[0].userptr = (unsigned long)checkerboard;
+ src_img.user_ptr[0].size = img_w * img_h * 4;
+ break;
+ case G2D_IMGBUF_COLOR:
+ default:
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ printf("checkerboard test with %s.\n",
+ type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+ src_img.width = img_w;
+ src_img.height = img_h;
+ src_img.stride = src_img.width * 4;
+ src_img.buf_type = type;
+ src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+
+ dst_img.width = screen_width;
+ dst_img.height = screen_height;
+ dst_img.stride = dst_img.width * 4;
+ dst_img.buf_type = G2D_IMGBUF_GEM;
+ dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ src_img.color = 0xff000000;
+ ret = g2d_solid_fill(ctx, &dst_img, src_x, src_y, screen_width, screen_height);
+ if (ret < 0)
+ goto fail;
+
+ ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y,
+ img_w, img_h);
+ if (ret < 0)
+ goto fail;
+
+ g2d_exec(ctx);
+
+fail:
+ free(checkerboard);
+ g2d_fini(ctx);
+
+ return ret;
+}
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-s]\n", name);
+ fprintf(stderr, "-s <connector_id>@<crtc_id>:<mode>\n");
+ exit(0);
+}
+
+extern char *optarg;
+static const char optstr[] = "s:";
+
+int main(int argc, char **argv)
+{
+ struct exynos_device *dev;
+ struct exynos_bo *bo, *src;
+ struct connector con;
+ unsigned int fb_id;
+ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+ drmModeRes *resources;
+ int ret, fd, c;
+
+ memset(&con, 0, sizeof(struct connector));
+
+ if (argc != 3) {
+ usage(argv[0]);
+ return -EINVAL;
+ }
+
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 's':
+ con.crtc = -1;
+ if (sscanf(optarg, "%d:0x%64s",
+ &con.id,
+ con.mode_str) != 2 &&
+ sscanf(optarg, "%d@%d:%64s",
+ &con.id,
+ &con.crtc,
+ con.mode_str) != 3)
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ fd = drmOpen(DRM_MODULE_NAME, NULL);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open.\n");
+ return fd;
+ }
+
+ dev = exynos_device_create(fd);
+ if (!dev) {
+ ret = -EFAULT;
+ goto err_drm_close;
+ }
+
+ resources = drmModeGetResources(dev->fd);
+ if (!resources) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ ret = -EFAULT;
+ goto err_dev_destory;
+ }
+
+ connector_find_mode(dev->fd, &con, resources);
+ drmModeFreeResources(resources);
+
+ if (!con.mode) {
+ fprintf(stderr, "failed to find usable connector\n");
+ ret = -EFAULT;
+ goto err_dev_destory;
+ }
+
+ screen_width = con.mode->hdisplay;
+ screen_height = con.mode->vdisplay;
+
+ if (screen_width == 0 || screen_height == 0) {
+ fprintf(stderr, "failed to find sane resolution on connector\n");
+ ret = -EFAULT;
+ goto err_dev_destory;
+ }
+
+ printf("screen width = %d, screen height = %d\n", screen_width,
+ screen_height);
+
+ bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
+ if (!bo) {
+ ret = -EFAULT;
+ goto err_dev_destory;
+ }
+
+ handles[0] = bo->handle;
+ pitches[0] = screen_width * 4;
+ offsets[0] = 0;
+
+ ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
+ DRM_FORMAT_XRGB8888, handles,
+ pitches, offsets, &fb_id, 0);
+ if (ret < 0)
+ goto err_destroy_buffer;
+
+ memset(bo->vaddr, 0xff, screen_width * screen_height * 4);
+
+ ret = drm_set_crtc(dev, &con, fb_id);
+ if (ret < 0)
+ goto err_rm_fb;
+
+ ret = g2d_solid_fill_test(dev, bo);
+ if (ret < 0) {
+ fprintf(stderr, "failed to solid fill operation.\n");
+ goto err_rm_fb;
+ }
+
+ wait_for_user_input(0);
+
+ src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
+ if (!src) {
+ ret = -EFAULT;
+ goto err_rm_fb;
+ }
+
+ ret = g2d_copy_test(dev, src, bo, G2D_IMGBUF_GEM);
+ if (ret < 0) {
+ fprintf(stderr, "failed to test copy operation.\n");
+ goto err_free_src;
+ }
+
+ wait_for_user_input(0);
+
+ ret = g2d_move_test(dev, src, bo, G2D_IMGBUF_GEM);
+ if (ret < 0) {
+ fprintf(stderr, "failed to test move operation.\n");
+ goto err_free_src;
+ }
+
+ wait_for_user_input(0);
+
+ ret = g2d_copy_with_scale_test(dev, src, bo, G2D_IMGBUF_GEM);
+ if (ret < 0) {
+ fprintf(stderr, "failed to test copy and scale operation.\n");
+ goto err_free_src;
+ }
+
+ wait_for_user_input(0);
+
+ ret = g2d_checkerboard_test(dev, src, bo, G2D_IMGBUF_GEM);
+ if (ret < 0) {
+ fprintf(stderr, "failed to issue checkerboard test.\n");
+ goto err_free_src;
+ }
+
+ wait_for_user_input(1);
+
+ /*
+ * The blend test uses the userptr functionality of exynos-drm, which
+ * is currently not safe to use. If the kernel hasn't been build with
+ * exynos-iommu support, then the blend test is going to produce (kernel)
+ * memory corruption, eventually leading to a system crash.
+ *
+ * Disable the test for now, until the kernel code has been sanitized.
+ */
+#ifdef EXYNOS_G2D_USERPTR_TEST
+ ret = g2d_blend_test(dev, src, bo, G2D_IMGBUF_USERPTR);
+ if (ret < 0)
+ fprintf(stderr, "failed to test blend operation.\n");
+
+ getchar();
+#endif
+
+err_free_src:
+ if (src)
+ exynos_destroy_buffer(src);
+
+err_rm_fb:
+ drmModeRmFB(dev->fd, fb_id);
+
+err_destroy_buffer:
+ exynos_destroy_buffer(bo);
+
+err_dev_destory:
+ exynos_device_destroy(dev);
+
+err_drm_close:
+ drmClose(fd);
+
+ return ret;
+}
diff --git a/tests/exynos/meson.build b/tests/exynos/meson.build
new file mode 100644
index 0000000..12259c3
--- /dev/null
+++ b/tests/exynos/meson.build
@@ -0,0 +1,51 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+inc_exynos = include_directories('../../exynos')
+
+exynos_fimg2d_test = executable(
+ 'exynos_fimg2d_test',
+ files('exynos_fimg2d_test.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_drm, inc_exynos],
+ link_with : [libdrm, libdrm_exynos],
+ dependencies : dep_threads,
+ install : with_install_tests,
+)
+
+exynos_fimg2d_perf = executable(
+ 'exynos_fimg2d_perf',
+ files('exynos_fimg2d_perf.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_drm, inc_exynos],
+ link_with : [libdrm, libdrm_exynos],
+ dependencies : dep_threads,
+ install : with_install_tests,
+)
+
+exynos_fimg2d_event = executable(
+ 'exynos_fimg2d_event',
+ files('exynos_fimg2d_event.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_drm, inc_exynos],
+ link_with : [libdrm, libdrm_exynos],
+ dependencies : dep_threads,
+ install : with_install_tests,
+)
diff --git a/tests/hash.c b/tests/hash.c
new file mode 100644
index 0000000..4475fba
--- /dev/null
+++ b/tests/hash.c
@@ -0,0 +1,217 @@
+/* xf86drmHash.c -- Small hash table support for integer -> integer mapping
+ * Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward implementation of a fixed-sized
+ * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
+ * collision resolution. There are two potentially interesting things
+ * about this implementation:
+ *
+ * 1) The table is power-of-two sized. Prime sized tables are more
+ * traditional, but do not have a significant advantage over power-of-two
+ * sized table, especially when double hashing is not used for collision
+ * resolution.
+ *
+ * 2) The hash computation uses a table of random integers [Hanson97,
+ * pp. 39-41].
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * With a table size of 512, the current implementation is sufficient for a
+ * few hundred keys. Since this is well above the expected size of the
+ * tables for which this implementation was designed, the implementation of
+ * dynamic hash tables was postponed until the need arises. A common (and
+ * naive) approach to dynamic hash table implementation simply creates a
+ * new hash table when necessary, rehashes all the data into the new table,
+ * and destroys the old table. The approach in [Larson88] is superior in
+ * two ways: 1) only a portion of the table is expanded when needed,
+ * distributing the expansion cost over several insertions, and 2) portions
+ * of the table can be locked, enabling a scalable thread-safe
+ * implementation.
+ *
+ * REFERENCES
+ *
+ * [Hanson97] David R. Hanson. C Interfaces and Implementations:
+ * Techniques for Creating Reusable Software. Reading, Massachusetts:
+ * Addison-Wesley, 1997.
+ *
+ * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
+ * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
+ *
+ * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
+ * 1988, pp. 446-457.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xf86drm.h"
+#include "xf86drmHash.h"
+
+#define DIST_LIMIT 10
+static int dist[DIST_LIMIT];
+
+static void clear_dist(void) {
+ int i;
+
+ for (i = 0; i < DIST_LIMIT; i++)
+ dist[i] = 0;
+}
+
+static int count_entries(HashBucketPtr bucket)
+{
+ int count = 0;
+
+ for (; bucket; bucket = bucket->next)
+ ++count;
+ return count;
+}
+
+static void update_dist(int count)
+{
+ if (count >= DIST_LIMIT)
+ ++dist[DIST_LIMIT-1];
+ else
+ ++dist[count];
+}
+
+static void compute_dist(HashTablePtr table)
+{
+ int i;
+ HashBucketPtr bucket;
+
+ printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
+ table->entries, table->hits, table->partials, table->misses);
+ clear_dist();
+ for (i = 0; i < HASH_SIZE; i++) {
+ bucket = table->buckets[i];
+ update_dist(count_entries(bucket));
+ }
+ for (i = 0; i < DIST_LIMIT; i++) {
+ if (i != DIST_LIMIT-1)
+ printf("%5d %10d\n", i, dist[i]);
+ else
+ printf("other %10d\n", dist[i]);
+ }
+}
+
+static int check_table(HashTablePtr table,
+ unsigned long key, void * value)
+{
+ void *retval;
+ int retcode = drmHashLookup(table, key, &retval);
+
+ switch (retcode) {
+ case -1:
+ printf("Bad magic = 0x%08lx:"
+ " key = %lu, expected = %p, returned = %p\n",
+ table->magic, key, value, retval);
+ break;
+ case 1:
+ printf("Not found: key = %lu, expected = %p, returned = %p\n",
+ key, value, retval);
+ break;
+ case 0:
+ if (value != retval) {
+ printf("Bad value: key = %lu, expected = %p, returned = %p\n",
+ key, value, retval);
+ retcode = -1;
+ }
+ break;
+ default:
+ printf("Bad retcode = %d: key = %lu, expected = %p, returned = %p\n",
+ retcode, key, value, retval);
+ break;
+ }
+ return retcode;
+}
+
+int main(void)
+{
+ HashTablePtr table;
+ unsigned long i;
+ int ret = 0;
+
+ printf("\n***** 256 consecutive integers ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 256; i++)
+ drmHashInsert(table, i, (void *)(i << 16 | i));
+ for (i = 0; i < 256; i++)
+ ret |= check_table(table, i, (void *)(i << 16 | i));
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 consecutive integers ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 1024; i++)
+ drmHashInsert(table, i, (void *)(i << 16 | i));
+ for (i = 0; i < 1024; i++)
+ ret |= check_table(table, i, (void *)(i << 16 | i));
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 1024; i++)
+ drmHashInsert(table, i*4096, (void *)(i << 16 | i));
+ for (i = 0; i < 1024; i++)
+ ret |= check_table(table, i*4096, (void *)(i << 16 | i));
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 random integers ****\n");
+ table = drmHashCreate();
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++)
+ drmHashInsert(table, random(), (void *)(i << 16 | i));
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++)
+ ret |= check_table(table, random(), (void *)(i << 16 | i));
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++)
+ ret |= check_table(table, random(), (void *)(i << 16 | i));
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 5000 random integers ****\n");
+ table = drmHashCreate();
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++)
+ drmHashInsert(table, random(), (void *)(i << 16 | i));
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++)
+ ret |= check_table(table, random(), (void *)(i << 16 | i));
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++)
+ ret |= check_table(table, random(), (void *)(i << 16 | i));
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ return ret;
+}
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..ac9e66b
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,74 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+inc_tests = include_directories('.')
+
+subdir('util')
+subdir('modeprint')
+subdir('proptest')
+subdir('modetest')
+subdir('vbltest')
+if with_radeon
+ subdir('radeon')
+endif
+if with_amdgpu
+ subdir('amdgpu')
+endif
+if with_exynos
+ subdir('exynos')
+endif
+if with_tegra
+ subdir('tegra')
+endif
+if with_etnaviv
+ subdir('etnaviv')
+endif
+if with_nouveau
+ subdir('nouveau')
+endif
+
+drmsl = executable(
+ 'drmsl',
+ files('drmsl.c'),
+ include_directories : [inc_root, inc_drm],
+ link_with : libdrm,
+ c_args : libdrm_c_args,
+)
+
+hash = executable(
+ 'hash',
+ files('hash.c'),
+ include_directories : [inc_root, inc_drm],
+ link_with : libdrm,
+ c_args : libdrm_c_args,
+)
+
+drmdevice = executable(
+ 'drmdevice',
+ files('drmdevice.c'),
+ include_directories : [inc_root, inc_drm],
+ link_with : libdrm,
+ c_args : libdrm_c_args,
+ install : with_install_tests,
+)
+
+test('hash', hash)
+test('drmsl', drmsl)
+test('drmdevice', drmdevice)
diff --git a/tests/modeprint/meson.build b/tests/modeprint/meson.build
new file mode 100644
index 0000000..0801808
--- /dev/null
+++ b/tests/modeprint/meson.build
@@ -0,0 +1,29 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+modeprint = executable(
+ 'modeprint',
+ files('modeprint.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_tests, inc_drm],
+ link_with : [libdrm, libutil],
+ dependencies : dep_threads,
+ install : with_install_tests,
+)
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c
new file mode 100644
index 0000000..0f644c7
--- /dev/null
+++ b/tests/modeprint/modeprint.c
@@ -0,0 +1,418 @@
+/*
+ * \file modedemo.c
+ * Test program to dump DRM kernel mode setting related information.
+ * Queries the kernel for all available information and dumps it to stdout.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+/*
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "util/common.h"
+#include "util/kms.h"
+
+int current;
+int connectors;
+int full_props;
+int edid;
+int modes;
+int full_modes;
+int encoders;
+int crtcs;
+int fbs;
+char *module_name;
+
+static int printMode(struct drm_mode_modeinfo *mode)
+{
+ if (full_modes) {
+ printf("Mode: %s\n", mode->name);
+ printf("\tclock : %i\n", mode->clock);
+ printf("\thdisplay : %i\n", mode->hdisplay);
+ printf("\thsync_start : %i\n", mode->hsync_start);
+ printf("\thsync_end : %i\n", mode->hsync_end);
+ printf("\thtotal : %i\n", mode->htotal);
+ printf("\thskew : %i\n", mode->hskew);
+ printf("\tvdisplay : %i\n", mode->vdisplay);
+ printf("\tvsync_start : %i\n", mode->vsync_start);
+ printf("\tvsync_end : %i\n", mode->vsync_end);
+ printf("\tvtotal : %i\n", mode->vtotal);
+ printf("\tvscan : %i\n", mode->vscan);
+ printf("\tvrefresh : %i\n", mode->vrefresh);
+ printf("\tflags : %i\n", mode->flags);
+ } else {
+ printf("Mode: \"%s\" %ix%i %i\n", mode->name,
+ mode->hdisplay, mode->vdisplay, mode->vrefresh);
+ }
+ return 0;
+}
+
+static int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value)
+{
+ const char *name = NULL;
+ int j;
+
+ printf("Property: %s\n", props->name);
+ printf("\tid : %i\n", props->prop_id);
+ printf("\tflags : %i\n", props->flags);
+ printf("\tcount_values : %d\n", props->count_values);
+
+
+ if (props->count_values) {
+ printf("\tvalues :");
+ for (j = 0; j < props->count_values; j++)
+ printf(" %" PRIu64, props->values[j]);
+ printf("\n");
+ }
+
+
+ printf("\tcount_enums : %d\n", props->count_enums);
+
+ if (props->flags & DRM_MODE_PROP_BLOB) {
+ drmModePropertyBlobPtr blob;
+
+ blob = drmModeGetPropertyBlob(fd, value);
+ if (blob) {
+ printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
+ drmModeFreePropertyBlob(blob);
+ } else {
+ printf("error getting blob %" PRIu64 "\n", value);
+ }
+
+ } else {
+ for (j = 0; j < props->count_enums; j++) {
+ printf("\t\t%" PRIu64" = %s\n", (uint64_t)props->enums[j].value, props->enums[j].name);
+ if (props->enums[j].value == value)
+ name = props->enums[j].name;
+ }
+
+ if (props->count_enums && name) {
+ printf("\tcon_value : %s\n", name);
+ } else {
+ printf("\tcon_value : %" PRIu64 "\n", value);
+ }
+ }
+
+ return 0;
+}
+
+static int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id)
+{
+ int i = 0;
+ struct drm_mode_modeinfo *mode = NULL;
+ drmModePropertyPtr props;
+ const char *connector_type_name = NULL;
+
+ connector_type_name = drmModeGetConnectorTypeName(connector->connector_type);
+
+ if (connector_type_name)
+ printf("Connector: %s-%d\n", connector_type_name,
+ connector->connector_type_id);
+ else
+ printf("Connector: %d-%d\n", connector->connector_type,
+ connector->connector_type_id);
+ printf("\tid : %i\n", id);
+ printf("\tencoder id : %i\n", connector->encoder_id);
+ printf("\tconn : %s\n", util_lookup_connector_status_name(connector->connection));
+ printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight);
+ printf("\tcount_modes : %i\n", connector->count_modes);
+ printf("\tcount_props : %i\n", connector->count_props);
+ if (connector->count_props) {
+ printf("\tprops :");
+ for (i = 0; i < connector->count_props; i++)
+ printf(" %i", connector->props[i]);
+ printf("\n");
+ }
+
+ printf("\tcount_encoders : %i\n", connector->count_encoders);
+ if (connector->count_encoders) {
+ printf("\tencoders :");
+ for (i = 0; i < connector->count_encoders; i++)
+ printf(" %i", connector->encoders[i]);
+ printf("\n");
+ }
+
+ if (modes) {
+ for (i = 0; i < connector->count_modes; i++) {
+ mode = (struct drm_mode_modeinfo *)&connector->modes[i];
+ printMode(mode);
+ }
+ }
+
+ if (full_props) {
+ for (i = 0; i < connector->count_props; i++) {
+ props = drmModeGetProperty(fd, connector->props[i]);
+ if (props) {
+ printProperty(fd, res, props, connector->prop_values[i]);
+ drmModeFreeProperty(props);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id)
+{
+ const char *encoder_name;
+
+ encoder_name = util_lookup_encoder_type_name(encoder->encoder_type);
+ if (encoder_name)
+ printf("Encoder: %s\n", encoder_name);
+ else
+ printf("Encoder\n");
+ printf("\tid :%i\n", id);
+ printf("\tcrtc_id :%d\n", encoder->crtc_id);
+ printf("\ttype :%d\n", encoder->encoder_type);
+ printf("\tpossible_crtcs :0x%x\n", encoder->possible_crtcs);
+ printf("\tpossible_clones :0x%x\n", encoder->possible_clones);
+ return 0;
+}
+
+static int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
+{
+ printf("Crtc\n");
+ printf("\tid : %i\n", id);
+ printf("\tx : %i\n", crtc->x);
+ printf("\ty : %i\n", crtc->y);
+ printf("\twidth : %i\n", crtc->width);
+ printf("\theight : %i\n", crtc->height);
+ printf("\tmode : %p\n", &crtc->mode);
+ printf("\tgamma size : %d\n", crtc->gamma_size);
+
+ return 0;
+}
+
+static int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb)
+{
+ printf("Framebuffer\n");
+ printf("\thandle : %i\n", fb->handle);
+ printf("\twidth : %i\n", fb->width);
+ printf("\theight : %i\n", fb->height);
+ printf("\tpitch : %i\n", fb->pitch);
+ printf("\tbpp : %i\n", fb->bpp);
+ printf("\tdepth : %i\n", fb->depth);
+ printf("\tbuffer_id : %i\n", fb->handle);
+
+ return 0;
+}
+
+static int printRes(int fd, drmModeResPtr res)
+{
+ int i;
+ drmModeFBPtr fb;
+ drmModeCrtcPtr crtc;
+ drmModeEncoderPtr encoder;
+ drmModeConnectorPtr connector;
+
+ printf("Resources\n\n");
+
+ printf("count_connectors : %i\n", res->count_connectors);
+ printf("count_encoders : %i\n", res->count_encoders);
+ printf("count_crtcs : %i\n", res->count_crtcs);
+ printf("count_fbs : %i\n", res->count_fbs);
+
+ printf("\n");
+
+ if (connectors) {
+ for (i = 0; i < res->count_connectors; i++) {
+ connector = (current ? drmModeGetConnectorCurrent : drmModeGetConnector) (fd, res->connectors[i]);
+
+ if (!connector)
+ printf("Could not get connector %i\n", res->connectors[i]);
+ else {
+ printConnector(fd, res, connector, res->connectors[i]);
+ drmModeFreeConnector(connector);
+ }
+ }
+ printf("\n");
+ }
+
+
+ if (encoders) {
+ for (i = 0; i < res->count_encoders; i++) {
+ encoder = drmModeGetEncoder(fd, res->encoders[i]);
+
+ if (!encoder)
+ printf("Could not get encoder %i\n", res->encoders[i]);
+ else {
+ printEncoder(fd, res, encoder, res->encoders[i]);
+ drmModeFreeEncoder(encoder);
+ }
+ }
+ printf("\n");
+ }
+
+ if (crtcs) {
+ for (i = 0; i < res->count_crtcs; i++) {
+ crtc = drmModeGetCrtc(fd, res->crtcs[i]);
+
+ if (!crtc)
+ printf("Could not get crtc %i\n", res->crtcs[i]);
+ else {
+ printCrtc(fd, res, crtc, res->crtcs[i]);
+ drmModeFreeCrtc(crtc);
+ }
+ }
+ printf("\n");
+ }
+
+ if (fbs) {
+ for (i = 0; i < res->count_fbs; i++) {
+ fb = drmModeGetFB(fd, res->fbs[i]);
+
+ if (!fb)
+ printf("Could not get fb %i\n", res->fbs[i]);
+ else {
+ printFrameBuffer(fd, res, fb);
+ drmModeFreeFB(fb);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void args(int argc, char **argv)
+{
+ int defaults = 1;
+ int i;
+
+ fbs = 0;
+ edid = 0;
+ crtcs = 0;
+ modes = 0;
+ encoders = 0;
+ full_modes = 0;
+ full_props = 0;
+ connectors = 0;
+ current = 0;
+
+ module_name = argv[1];
+
+ for (i = 2; i < argc; i++) {
+ if (strcmp(argv[i], "-fb") == 0) {
+ fbs = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-crtcs") == 0) {
+ crtcs = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-cons") == 0) {
+ connectors = 1;
+ modes = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-modes") == 0) {
+ connectors = 1;
+ modes = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-full") == 0) {
+ connectors = 1;
+ modes = 1;
+ full_modes = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-props") == 0) {
+ connectors = 1;
+ full_props = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-edids") == 0) {
+ connectors = 1;
+ edid = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-encoders") == 0) {
+ encoders = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-v") == 0) {
+ fbs = 1;
+ edid = 1;
+ crtcs = 1;
+ modes = 1;
+ encoders = 1;
+ full_modes = 1;
+ full_props = 1;
+ connectors = 1;
+ defaults = 0;
+ } else if (strcmp(argv[i], "-current") == 0) {
+ current = 1;
+ }
+ }
+
+ if (defaults) {
+ fbs = 1;
+ edid = 1;
+ crtcs = 1;
+ modes = 1;
+ encoders = 1;
+ full_modes = 0;
+ full_props = 0;
+ connectors = 1;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ drmModeResPtr res;
+
+ if (argc == 1) {
+ printf("Please add modulename as first argument\n");
+ return 1;
+ }
+
+ args(argc, argv);
+
+ printf("Starting test\n");
+
+ fd = drmOpen(module_name, NULL);
+
+ if (fd < 0) {
+ printf("Failed to open the card fd (%d)\n",fd);
+ return 1;
+ }
+
+ res = drmModeGetResources(fd);
+ if (res == 0) {
+ printf("Failed to get resources from card\n");
+ drmClose(fd);
+ return 1;
+ }
+
+ printRes(fd, res);
+
+ drmModeFreeResources(res);
+
+ printf("Ok\n");
+
+ return 0;
+}
diff --git a/tests/modetest/Android.mk b/tests/modetest/Android.mk
new file mode 100644
index 0000000..c1a71fd
--- /dev/null
+++ b/tests/modetest/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Makefile.sources
+
+LOCAL_SRC_FILES := $(MODETEST_FILES)
+
+LOCAL_MODULE := modetest
+
+LOCAL_SHARED_LIBRARIES := libdrm
+LOCAL_STATIC_LIBRARIES := libdrm_util
+
+include $(LIBDRM_COMMON_MK)
+include $(BUILD_EXECUTABLE)
diff --git a/tests/modetest/Makefile.sources b/tests/modetest/Makefile.sources
new file mode 100644
index 0000000..399af0d
--- /dev/null
+++ b/tests/modetest/Makefile.sources
@@ -0,0 +1,6 @@
+MODETEST_FILES := \
+ buffers.c \
+ buffers.h \
+ cursor.c \
+ cursor.h \
+ modetest.c
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
new file mode 100644
index 0000000..0b55aed
--- /dev/null
+++ b/tests/modetest/buffers.c
@@ -0,0 +1,340 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "drm.h"
+#include "drm_fourcc.h"
+
+#include "libdrm_macros.h"
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "buffers.h"
+
+struct bo
+{
+ int fd;
+ void *ptr;
+ uint64_t size;
+ uint32_t pitch;
+ uint32_t handle;
+};
+
+/* -----------------------------------------------------------------------------
+ * Buffers management
+ */
+
+static struct bo *
+bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp)
+{
+ struct bo *bo;
+ int ret;
+
+ bo = calloc(1, sizeof(*bo));
+ if (bo == NULL) {
+ fprintf(stderr, "failed to allocate buffer object\n");
+ return NULL;
+ }
+
+ ret = drmModeCreateDumbBuffer(fd, width, height, bpp, 0, &bo->handle,
+ &bo->pitch, &bo->size);
+ if (ret) {
+ fprintf(stderr, "failed to create dumb buffer: %s\n",
+ strerror(errno));
+ free(bo);
+ return NULL;
+ }
+
+ bo->fd = fd;
+
+ return bo;
+}
+
+static int bo_map(struct bo *bo, void **out)
+{
+ void *map;
+ int ret;
+ uint64_t offset;
+
+ ret = drmModeMapDumbBuffer(bo->fd, bo->handle, &offset);
+ if (ret)
+ return ret;
+
+ map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ bo->fd, offset);
+ if (map == MAP_FAILED)
+ return -EINVAL;
+
+ bo->ptr = map;
+ *out = map;
+
+ return 0;
+}
+
+static void bo_unmap(struct bo *bo)
+{
+ if (!bo->ptr)
+ return;
+
+ drm_munmap(bo->ptr, bo->size);
+ bo->ptr = NULL;
+}
+
+struct bo *
+bo_create(int fd, unsigned int format,
+ unsigned int width, unsigned int height,
+ unsigned int handles[4], unsigned int pitches[4],
+ unsigned int offsets[4], enum util_fill_pattern pattern)
+{
+ unsigned int virtual_height;
+ struct bo *bo;
+ unsigned int bpp;
+ void *planes[3] = { 0, };
+ void *virtual;
+ int ret;
+
+ switch (format) {
+ case DRM_FORMAT_C8:
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ bpp = 8;
+ break;
+
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ bpp = 16;
+ break;
+
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ bpp = 24;
+ break;
+
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ bpp = 32;
+ break;
+
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ bpp = 64;
+ break;
+
+ default:
+ fprintf(stderr, "unsupported format 0x%08x\n", format);
+ return NULL;
+ }
+
+ switch (format) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ virtual_height = height * 3 / 2;
+ break;
+
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ virtual_height = height * 2;
+ break;
+
+ default:
+ virtual_height = height;
+ break;
+ }
+
+ bo = bo_create_dumb(fd, width, virtual_height, bpp);
+ if (!bo)
+ return NULL;
+
+ ret = bo_map(bo, &virtual);
+ if (ret) {
+ fprintf(stderr, "failed to map buffer: %s\n",
+ strerror(-errno));
+ bo_destroy(bo);
+ return NULL;
+ }
+
+ /* just testing a limited # of formats to test single
+ * and multi-planar path.. would be nice to add more..
+ */
+ switch (format) {
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ offsets[0] = 0;
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
+
+ planes[0] = virtual;
+ break;
+
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ offsets[0] = 0;
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
+ pitches[1] = pitches[0];
+ offsets[1] = pitches[0] * height;
+ handles[1] = bo->handle;
+
+ planes[0] = virtual;
+ planes[1] = virtual + offsets[1];
+ break;
+
+ case DRM_FORMAT_YUV420:
+ case DRM_FORMAT_YVU420:
+ offsets[0] = 0;
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
+ pitches[1] = pitches[0] / 2;
+ offsets[1] = pitches[0] * height;
+ handles[1] = bo->handle;
+ pitches[2] = pitches[1];
+ offsets[2] = offsets[1] + pitches[1] * height / 2;
+ handles[2] = bo->handle;
+
+ planes[0] = virtual;
+ planes[1] = virtual + offsets[1];
+ planes[2] = virtual + offsets[2];
+ break;
+
+ case DRM_FORMAT_C8:
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ offsets[0] = 0;
+ handles[0] = bo->handle;
+ pitches[0] = bo->pitch;
+
+ planes[0] = virtual;
+ break;
+ }
+
+ util_fill_pattern(format, pattern, planes, width, height, pitches[0]);
+ bo_unmap(bo);
+
+ return bo;
+}
+
+void bo_destroy(struct bo *bo)
+{
+ int ret;
+
+ ret = drmModeDestroyDumbBuffer(bo->fd, bo->handle);
+ if (ret)
+ fprintf(stderr, "failed to destroy dumb buffer: %s\n",
+ strerror(errno));
+
+ free(bo);
+}
diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h
new file mode 100644
index 0000000..7f95396
--- /dev/null
+++ b/tests/modetest/buffers.h
@@ -0,0 +1,40 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __BUFFERS_H__
+#define __BUFFERS_H__
+
+#include "util/pattern.h"
+
+struct bo;
+
+struct bo *bo_create(int fd, unsigned int format,
+ unsigned int width, unsigned int height,
+ unsigned int handles[4], unsigned int pitches[4],
+ unsigned int offsets[4], enum util_fill_pattern pattern);
+void bo_destroy(struct bo *bo);
+
+#endif
diff --git a/tests/modetest/cursor.c b/tests/modetest/cursor.c
new file mode 100644
index 0000000..829bced
--- /dev/null
+++ b/tests/modetest/cursor.c
@@ -0,0 +1,206 @@
+/*
+ * DRM based mode setting test program
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "util/common.h"
+
+#include "buffers.h"
+#include "cursor.h"
+
+struct cursor {
+ int fd;
+ uint32_t bo_handle;
+ uint32_t crtc_id;
+ uint32_t crtc_w, crtc_h;
+ uint32_t w, h;
+
+ /* current state */
+ uint32_t enabled, x, y;
+ int32_t dx, dy;
+};
+
+#define MAX_CURSORS 8
+static struct cursor cursors[MAX_CURSORS];
+static int ncursors;
+
+static pthread_t cursor_thread;
+static int cursor_running;
+
+/*
+ * Timer driven program loops through these steps to move/enable/disable
+ * the cursor
+ */
+
+struct cursor_step {
+ void (*run)(struct cursor *cursor, const struct cursor_step *step);
+ uint32_t msec;
+ uint32_t repeat;
+ int arg;
+};
+
+static uint32_t indx, count;
+
+static void set_cursor(struct cursor *cursor, const struct cursor_step *step)
+{
+ int enabled = (step->arg ^ count) & 0x1;
+ uint32_t handle = 0;
+
+ if (enabled)
+ handle = cursor->bo_handle;
+
+ cursor->enabled = enabled;
+
+ drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h);
+}
+
+static void move_cursor(struct cursor *cursor, const struct cursor_step *step)
+{
+ int x = cursor->x;
+ int y = cursor->y;
+
+ if (!cursor->enabled)
+ drmModeSetCursor(cursor->fd, cursor->crtc_id,
+ cursor->bo_handle, cursor->w, cursor->h);
+
+ /* calculate new cursor position: */
+ x += cursor->dx * step->arg;
+ y += cursor->dy * step->arg;
+
+ if (x < 0) {
+ x = 0;
+ cursor->dx = 1;
+ } else if (x > (int)cursor->crtc_w) {
+ x = cursor->crtc_w - 1;
+ cursor->dx = -1;
+ }
+
+ if (y < 0) {
+ y = 0;
+ cursor->dy = 1;
+ } else if (y > (int)cursor->crtc_h) {
+ y = cursor->crtc_h - 1;
+ cursor->dy = -1;
+ }
+
+ cursor->x = x;
+ cursor->y = y;
+
+ drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y);
+}
+
+static const struct cursor_step steps[] = {
+ { set_cursor, 10, 0, 1 }, /* enable */
+ { move_cursor, 1, 100, 1 },
+ { move_cursor, 1, 10, 10 },
+ { set_cursor, 1, 100, 0 }, /* disable/enable loop */
+ { move_cursor, 1, 10, 10 },
+ { move_cursor, 9, 100, 1 },
+ { move_cursor, 11, 100, 5 },
+ { set_cursor, 17, 10, 0 }, /* disable/enable loop */
+ { move_cursor, 9, 100, 1 },
+ { set_cursor, 13, 10, 0 }, /* disable/enable loop */
+ { move_cursor, 9, 100, 1 },
+ { set_cursor, 13, 10, 0 }, /* disable/enable loop */
+ { set_cursor, 10, 0, 0 }, /* disable */
+};
+
+static void *cursor_thread_func(void *data)
+{
+ while (cursor_running) {
+ const struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)];
+ int i;
+
+ for (i = 0; i < ncursors; i++) {
+ struct cursor *cursor = &cursors[i];
+ step->run(cursor, step);
+ }
+
+ /* iterate to next count/step: */
+ if (count < step->repeat) {
+ count++;
+ } else {
+ count = 0;
+ indx++;
+ }
+
+ usleep(1000 * step->msec);
+ }
+
+ return NULL;
+}
+
+int cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id,
+ uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h)
+{
+ struct cursor *cursor = &cursors[ncursors];
+
+ assert(ncursors < MAX_CURSORS);
+
+ cursor->fd = fd;
+ cursor->bo_handle = bo_handle;
+ cursor->crtc_id = crtc_id;
+ cursor->crtc_w = crtc_w;
+ cursor->crtc_h = crtc_h;
+ cursor->w = w;
+ cursor->h = h;
+
+ cursor->enabled = 0;
+ cursor->x = w/2;
+ cursor->y = h/2;
+ cursor->dx = 1;
+ cursor->dy = 1;
+
+ ncursors++;
+
+ return 0;
+}
+
+int cursor_start(void)
+{
+ cursor_running = 1;
+ pthread_create(&cursor_thread, NULL, cursor_thread_func, NULL);
+ printf("starting cursor\n");
+ return 0;
+}
+
+int cursor_stop(void)
+{
+ cursor_running = 0;
+ pthread_join(cursor_thread, NULL);
+ printf("cursor stopped\n");
+ return 0;
+}
diff --git a/tests/modetest/cursor.h b/tests/modetest/cursor.h
new file mode 100644
index 0000000..d849f6c
--- /dev/null
+++ b/tests/modetest/cursor.h
@@ -0,0 +1,33 @@
+/*
+ * DRM based mode setting test program
+ * Copyright (C) 2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __CURSOR_H__
+#define __CURSOR_H__
+
+int cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id,
+ uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h);
+int cursor_start(void);
+int cursor_stop(void);
+
+#endif
diff --git a/tests/modetest/meson.build b/tests/modetest/meson.build
new file mode 100644
index 0000000..23d84a1
--- /dev/null
+++ b/tests/modetest/meson.build
@@ -0,0 +1,29 @@
+# Copyright © 2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+modetest = executable(
+ 'modetest',
+ files('buffers.c', 'cursor.c', 'modetest.c'),
+ c_args : [libdrm_c_args, '-Wno-pointer-arith'],
+ include_directories : [inc_root, inc_tests, inc_drm],
+ dependencies : [dep_threads, dep_cairo],
+ link_with : [libdrm, libutil],
+ install : with_install_tests,
+)
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
new file mode 100644
index 0000000..42e2d1f
--- /dev/null
+++ b/tests/modetest/modetest.c
@@ -0,0 +1,2285 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This fairly simple test program dumps output in a similar format to the
+ * "xrandr" tool everyone knows & loves. It's necessarily slightly different
+ * since the kernel separates outputs into encoder and connector structures,
+ * each with their own unique ID. The program also allows test testing of the
+ * memory management and mode setting APIs by allowing the user to specify a
+ * connector and mode to use for mode setting. If all works as expected, a
+ * blue background should be painted on the monitor attached to the specified
+ * connector after the selected mode is set.
+ *
+ * TODO: use cairo to write the mode info on the selected output once
+ * the mode has been programmed, along with possible test patterns.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <poll.h>
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <math.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "drm_fourcc.h"
+
+#include "util/common.h"
+#include "util/format.h"
+#include "util/kms.h"
+#include "util/pattern.h"
+
+#include "buffers.h"
+#include "cursor.h"
+
+static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE;
+static enum util_fill_pattern secondary_fill = UTIL_PATTERN_TILES;
+
+struct crtc {
+ drmModeCrtc *crtc;
+ drmModeObjectProperties *props;
+ drmModePropertyRes **props_info;
+ drmModeModeInfo *mode;
+};
+
+struct encoder {
+ drmModeEncoder *encoder;
+};
+
+struct connector {
+ drmModeConnector *connector;
+ drmModeObjectProperties *props;
+ drmModePropertyRes **props_info;
+ char *name;
+};
+
+struct fb {
+ drmModeFB *fb;
+};
+
+struct plane {
+ drmModePlane *plane;
+ drmModeObjectProperties *props;
+ drmModePropertyRes **props_info;
+};
+
+struct resources {
+ struct crtc *crtcs;
+ int count_crtcs;
+ struct encoder *encoders;
+ int count_encoders;
+ struct connector *connectors;
+ int count_connectors;
+ struct fb *fbs;
+ int count_fbs;
+ struct plane *planes;
+ uint32_t count_planes;
+};
+
+struct device {
+ int fd;
+
+ struct resources *resources;
+
+ struct {
+ unsigned int width;
+ unsigned int height;
+
+ unsigned int fb_id;
+ struct bo *bo;
+ struct bo *cursor_bo;
+ } mode;
+
+ int use_atomic;
+ drmModeAtomicReq *req;
+};
+
+static inline int64_t U642I64(uint64_t val)
+{
+ return (int64_t)*((int64_t *)&val);
+}
+
+static float mode_vrefresh(drmModeModeInfo *mode)
+{
+ return mode->clock * 1000.00
+ / (mode->htotal * mode->vtotal);
+}
+
+#define bit_name_fn(res) \
+const char * res##_str(int type) { \
+ unsigned int i; \
+ const char *sep = ""; \
+ for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+ if (type & (1 << i)) { \
+ printf("%s%s", sep, res##_names[i]); \
+ sep = ", "; \
+ } \
+ } \
+ return NULL; \
+}
+
+static const char *mode_type_names[] = {
+ "builtin",
+ "clock_c",
+ "crtc_c",
+ "preferred",
+ "default",
+ "userdef",
+ "driver",
+};
+
+static bit_name_fn(mode_type)
+
+static const char *mode_flag_names[] = {
+ "phsync",
+ "nhsync",
+ "pvsync",
+ "nvsync",
+ "interlace",
+ "dblscan",
+ "csync",
+ "pcsync",
+ "ncsync",
+ "hskew",
+ "bcast",
+ "pixmux",
+ "dblclk",
+ "clkdiv2"
+};
+
+static bit_name_fn(mode_flag)
+
+static void dump_fourcc(uint32_t fourcc)
+{
+ char *name = drmGetFormatName(fourcc);
+ printf(" %s", name);
+ free(name);
+}
+
+static void dump_encoders(struct device *dev)
+{
+ drmModeEncoder *encoder;
+ int i;
+
+ printf("Encoders:\n");
+ printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+ for (i = 0; i < dev->resources->count_encoders; i++) {
+ encoder = dev->resources->encoders[i].encoder;
+ if (!encoder)
+ continue;
+
+ printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+ encoder->encoder_id,
+ encoder->crtc_id,
+ util_lookup_encoder_type_name(encoder->encoder_type),
+ encoder->possible_crtcs,
+ encoder->possible_clones);
+ }
+ printf("\n");
+}
+
+static void dump_mode(drmModeModeInfo *mode, int index)
+{
+ printf(" #%i %s %.2f %d %d %d %d %d %d %d %d %d",
+ index,
+ mode->name,
+ mode_vrefresh(mode),
+ mode->hdisplay,
+ mode->hsync_start,
+ mode->hsync_end,
+ mode->htotal,
+ mode->vdisplay,
+ mode->vsync_start,
+ mode->vsync_end,
+ mode->vtotal,
+ mode->clock);
+
+ printf(" flags: ");
+ mode_flag_str(mode->flags);
+ printf("; type: ");
+ mode_type_str(mode->type);
+ printf("\n");
+}
+
+static void dump_blob(struct device *dev, uint32_t blob_id)
+{
+ uint32_t i;
+ unsigned char *blob_data;
+ drmModePropertyBlobPtr blob;
+
+ blob = drmModeGetPropertyBlob(dev->fd, blob_id);
+ if (!blob) {
+ printf("\n");
+ return;
+ }
+
+ blob_data = blob->data;
+
+ for (i = 0; i < blob->length; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t\t");
+ printf("%.2hhx", blob_data[i]);
+ }
+ printf("\n");
+
+ drmModeFreePropertyBlob(blob);
+}
+
+static const char *modifier_to_string(uint64_t modifier)
+{
+ static char mod_string[4096];
+
+ char *modifier_name = drmGetFormatModifierName(modifier);
+ char *vendor_name = drmGetFormatModifierVendor(modifier);
+ memset(mod_string, 0x00, sizeof(mod_string));
+
+ if (!modifier_name) {
+ if (vendor_name)
+ snprintf(mod_string, sizeof(mod_string), "%s_%s",
+ vendor_name, "UNKNOWN_MODIFIER");
+ else
+ snprintf(mod_string, sizeof(mod_string), "%s_%s",
+ "UNKNOWN_VENDOR", "UNKNOWN_MODIFIER");
+ /* safe, as free is no-op for NULL */
+ free(vendor_name);
+ return mod_string;
+ }
+
+ if (modifier == DRM_FORMAT_MOD_LINEAR) {
+ snprintf(mod_string, sizeof(mod_string), "%s", modifier_name);
+ free(modifier_name);
+ free(vendor_name);
+ return mod_string;
+ }
+
+ snprintf(mod_string, sizeof(mod_string), "%s_%s",
+ vendor_name, modifier_name);
+
+ free(modifier_name);
+ free(vendor_name);
+ return mod_string;
+}
+
+static void dump_in_formats(struct device *dev, uint32_t blob_id)
+{
+ drmModeFormatModifierIterator iter = {0};
+ drmModePropertyBlobPtr blob;
+ uint32_t fmt = 0;
+
+ printf("\t\tin_formats blob decoded:\n");
+ blob = drmModeGetPropertyBlob(dev->fd, blob_id);
+ if (!blob) {
+ printf("\n");
+ return;
+ }
+
+ while (drmModeFormatModifierBlobIterNext(blob, &iter)) {
+ if (!fmt || fmt != iter.fmt) {
+ printf("%s\t\t\t", !fmt ? "" : "\n");
+ fmt = iter.fmt;
+ dump_fourcc(fmt);
+ printf(": ");
+ }
+
+ printf(" %s", modifier_to_string(iter.mod));
+ }
+
+ printf("\n");
+
+ drmModeFreePropertyBlob(blob);
+}
+
+static void dump_prop(struct device *dev, drmModePropertyPtr prop,
+ uint32_t prop_id, uint64_t value)
+{
+ int i;
+ printf("\t%d", prop_id);
+ if (!prop) {
+ printf("\n");
+ return;
+ }
+
+ printf(" %s:\n", prop->name);
+
+ printf("\t\tflags:");
+ if (prop->flags & DRM_MODE_PROP_PENDING)
+ printf(" pending");
+ if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
+ printf(" immutable");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
+ printf(" signed range");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
+ printf(" range");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
+ printf(" enum");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
+ printf(" bitmask");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
+ printf(" blob");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
+ printf(" object");
+ printf("\n");
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_values; i++)
+ printf(" %"PRId64, U642I64(prop->values[i]));
+ printf("\n");
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_values; i++)
+ printf(" %"PRIu64, prop->values[i]);
+ printf("\n");
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
+ printf("\t\tenums:");
+ for (i = 0; i < prop->count_enums; i++)
+ printf(" %s=%"PRIu64, prop->enums[i].name,
+ (uint64_t)prop->enums[i].value);
+ printf("\n");
+ } else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_enums; i++)
+ printf(" %s=0x%llx", prop->enums[i].name,
+ (1LL << prop->enums[i].value));
+ printf("\n");
+ } else {
+ assert(prop->count_enums == 0);
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
+ printf("\t\tblobs:\n");
+ for (i = 0; i < prop->count_blobs; i++)
+ dump_blob(dev, prop->blob_ids[i]);
+ printf("\n");
+ } else {
+ assert(prop->count_blobs == 0);
+ }
+
+ printf("\t\tvalue:");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
+ dump_blob(dev, value);
+ else if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
+ printf(" %"PRId64"\n", value);
+ else
+ printf(" %"PRIu64"\n", value);
+
+ if (strcmp(prop->name, "IN_FORMATS") == 0)
+ dump_in_formats(dev, value);
+}
+
+static void dump_connectors(struct device *dev)
+{
+ int i, j;
+
+ printf("Connectors:\n");
+ printf("id\tencoder\tstatus\t\tname\t\tsize (mm)\tmodes\tencoders\n");
+ for (i = 0; i < dev->resources->count_connectors; i++) {
+ struct connector *_connector = &dev->resources->connectors[i];
+ drmModeConnector *connector = _connector->connector;
+ if (!connector)
+ continue;
+
+ printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t",
+ connector->connector_id,
+ connector->encoder_id,
+ util_lookup_connector_status_name(connector->connection),
+ _connector->name,
+ connector->mmWidth, connector->mmHeight,
+ connector->count_modes);
+
+ for (j = 0; j < connector->count_encoders; j++)
+ printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
+ printf("\n");
+
+ if (connector->count_modes) {
+ printf(" modes:\n");
+ printf("\tindex name refresh (Hz) hdisp hss hse htot vdisp "
+ "vss vse vtot\n");
+ for (j = 0; j < connector->count_modes; j++)
+ dump_mode(&connector->modes[j], j);
+ }
+
+ if (_connector->props) {
+ printf(" props:\n");
+ for (j = 0; j < (int)_connector->props->count_props; j++)
+ dump_prop(dev, _connector->props_info[j],
+ _connector->props->props[j],
+ _connector->props->prop_values[j]);
+ }
+ }
+ printf("\n");
+}
+
+static void dump_crtcs(struct device *dev)
+{
+ int i;
+ uint32_t j;
+
+ printf("CRTCs:\n");
+ printf("id\tfb\tpos\tsize\n");
+ for (i = 0; i < dev->resources->count_crtcs; i++) {
+ struct crtc *_crtc = &dev->resources->crtcs[i];
+ drmModeCrtc *crtc = _crtc->crtc;
+ if (!crtc)
+ continue;
+
+ printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+ crtc->crtc_id,
+ crtc->buffer_id,
+ crtc->x, crtc->y,
+ crtc->width, crtc->height);
+ dump_mode(&crtc->mode, 0);
+
+ if (_crtc->props) {
+ printf(" props:\n");
+ for (j = 0; j < _crtc->props->count_props; j++)
+ dump_prop(dev, _crtc->props_info[j],
+ _crtc->props->props[j],
+ _crtc->props->prop_values[j]);
+ } else {
+ printf(" no properties found\n");
+ }
+ }
+ printf("\n");
+}
+
+static void dump_framebuffers(struct device *dev)
+{
+ drmModeFB *fb;
+ int i;
+
+ printf("Frame buffers:\n");
+ printf("id\tsize\tpitch\n");
+ for (i = 0; i < dev->resources->count_fbs; i++) {
+ fb = dev->resources->fbs[i].fb;
+ if (!fb)
+ continue;
+
+ printf("%u\t(%ux%u)\t%u\n",
+ fb->fb_id,
+ fb->width, fb->height,
+ fb->pitch);
+ }
+ printf("\n");
+}
+
+static void dump_planes(struct device *dev)
+{
+ unsigned int i, j;
+
+ printf("Planes:\n");
+ printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\tpossible crtcs\n");
+
+ for (i = 0; i < dev->resources->count_planes; i++) {
+ struct plane *plane = &dev->resources->planes[i];
+ drmModePlane *ovr = plane->plane;
+ if (!ovr)
+ continue;
+
+ printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n",
+ ovr->plane_id, ovr->crtc_id, ovr->fb_id,
+ ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
+ ovr->gamma_size, ovr->possible_crtcs);
+
+ if (!ovr->count_formats)
+ continue;
+
+ printf(" formats:");
+ for (j = 0; j < ovr->count_formats; j++)
+ dump_fourcc(ovr->formats[j]);
+ printf("\n");
+
+ if (plane->props) {
+ printf(" props:\n");
+ for (j = 0; j < plane->props->count_props; j++)
+ dump_prop(dev, plane->props_info[j],
+ plane->props->props[j],
+ plane->props->prop_values[j]);
+ } else {
+ printf(" no properties found\n");
+ }
+ }
+ printf("\n");
+
+ return;
+}
+
+static void free_resources(struct resources *res)
+{
+ int i;
+
+ if (!res)
+ return;
+
+#define free_resource(_res, type, Type) \
+ do { \
+ if (!(_res)->type##s) \
+ break; \
+ for (i = 0; i < (int)(_res)->count_##type##s; ++i) { \
+ if (!(_res)->type##s[i].type) \
+ break; \
+ drmModeFree##Type((_res)->type##s[i].type); \
+ } \
+ free((_res)->type##s); \
+ } while (0)
+
+#define free_properties(_res, type) \
+ do { \
+ for (i = 0; i < (int)(_res)->count_##type##s; ++i) { \
+ unsigned int j; \
+ for (j = 0; j < res->type##s[i].props->count_props; ++j)\
+ drmModeFreeProperty(res->type##s[i].props_info[j]);\
+ free(res->type##s[i].props_info); \
+ drmModeFreeObjectProperties(res->type##s[i].props); \
+ } \
+ } while (0)
+
+ free_properties(res, plane);
+ free_resource(res, plane, Plane);
+
+ free_properties(res, connector);
+ free_properties(res, crtc);
+
+ for (i = 0; i < res->count_connectors; i++)
+ free(res->connectors[i].name);
+
+ free_resource(res, fb, FB);
+ free_resource(res, connector, Connector);
+ free_resource(res, encoder, Encoder);
+ free_resource(res, crtc, Crtc);
+
+ free(res);
+}
+
+static struct resources *get_resources(struct device *dev)
+{
+ drmModeRes *_res;
+ drmModePlaneRes *plane_res;
+ struct resources *res;
+ int i;
+
+ res = calloc(1, sizeof(*res));
+ if (res == 0)
+ return NULL;
+
+ drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+
+ _res = drmModeGetResources(dev->fd);
+ if (!_res) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ free(res);
+ return NULL;
+ }
+
+ res->count_crtcs = _res->count_crtcs;
+ res->count_encoders = _res->count_encoders;
+ res->count_connectors = _res->count_connectors;
+ res->count_fbs = _res->count_fbs;
+
+ res->crtcs = calloc(res->count_crtcs, sizeof(*res->crtcs));
+ res->encoders = calloc(res->count_encoders, sizeof(*res->encoders));
+ res->connectors = calloc(res->count_connectors, sizeof(*res->connectors));
+ res->fbs = calloc(res->count_fbs, sizeof(*res->fbs));
+
+ if (!res->crtcs || !res->encoders || !res->connectors || !res->fbs) {
+ drmModeFreeResources(_res);
+ goto error;
+ }
+
+#define get_resource(_res, __res, type, Type) \
+ do { \
+ for (i = 0; i < (int)(_res)->count_##type##s; ++i) { \
+ uint32_t type##id = (__res)->type##s[i]; \
+ (_res)->type##s[i].type = \
+ drmModeGet##Type(dev->fd, type##id); \
+ if (!(_res)->type##s[i].type) \
+ fprintf(stderr, "could not get %s %i: %s\n", \
+ #type, type##id, \
+ strerror(errno)); \
+ } \
+ } while (0)
+
+ get_resource(res, _res, crtc, Crtc);
+ get_resource(res, _res, encoder, Encoder);
+ get_resource(res, _res, connector, Connector);
+ get_resource(res, _res, fb, FB);
+
+ drmModeFreeResources(_res);
+
+ /* Set the name of all connectors based on the type name and the per-type ID. */
+ for (i = 0; i < res->count_connectors; i++) {
+ struct connector *connector = &res->connectors[i];
+ drmModeConnector *conn = connector->connector;
+ int num;
+
+ num = asprintf(&connector->name, "%s-%u",
+ drmModeGetConnectorTypeName(conn->connector_type),
+ conn->connector_type_id);
+ if (num < 0)
+ goto error;
+ }
+
+#define get_properties(_res, type, Type) \
+ do { \
+ for (i = 0; i < (int)(_res)->count_##type##s; ++i) { \
+ struct type *obj = &res->type##s[i]; \
+ unsigned int j; \
+ obj->props = \
+ drmModeObjectGetProperties(dev->fd, obj->type->type##_id, \
+ DRM_MODE_OBJECT_##Type); \
+ if (!obj->props) { \
+ fprintf(stderr, \
+ "could not get %s %i properties: %s\n", \
+ #type, obj->type->type##_id, \
+ strerror(errno)); \
+ continue; \
+ } \
+ obj->props_info = calloc(obj->props->count_props, \
+ sizeof(*obj->props_info)); \
+ if (!obj->props_info) \
+ continue; \
+ for (j = 0; j < obj->props->count_props; ++j) \
+ obj->props_info[j] = \
+ drmModeGetProperty(dev->fd, obj->props->props[j]); \
+ } \
+ } while (0)
+
+ get_properties(res, crtc, CRTC);
+ get_properties(res, connector, CONNECTOR);
+
+ for (i = 0; i < res->count_crtcs; ++i)
+ res->crtcs[i].mode = &res->crtcs[i].crtc->mode;
+
+ plane_res = drmModeGetPlaneResources(dev->fd);
+ if (!plane_res) {
+ fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
+ strerror(errno));
+ return res;
+ }
+
+ res->count_planes = plane_res->count_planes;
+
+ res->planes = calloc(res->count_planes, sizeof(*res->planes));
+ if (!res->planes) {
+ drmModeFreePlaneResources(plane_res);
+ goto error;
+ }
+
+ get_resource(res, plane_res, plane, Plane);
+ drmModeFreePlaneResources(plane_res);
+ get_properties(res, plane, PLANE);
+
+ return res;
+
+error:
+ free_resources(res);
+ return NULL;
+}
+
+static struct crtc *get_crtc_by_id(struct device *dev, uint32_t id)
+{
+ int i;
+
+ for (i = 0; i < dev->resources->count_crtcs; ++i) {
+ drmModeCrtc *crtc = dev->resources->crtcs[i].crtc;
+ if (crtc && crtc->crtc_id == id)
+ return &dev->resources->crtcs[i];
+ }
+
+ return NULL;
+}
+
+static uint32_t get_crtc_mask(struct device *dev, struct crtc *crtc)
+{
+ unsigned int i;
+
+ for (i = 0; i < (unsigned int)dev->resources->count_crtcs; i++) {
+ if (crtc->crtc->crtc_id == dev->resources->crtcs[i].crtc->crtc_id)
+ return 1 << i;
+ }
+ /* Unreachable: crtc->crtc is one of resources->crtcs[] */
+ /* Don't return zero or static analysers will complain */
+ abort();
+ return 0;
+}
+
+static drmModeConnector *get_connector_by_name(struct device *dev, const char *name)
+{
+ struct connector *connector;
+ int i;
+
+ for (i = 0; i < dev->resources->count_connectors; i++) {
+ connector = &dev->resources->connectors[i];
+
+ if (strcmp(connector->name, name) == 0)
+ return connector->connector;
+ }
+
+ return NULL;
+}
+
+static drmModeConnector *get_connector_by_id(struct device *dev, uint32_t id)
+{
+ drmModeConnector *connector;
+ int i;
+
+ for (i = 0; i < dev->resources->count_connectors; i++) {
+ connector = dev->resources->connectors[i].connector;
+ if (connector && connector->connector_id == id)
+ return connector;
+ }
+
+ return NULL;
+}
+
+static drmModeEncoder *get_encoder_by_id(struct device *dev, uint32_t id)
+{
+ drmModeEncoder *encoder;
+ int i;
+
+ for (i = 0; i < dev->resources->count_encoders; i++) {
+ encoder = dev->resources->encoders[i].encoder;
+ if (encoder && encoder->encoder_id == id)
+ return encoder;
+ }
+
+ return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipes and planes
+ */
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+struct pipe_arg {
+ const char **cons;
+ uint32_t *con_ids;
+ unsigned int num_cons;
+ uint32_t crtc_id;
+ char mode_str[64];
+ char format_str[5];
+ float vrefresh;
+ unsigned int fourcc;
+ drmModeModeInfo *mode;
+ struct crtc *crtc;
+ unsigned int fb_id[2], current_fb_id;
+ struct timeval start;
+
+ int swap_count;
+};
+
+struct plane_arg {
+ uint32_t plane_id; /* the id of plane to use */
+ uint32_t crtc_id; /* the id of CRTC to bind to */
+ bool has_position;
+ int32_t x, y;
+ uint32_t w, h;
+ double scale;
+ unsigned int fb_id;
+ unsigned int old_fb_id;
+ struct bo *bo;
+ struct bo *old_bo;
+ char format_str[5]; /* need to leave room for terminating \0 */
+ unsigned int fourcc;
+};
+
+static drmModeModeInfo *
+connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
+ const float vrefresh)
+{
+ drmModeConnector *connector;
+ drmModeModeInfo *mode;
+ int i;
+
+ connector = get_connector_by_id(dev, con_id);
+ if (!connector || !connector->count_modes)
+ return NULL;
+
+ /* Pick by Index */
+ if (mode_str[0] == '#') {
+ int index = atoi(mode_str + 1);
+
+ if (index >= connector->count_modes || index < 0)
+ return NULL;
+ return &connector->modes[index];
+ }
+
+ /* Pick by Name */
+ for (i = 0; i < connector->count_modes; i++) {
+ mode = &connector->modes[i];
+ if (!strcmp(mode->name, mode_str)) {
+ /* If the vertical refresh frequency is not specified
+ * then return the first mode that match with the name.
+ * Else, return the mode that match the name and
+ * the specified vertical refresh frequency.
+ */
+ if (vrefresh == 0)
+ return mode;
+ else if (fabs(mode_vrefresh(mode) - vrefresh) < 0.005)
+ return mode;
+ }
+ }
+
+ return NULL;
+}
+
+static struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe)
+{
+ uint32_t possible_crtcs = ~0;
+ uint32_t active_crtcs = 0;
+ unsigned int crtc_idx;
+ unsigned int i;
+ int j;
+
+ for (i = 0; i < pipe->num_cons; ++i) {
+ uint32_t crtcs_for_connector = 0;
+ drmModeConnector *connector;
+ drmModeEncoder *encoder;
+ struct crtc *crtc;
+
+ connector = get_connector_by_id(dev, pipe->con_ids[i]);
+ if (!connector)
+ return NULL;
+
+ for (j = 0; j < connector->count_encoders; ++j) {
+ encoder = get_encoder_by_id(dev, connector->encoders[j]);
+ if (!encoder)
+ continue;
+
+ crtcs_for_connector |= encoder->possible_crtcs;
+ crtc = get_crtc_by_id(dev, encoder->crtc_id);
+ if (!crtc)
+ continue;
+ active_crtcs |= get_crtc_mask(dev, crtc);
+ }
+
+ possible_crtcs &= crtcs_for_connector;
+ }
+
+ if (!possible_crtcs)
+ return NULL;
+
+ /* Return the first possible and active CRTC if one exists, or the first
+ * possible CRTC otherwise.
+ */
+ if (possible_crtcs & active_crtcs)
+ crtc_idx = ffs(possible_crtcs & active_crtcs);
+ else
+ crtc_idx = ffs(possible_crtcs);
+
+ return &dev->resources->crtcs[crtc_idx - 1];
+}
+
+static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe)
+{
+ drmModeModeInfo *mode = NULL;
+ int i;
+
+ pipe->mode = NULL;
+
+ for (i = 0; i < (int)pipe->num_cons; i++) {
+ mode = connector_find_mode(dev, pipe->con_ids[i],
+ pipe->mode_str, pipe->vrefresh);
+ if (mode == NULL) {
+ if (pipe->vrefresh)
+ fprintf(stderr,
+ "failed to find mode "
+ "\"%s-%.2fHz\" for connector %s\n",
+ pipe->mode_str, pipe->vrefresh, pipe->cons[i]);
+ else
+ fprintf(stderr,
+ "failed to find mode \"%s\" for connector %s\n",
+ pipe->mode_str, pipe->cons[i]);
+ return -EINVAL;
+ }
+ }
+
+ /* If the CRTC ID was specified, get the corresponding CRTC. Otherwise
+ * locate a CRTC that can be attached to all the connectors.
+ */
+ if (pipe->crtc_id != (uint32_t)-1) {
+ pipe->crtc = get_crtc_by_id(dev, pipe->crtc_id);
+ } else {
+ pipe->crtc = pipe_find_crtc(dev, pipe);
+ pipe->crtc_id = pipe->crtc->crtc->crtc_id;
+ }
+
+ if (!pipe->crtc) {
+ fprintf(stderr, "failed to find CRTC for pipe\n");
+ return -EINVAL;
+ }
+
+ pipe->mode = mode;
+ pipe->crtc->mode = mode;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Properties
+ */
+
+struct property_arg {
+ uint32_t obj_id;
+ uint32_t obj_type;
+ char name[DRM_PROP_NAME_LEN+1];
+ uint32_t prop_id;
+ uint64_t value;
+ bool optional;
+};
+
+static bool set_property(struct device *dev, struct property_arg *p)
+{
+ drmModeObjectProperties *props = NULL;
+ drmModePropertyRes **props_info = NULL;
+ const char *obj_type;
+ int ret;
+ int i;
+
+ p->obj_type = 0;
+ p->prop_id = 0;
+
+#define find_object(_res, type, Type) \
+ do { \
+ for (i = 0; i < (int)(_res)->count_##type##s; ++i) { \
+ struct type *obj = &(_res)->type##s[i]; \
+ if (obj->type->type##_id != p->obj_id) \
+ continue; \
+ p->obj_type = DRM_MODE_OBJECT_##Type; \
+ obj_type = #Type; \
+ props = obj->props; \
+ props_info = obj->props_info; \
+ } \
+ } while(0) \
+
+ find_object(dev->resources, crtc, CRTC);
+ if (p->obj_type == 0)
+ find_object(dev->resources, connector, CONNECTOR);
+ if (p->obj_type == 0)
+ find_object(dev->resources, plane, PLANE);
+ if (p->obj_type == 0) {
+ fprintf(stderr, "Object %i not found, can't set property\n",
+ p->obj_id);
+ return false;
+ }
+
+ if (!props) {
+ fprintf(stderr, "%s %i has no properties\n",
+ obj_type, p->obj_id);
+ return false;
+ }
+
+ for (i = 0; i < (int)props->count_props; ++i) {
+ if (!props_info[i])
+ continue;
+ if (strcmp(props_info[i]->name, p->name) == 0)
+ break;
+ }
+
+ if (i == (int)props->count_props) {
+ if (!p->optional)
+ fprintf(stderr, "%s %i has no %s property\n",
+ obj_type, p->obj_id, p->name);
+ return false;
+ }
+
+ p->prop_id = props->props[i];
+
+ if (!dev->use_atomic)
+ ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
+ p->prop_id, p->value);
+ else
+ ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value);
+
+ if (ret < 0)
+ fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
+ obj_type, p->obj_id, p->name, p->value, strerror(errno));
+
+ return true;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void
+page_flip_handler(int fd, unsigned int frame,
+ unsigned int sec, unsigned int usec, void *data)
+{
+ struct pipe_arg *pipe;
+ unsigned int new_fb_id;
+ struct timeval end;
+ double t;
+
+ pipe = data;
+ if (pipe->current_fb_id == pipe->fb_id[0])
+ new_fb_id = pipe->fb_id[1];
+ else
+ new_fb_id = pipe->fb_id[0];
+
+ drmModePageFlip(fd, pipe->crtc_id, new_fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, pipe);
+ pipe->current_fb_id = new_fb_id;
+ pipe->swap_count++;
+ if (pipe->swap_count == 60) {
+ gettimeofday(&end, NULL);
+ t = end.tv_sec + end.tv_usec * 1e-6 -
+ (pipe->start.tv_sec + pipe->start.tv_usec * 1e-6);
+ fprintf(stderr, "freq: %.02fHz\n", pipe->swap_count / t);
+ pipe->swap_count = 0;
+ pipe->start = end;
+ }
+}
+
+static bool format_support(const drmModePlanePtr ovr, uint32_t fmt)
+{
+ unsigned int i;
+
+ for (i = 0; i < ovr->count_formats; ++i) {
+ if (ovr->formats[i] == fmt)
+ return true;
+ }
+
+ return false;
+}
+
+static void add_property(struct device *dev, uint32_t obj_id,
+ const char *name, uint64_t value)
+{
+ struct property_arg p;
+
+ p.obj_id = obj_id;
+ strcpy(p.name, name);
+ p.value = value;
+
+ set_property(dev, &p);
+}
+
+static bool add_property_optional(struct device *dev, uint32_t obj_id,
+ const char *name, uint64_t value)
+{
+ struct property_arg p;
+
+ p.obj_id = obj_id;
+ strcpy(p.name, name);
+ p.value = value;
+ p.optional = true;
+
+ return set_property(dev, &p);
+}
+
+static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
+{
+ unsigned blob_id = 0;
+ /* TODO: support 1024-sized LUTs, when the use-case arises */
+ struct drm_color_lut gamma_lut[256];
+ int i, ret;
+
+ if (fourcc == DRM_FORMAT_C8) {
+ /* TODO: Add C8 support for more patterns */
+ util_smpte_c8_gamma(256, gamma_lut);
+ drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id);
+ } else {
+ for (i = 0; i < 256; i++) {
+ gamma_lut[i].red =
+ gamma_lut[i].green =
+ gamma_lut[i].blue = i << 8;
+ }
+ }
+
+ add_property_optional(dev, crtc_id, "DEGAMMA_LUT", 0);
+ add_property_optional(dev, crtc_id, "CTM", 0);
+ if (!add_property_optional(dev, crtc_id, "GAMMA_LUT", blob_id)) {
+ uint16_t r[256], g[256], b[256];
+
+ for (i = 0; i < 256; i++) {
+ r[i] = gamma_lut[i].red;
+ g[i] = gamma_lut[i].green;
+ b[i] = gamma_lut[i].blue;
+ }
+
+ ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b);
+ if (ret)
+ fprintf(stderr, "failed to set gamma: %s\n", strerror(errno));
+ }
+}
+
+static int
+bo_fb_create(int fd, unsigned int fourcc, const uint32_t w, const uint32_t h,
+ enum util_fill_pattern pat, struct bo **out_bo, unsigned int *out_fb_id)
+{
+ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+ struct bo *bo;
+ unsigned int fb_id;
+
+ bo = bo_create(fd, fourcc, w, h, handles, pitches, offsets, pat);
+
+ if (bo == NULL)
+ return -1;
+
+ if (drmModeAddFB2(fd, w, h, fourcc, handles, pitches, offsets, &fb_id, 0)) {
+ fprintf(stderr, "failed to add fb (%ux%u): %s\n", w, h, strerror(errno));
+ bo_destroy(bo);
+ return -1;
+ }
+ *out_bo = bo;
+ *out_fb_id = fb_id;
+ return 0;
+}
+
+static int atomic_set_plane(struct device *dev, struct plane_arg *p,
+ int pattern, bool update)
+{
+ struct bo *plane_bo;
+ int crtc_x, crtc_y, crtc_w, crtc_h;
+ struct crtc *crtc = NULL;
+ unsigned int old_fb_id;
+
+ /* Find an unused plane which can be connected to our CRTC. Find the
+ * CRTC index first, then iterate over available planes.
+ */
+ crtc = get_crtc_by_id(dev, p->crtc_id);
+ if (!crtc) {
+ fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
+ return -1;
+ }
+
+ if (!update)
+ fprintf(stderr, "testing %dx%d@%s on plane %u, crtc %u\n",
+ p->w, p->h, p->format_str, p->plane_id, p->crtc_id);
+
+ plane_bo = p->old_bo;
+ p->old_bo = p->bo;
+
+ if (!plane_bo) {
+ if (bo_fb_create(dev->fd, p->fourcc, p->w, p->h,
+ pattern, &plane_bo, &p->fb_id))
+ return -1;
+ }
+
+ p->bo = plane_bo;
+
+ old_fb_id = p->fb_id;
+ p->old_fb_id = old_fb_id;
+
+ crtc_w = p->w * p->scale;
+ crtc_h = p->h * p->scale;
+ if (!p->has_position) {
+ /* Default to the middle of the screen */
+ crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+ crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
+ } else {
+ crtc_x = p->x;
+ crtc_y = p->y;
+ }
+
+ add_property(dev, p->plane_id, "FB_ID", p->fb_id);
+ add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id);
+ add_property(dev, p->plane_id, "SRC_X", 0);
+ add_property(dev, p->plane_id, "SRC_Y", 0);
+ add_property(dev, p->plane_id, "SRC_W", p->w << 16);
+ add_property(dev, p->plane_id, "SRC_H", p->h << 16);
+ add_property(dev, p->plane_id, "CRTC_X", crtc_x);
+ add_property(dev, p->plane_id, "CRTC_Y", crtc_y);
+ add_property(dev, p->plane_id, "CRTC_W", crtc_w);
+ add_property(dev, p->plane_id, "CRTC_H", crtc_h);
+
+ return 0;
+}
+
+static int set_plane(struct device *dev, struct plane_arg *p)
+{
+ drmModePlane *ovr;
+ uint32_t plane_id;
+ int crtc_x, crtc_y, crtc_w, crtc_h;
+ struct crtc *crtc = NULL;
+ unsigned int i, crtc_mask;
+
+ /* Find an unused plane which can be connected to our CRTC. Find the
+ * CRTC index first, then iterate over available planes.
+ */
+ crtc = get_crtc_by_id(dev, p->crtc_id);
+ if (!crtc) {
+ fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
+ return -1;
+ }
+ crtc_mask = get_crtc_mask(dev, crtc);
+ plane_id = p->plane_id;
+
+ for (i = 0; i < dev->resources->count_planes; i++) {
+ ovr = dev->resources->planes[i].plane;
+ if (!ovr)
+ continue;
+
+ if (plane_id && plane_id != ovr->plane_id)
+ continue;
+
+ if (!format_support(ovr, p->fourcc))
+ continue;
+
+ if ((ovr->possible_crtcs & crtc_mask) &&
+ (ovr->crtc_id == 0 || ovr->crtc_id == p->crtc_id)) {
+ plane_id = ovr->plane_id;
+ break;
+ }
+ }
+
+ if (i == dev->resources->count_planes) {
+ fprintf(stderr, "no unused plane available for CRTC %u\n",
+ p->crtc_id);
+ return -1;
+ }
+
+ fprintf(stderr, "testing %dx%d@%s overlay plane %u\n",
+ p->w, p->h, p->format_str, plane_id);
+
+ /* just use single plane format for now.. */
+ if (bo_fb_create(dev->fd, p->fourcc, p->w, p->h,
+ secondary_fill, &p->bo, &p->fb_id))
+ return -1;
+
+ crtc_w = p->w * p->scale;
+ crtc_h = p->h * p->scale;
+ if (!p->has_position) {
+ /* Default to the middle of the screen */
+ crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+ crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
+ } else {
+ crtc_x = p->x;
+ crtc_y = p->y;
+ }
+
+ /* note src coords (last 4 args) are in Q16 format */
+ if (drmModeSetPlane(dev->fd, plane_id, p->crtc_id, p->fb_id,
+ 0, crtc_x, crtc_y, crtc_w, crtc_h,
+ 0, 0, p->w << 16, p->h << 16)) {
+ fprintf(stderr, "failed to enable plane: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ ovr->crtc_id = p->crtc_id;
+
+ return 0;
+}
+
+static void atomic_set_planes(struct device *dev, struct plane_arg *p,
+ unsigned int count, bool update)
+{
+ unsigned int i, pattern = primary_fill;
+
+ /* set up planes */
+ for (i = 0; i < count; i++) {
+ if (i > 0)
+ pattern = secondary_fill;
+ else
+ set_gamma(dev, p[i].crtc_id, p[i].fourcc);
+
+ if (atomic_set_plane(dev, &p[i], pattern, update))
+ return;
+ }
+}
+
+static void
+atomic_test_page_flip(struct device *dev, struct pipe_arg *pipe_args,
+ struct plane_arg *plane_args, unsigned int plane_count)
+{
+ int ret;
+
+ gettimeofday(&pipe_args->start, NULL);
+ pipe_args->swap_count = 0;
+
+ while (true) {
+ drmModeAtomicFree(dev->req);
+ dev->req = drmModeAtomicAlloc();
+ atomic_set_planes(dev, plane_args, plane_count, true);
+
+ ret = drmModeAtomicCommit(dev->fd, dev->req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed [2]\n");
+ return;
+ }
+
+ pipe_args->swap_count++;
+ if (pipe_args->swap_count == 60) {
+ struct timeval end;
+ double t;
+
+ gettimeofday(&end, NULL);
+ t = end.tv_sec + end.tv_usec * 1e-6 -
+ (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6);
+ fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t);
+ pipe_args->swap_count = 0;
+ pipe_args->start = end;
+ }
+ }
+}
+
+static void atomic_clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ add_property(dev, p[i].plane_id, "FB_ID", 0);
+ add_property(dev, p[i].plane_id, "CRTC_ID", 0);
+ add_property(dev, p[i].plane_id, "SRC_X", 0);
+ add_property(dev, p[i].plane_id, "SRC_Y", 0);
+ add_property(dev, p[i].plane_id, "SRC_W", 0);
+ add_property(dev, p[i].plane_id, "SRC_H", 0);
+ add_property(dev, p[i].plane_id, "CRTC_X", 0);
+ add_property(dev, p[i].plane_id, "CRTC_Y", 0);
+ add_property(dev, p[i].plane_id, "CRTC_W", 0);
+ add_property(dev, p[i].plane_id, "CRTC_H", 0);
+ }
+}
+
+static void atomic_clear_FB(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ if (p[i].fb_id) {
+ drmModeRmFB(dev->fd, p[i].fb_id);
+ p[i].fb_id = 0;
+ }
+ if (p[i].old_fb_id) {
+ drmModeRmFB(dev->fd, p[i].old_fb_id);
+ p[i].old_fb_id = 0;
+ }
+ if (p[i].bo) {
+ bo_destroy(p[i].bo);
+ p[i].bo = NULL;
+ }
+ if (p[i].old_bo) {
+ bo_destroy(p[i].old_bo);
+ p[i].old_bo = NULL;
+ }
+
+ }
+}
+
+static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ if (p[i].fb_id)
+ drmModeRmFB(dev->fd, p[i].fb_id);
+ if (p[i].bo)
+ bo_destroy(p[i].bo);
+ }
+}
+
+static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
+{
+ drmModeConnector *connector;
+ unsigned int i;
+ uint32_t id;
+ char *endp;
+
+ for (i = 0; i < pipe->num_cons; i++) {
+ id = strtoul(pipe->cons[i], &endp, 10);
+ if (endp == pipe->cons[i]) {
+ connector = get_connector_by_name(dev, pipe->cons[i]);
+ if (!connector) {
+ fprintf(stderr, "no connector named '%s'\n",
+ pipe->cons[i]);
+ return -ENODEV;
+ }
+
+ id = connector->connector_id;
+ }
+
+ pipe->con_ids[i] = id;
+ }
+
+ return 0;
+}
+
+static int pipe_attempt_connector(struct device *dev, drmModeConnector *con,
+ struct pipe_arg *pipe)
+{
+ char *con_str;
+ int i;
+
+ con_str = calloc(8, sizeof(char));
+ if (!con_str)
+ return -1;
+
+ sprintf(con_str, "%d", con->connector_id);
+ strcpy(pipe->format_str, "XR24");
+ pipe->fourcc = util_format_fourcc(pipe->format_str);
+ pipe->num_cons = 1;
+ pipe->con_ids = calloc(1, sizeof(*pipe->con_ids));
+ pipe->cons = calloc(1, sizeof(*pipe->cons));
+
+ if (!pipe->con_ids || !pipe->cons)
+ goto free_con_str;
+
+ pipe->con_ids[0] = con->connector_id;
+ pipe->cons[0] = (const char*)con_str;
+
+ pipe->crtc = pipe_find_crtc(dev, pipe);
+ if (!pipe->crtc)
+ goto free_all;
+
+ pipe->crtc_id = pipe->crtc->crtc->crtc_id;
+
+ /* Return the first mode if no preferred. */
+ pipe->mode = &con->modes[0];
+
+ for (i = 0; i < con->count_modes; i++) {
+ drmModeModeInfo *current_mode = &con->modes[i];
+
+ if (current_mode->type & DRM_MODE_TYPE_PREFERRED) {
+ pipe->mode = current_mode;
+ break;
+ }
+ }
+
+ sprintf(pipe->mode_str, "%dx%d", pipe->mode->hdisplay, pipe->mode->vdisplay);
+
+ return 0;
+
+free_all:
+ free(pipe->cons);
+ free(pipe->con_ids);
+free_con_str:
+ free(con_str);
+ return -1;
+}
+
+static int pipe_find_preferred(struct device *dev, struct pipe_arg **out_pipes)
+{
+ struct pipe_arg *pipes;
+ struct resources *res = dev->resources;
+ drmModeConnector *con = NULL;
+ int i, connected = 0, attempted = 0;
+
+ for (i = 0; i < res->count_connectors; i++) {
+ con = res->connectors[i].connector;
+ if (!con || con->connection != DRM_MODE_CONNECTED)
+ continue;
+ connected++;
+ }
+ if (!connected) {
+ printf("no connected connector!\n");
+ return 0;
+ }
+
+ pipes = calloc(connected, sizeof(struct pipe_arg));
+ if (!pipes)
+ return 0;
+
+ for (i = 0; i < res->count_connectors && attempted < connected; i++) {
+ con = res->connectors[i].connector;
+ if (!con || con->connection != DRM_MODE_CONNECTED)
+ continue;
+
+ if (pipe_attempt_connector(dev, con, &pipes[attempted]) < 0) {
+ printf("failed fetching preferred mode for connector\n");
+ continue;
+ }
+ attempted++;
+ }
+
+ *out_pipes = pipes;
+ return attempted;
+}
+
+static struct plane *get_primary_plane_by_crtc(struct device *dev, struct crtc *crtc)
+{
+ unsigned int i;
+
+ for (i = 0; i < dev->resources->count_planes; i++) {
+ struct plane *plane = &dev->resources->planes[i];
+ drmModePlane *ovr = plane->plane;
+ if (!ovr)
+ continue;
+
+ // XXX: add is_primary_plane and (?) format checks
+
+ if (ovr->possible_crtcs & get_crtc_mask(dev, crtc))
+ return plane;
+ }
+ return NULL;
+}
+
+static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ unsigned int i, j;
+ int ret, x = 0;
+ int preferred = count == 0;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ ret = pipe_resolve_connectors(dev, pipe);
+ if (ret < 0)
+ return;
+
+ ret = pipe_find_crtc_and_mode(dev, pipe);
+ if (ret < 0)
+ continue;
+ }
+ if (preferred) {
+ struct pipe_arg *pipe_args;
+
+ count = pipe_find_preferred(dev, &pipe_args);
+ if (!count) {
+ fprintf(stderr, "can't find any preferred connector/mode.\n");
+ return;
+ }
+ pipes = pipe_args;
+ }
+
+ if (!dev->use_atomic) {
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ if (pipe->mode == NULL)
+ continue;
+
+ if (!preferred) {
+ dev->mode.width += pipe->mode->hdisplay;
+ if (dev->mode.height < pipe->mode->vdisplay)
+ dev->mode.height = pipe->mode->vdisplay;
+ } else {
+ /* XXX: Use a clone mode, more like atomic. We could do per
+ * connector bo/fb, so we don't have the stretched image.
+ */
+ if (dev->mode.width < pipe->mode->hdisplay)
+ dev->mode.width = pipe->mode->hdisplay;
+ if (dev->mode.height < pipe->mode->vdisplay)
+ dev->mode.height = pipe->mode->vdisplay;
+ }
+ }
+
+ if (bo_fb_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height,
+ primary_fill, &dev->mode.bo, &dev->mode.fb_id))
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+ uint32_t blob_id;
+
+ if (pipe->mode == NULL)
+ continue;
+
+ printf("setting mode %s-%.2fHz on connectors ",
+ pipe->mode->name, mode_vrefresh(pipe->mode));
+ for (j = 0; j < pipe->num_cons; ++j) {
+ printf("%s, ", pipe->cons[j]);
+ if (dev->use_atomic)
+ add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc_id);
+ }
+ printf("crtc %d\n", pipe->crtc_id);
+
+ if (!dev->use_atomic) {
+ ret = drmModeSetCrtc(dev->fd, pipe->crtc_id, dev->mode.fb_id,
+ x, 0, pipe->con_ids, pipe->num_cons,
+ pipe->mode);
+
+ /* XXX: Actually check if this is needed */
+ drmModeDirtyFB(dev->fd, dev->mode.fb_id, NULL, 0);
+
+ if (!preferred)
+ x += pipe->mode->hdisplay;
+
+ if (ret) {
+ fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
+ return;
+ }
+
+ set_gamma(dev, pipe->crtc_id, pipe->fourcc);
+ } else {
+ drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id);
+ add_property(dev, pipe->crtc_id, "MODE_ID", blob_id);
+ add_property(dev, pipe->crtc_id, "ACTIVE", 1);
+
+ /* By default atomic modeset does not set a primary plane, shrug */
+ if (preferred) {
+ struct plane *plane = get_primary_plane_by_crtc(dev, pipe->crtc);
+ struct plane_arg plane_args = {
+ .plane_id = plane->plane->plane_id,
+ .crtc_id = pipe->crtc_id,
+ .w = pipe->mode->hdisplay,
+ .h = pipe->mode->vdisplay,
+ .scale = 1.0,
+ .format_str = "XR24",
+ .fourcc = util_format_fourcc(pipe->format_str),
+ };
+
+ atomic_set_planes(dev, &plane_args, 1, false);
+ }
+ }
+ }
+}
+
+static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ unsigned int i;
+ unsigned int j;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ if (pipe->mode == NULL)
+ continue;
+
+ for (j = 0; j < pipe->num_cons; ++j)
+ add_property(dev, pipe->con_ids[j], "CRTC_ID",0);
+
+ add_property(dev, pipe->crtc_id, "MODE_ID", 0);
+ add_property(dev, pipe->crtc_id, "ACTIVE", 0);
+ }
+}
+
+static void clear_mode(struct device *dev)
+{
+ if (dev->mode.fb_id)
+ drmModeRmFB(dev->fd, dev->mode.fb_id);
+ if (dev->mode.bo)
+ bo_destroy(dev->mode.bo);
+}
+
+static void set_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+ unsigned int i;
+
+ /* set up planes/overlays */
+ for (i = 0; i < count; i++)
+ if (set_plane(dev, &p[i]))
+ return;
+}
+
+static void set_cursors(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+ uint32_t cw = 64;
+ uint32_t ch = 64;
+ struct bo *bo;
+ uint64_t value;
+ unsigned int i;
+ int ret;
+
+ ret = drmGetCap(dev->fd, DRM_CAP_CURSOR_WIDTH, &value);
+ if (!ret)
+ cw = value;
+
+ ret = drmGetCap(dev->fd, DRM_CAP_CURSOR_HEIGHT, &value);
+ if (!ret)
+ ch = value;
+
+
+ /* create cursor bo.. just using PATTERN_PLAIN as it has
+ * translucent alpha
+ */
+ bo = bo_create(dev->fd, DRM_FORMAT_ARGB8888, cw, ch, handles, pitches,
+ offsets, UTIL_PATTERN_PLAIN);
+ if (bo == NULL)
+ return;
+
+ dev->mode.cursor_bo = bo;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+ ret = cursor_init(dev->fd, handles[0],
+ pipe->crtc_id,
+ pipe->mode->hdisplay, pipe->mode->vdisplay,
+ cw, ch);
+ if (ret) {
+ fprintf(stderr, "failed to init cursor for CRTC[%u]\n",
+ pipe->crtc_id);
+ return;
+ }
+ }
+
+ cursor_start();
+}
+
+static void clear_cursors(struct device *dev)
+{
+ cursor_stop();
+
+ if (dev->mode.cursor_bo)
+ bo_destroy(dev->mode.cursor_bo);
+}
+
+static void test_page_flip(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+ unsigned int other_fb_id;
+ struct bo *other_bo;
+ drmEventContext evctx;
+ unsigned int i;
+ int ret;
+
+ if (bo_fb_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height,
+ UTIL_PATTERN_PLAIN, &other_bo, &other_fb_id))
+ return;
+
+ for (i = 0; i < count; i++) {
+ struct pipe_arg *pipe = &pipes[i];
+
+ if (pipe->mode == NULL)
+ continue;
+
+ ret = drmModePageFlip(dev->fd, pipe->crtc_id,
+ other_fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+ pipe);
+ if (ret) {
+ fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
+ goto err_rmfb;
+ }
+ gettimeofday(&pipe->start, NULL);
+ pipe->swap_count = 0;
+ pipe->fb_id[0] = dev->mode.fb_id;
+ pipe->fb_id[1] = other_fb_id;
+ pipe->current_fb_id = other_fb_id;
+ }
+
+ memset(&evctx, 0, sizeof evctx);
+ evctx.version = DRM_EVENT_CONTEXT_VERSION;
+ evctx.vblank_handler = NULL;
+ evctx.page_flip_handler = page_flip_handler;
+
+ while (1) {
+#if 0
+ struct pollfd pfd[2];
+
+ pfd[0].fd = 0;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = fd;
+ pfd[1].events = POLLIN;
+
+ if (poll(pfd, 2, -1) < 0) {
+ fprintf(stderr, "poll error\n");
+ break;
+ }
+
+ if (pfd[0].revents)
+ break;
+#else
+ struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ FD_SET(dev->fd, &fds);
+ ret = select(dev->fd + 1, &fds, NULL, NULL, &timeout);
+
+ if (ret <= 0) {
+ fprintf(stderr, "select timed out or error (ret %d)\n",
+ ret);
+ continue;
+ } else if (FD_ISSET(0, &fds)) {
+ break;
+ }
+#endif
+
+ drmHandleEvent(dev->fd, &evctx);
+ }
+
+err_rmfb:
+ drmModeRmFB(dev->fd, other_fb_id);
+ bo_destroy(other_bo);
+}
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+static int parse_connector(struct pipe_arg *pipe, const char *arg)
+{
+ unsigned int len;
+ unsigned int i;
+ const char *p;
+ char *endp;
+
+ pipe->vrefresh = 0;
+ pipe->crtc_id = (uint32_t)-1;
+ strcpy(pipe->format_str, "XR24");
+
+ /* Count the number of connectors and allocate them. */
+ pipe->num_cons = 1;
+ for (p = arg; *p && *p != ':' && *p != '@'; ++p) {
+ if (*p == ',')
+ pipe->num_cons++;
+ }
+
+ pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
+ pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
+ if (pipe->con_ids == NULL || pipe->cons == NULL)
+ return -1;
+
+ /* Parse the connectors. */
+ for (i = 0, p = arg; i < pipe->num_cons; ++i, p = endp + 1) {
+ endp = strpbrk(p, ",@:");
+ if (!endp)
+ break;
+
+ pipe->cons[i] = strndup(p, endp - p);
+
+ if (*endp != ',')
+ break;
+ }
+
+ if (i != pipe->num_cons - 1)
+ return -1;
+
+ /* Parse the remaining parameters. */
+ if (!endp)
+ return -1;
+ if (*endp == '@') {
+ arg = endp + 1;
+ pipe->crtc_id = strtoul(arg, &endp, 10);
+ }
+ if (*endp != ':')
+ return -1;
+
+ arg = endp + 1;
+
+ /* Search for the vertical refresh or the format. */
+ p = strpbrk(arg, "-@");
+ if (p == NULL)
+ p = arg + strlen(arg);
+ len = min(sizeof pipe->mode_str - 1, (unsigned int)(p - arg));
+ strncpy(pipe->mode_str, arg, len);
+ pipe->mode_str[len] = '\0';
+
+ if (*p == '-') {
+ pipe->vrefresh = strtof(p + 1, &endp);
+ p = endp;
+ }
+
+ if (*p == '@') {
+ strncpy(pipe->format_str, p + 1, 4);
+ pipe->format_str[4] = '\0';
+ }
+
+ pipe->fourcc = util_format_fourcc(pipe->format_str);
+ if (pipe->fourcc == 0) {
+ fprintf(stderr, "unknown format %s\n", pipe->format_str);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int parse_plane(struct plane_arg *plane, const char *p)
+{
+ char *end;
+
+ plane->plane_id = strtoul(p, &end, 10);
+ if (*end != '@')
+ return -EINVAL;
+
+ p = end + 1;
+ plane->crtc_id = strtoul(p, &end, 10);
+ if (*end != ':')
+ return -EINVAL;
+
+ p = end + 1;
+ plane->w = strtoul(p, &end, 10);
+ if (*end != 'x')
+ return -EINVAL;
+
+ p = end + 1;
+ plane->h = strtoul(p, &end, 10);
+
+ if (*end == '+' || *end == '-') {
+ plane->x = strtol(end, &end, 10);
+ if (*end != '+' && *end != '-')
+ return -EINVAL;
+ plane->y = strtol(end, &end, 10);
+
+ plane->has_position = true;
+ }
+
+ if (*end == '*') {
+ p = end + 1;
+ plane->scale = strtod(p, &end);
+ if (plane->scale <= 0.0)
+ return -EINVAL;
+ } else {
+ plane->scale = 1.0;
+ }
+
+ if (*end == '@') {
+ strncpy(plane->format_str, end + 1, 4);
+ plane->format_str[4] = '\0';
+ } else {
+ strcpy(plane->format_str, "XR24");
+ }
+
+ plane->fourcc = util_format_fourcc(plane->format_str);
+ if (plane->fourcc == 0) {
+ fprintf(stderr, "unknown format %s\n", plane->format_str);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int parse_property(struct property_arg *p, const char *arg)
+{
+ if (sscanf(arg, "%d:%32[^:]:%" SCNu64, &p->obj_id, p->name, &p->value) != 3)
+ return -1;
+
+ p->obj_type = 0;
+ p->name[DRM_PROP_NAME_LEN] = '\0';
+
+ return 0;
+}
+
+static void parse_fill_patterns(char *arg)
+{
+ char *fill = strtok(arg, ",");
+ if (!fill)
+ return;
+ primary_fill = util_pattern_enum(fill);
+ fill = strtok(NULL, ",");
+ if (!fill)
+ return;
+ secondary_fill = util_pattern_enum(fill);
+}
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-acDdefMPpsCvrw]\n", name);
+
+ fprintf(stderr, "\n Query options:\n\n");
+ fprintf(stderr, "\t-c\tlist connectors\n");
+ fprintf(stderr, "\t-e\tlist encoders\n");
+ fprintf(stderr, "\t-f\tlist framebuffers\n");
+ fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
+
+ fprintf(stderr, "\n Test options:\n\n");
+ fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
+ fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]\tset a mode\n");
+ fprintf(stderr, "\t-C\ttest hw cursor\n");
+ fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
+ fprintf(stderr, "\t-r\tset the preferred mode for all connectors\n");
+ fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
+ fprintf(stderr, "\t-a \tuse atomic API\n");
+ fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n");
+
+ fprintf(stderr, "\n Generic options:\n\n");
+ fprintf(stderr, "\t-d\tdrop master after mode set\n");
+ fprintf(stderr, "\t-M module\tuse the given driver\n");
+ fprintf(stderr, "\t-D device\tuse the given device\n");
+
+ fprintf(stderr, "\n\tDefault is to dump all info.\n");
+ exit(0);
+}
+
+static char optstr[] = "acdD:efF:M:P:ps:Cvrw:";
+
+int main(int argc, char **argv)
+{
+ struct device dev;
+
+ int c;
+ int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
+ int drop_master = 0;
+ int test_vsync = 0;
+ int test_cursor = 0;
+ int set_preferred = 0;
+ int use_atomic = 0;
+ char *device = NULL;
+ char *module = NULL;
+ unsigned int i;
+ unsigned int count = 0, plane_count = 0;
+ unsigned int prop_count = 0;
+ struct pipe_arg *pipe_args = NULL;
+ struct plane_arg *plane_args = NULL;
+ struct property_arg *prop_args = NULL;
+ unsigned int args = 0;
+ int ret;
+
+ memset(&dev, 0, sizeof dev);
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ args++;
+
+ switch (c) {
+ case 'a':
+ use_atomic = 1;
+ /* Preserve the default behaviour of dumping all information. */
+ args--;
+ break;
+ case 'c':
+ connectors = 1;
+ break;
+ case 'D':
+ device = optarg;
+ /* Preserve the default behaviour of dumping all information. */
+ args--;
+ break;
+ case 'd':
+ drop_master = 1;
+ break;
+ case 'e':
+ encoders = 1;
+ break;
+ case 'f':
+ framebuffers = 1;
+ break;
+ case 'F':
+ parse_fill_patterns(optarg);
+ break;
+ case 'M':
+ module = optarg;
+ /* Preserve the default behaviour of dumping all information. */
+ args--;
+ break;
+ case 'P':
+ plane_args = realloc(plane_args,
+ (plane_count + 1) * sizeof *plane_args);
+ if (plane_args == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return 1;
+ }
+ memset(&plane_args[plane_count], 0, sizeof(*plane_args));
+
+ if (parse_plane(&plane_args[plane_count], optarg) < 0)
+ usage(argv[0]);
+
+ plane_count++;
+ break;
+ case 'p':
+ crtcs = 1;
+ planes = 1;
+ break;
+ case 's':
+ pipe_args = realloc(pipe_args,
+ (count + 1) * sizeof *pipe_args);
+ if (pipe_args == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return 1;
+ }
+ memset(&pipe_args[count], 0, sizeof(*pipe_args));
+
+ if (parse_connector(&pipe_args[count], optarg) < 0)
+ usage(argv[0]);
+
+ count++;
+ break;
+ case 'C':
+ test_cursor = 1;
+ break;
+ case 'v':
+ test_vsync = 1;
+ break;
+ case 'r':
+ set_preferred = 1;
+ break;
+ case 'w':
+ prop_args = realloc(prop_args,
+ (prop_count + 1) * sizeof *prop_args);
+ if (prop_args == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return 1;
+ }
+ memset(&prop_args[prop_count], 0, sizeof(*prop_args));
+
+ if (parse_property(&prop_args[prop_count], optarg) < 0)
+ usage(argv[0]);
+
+ prop_count++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ /* Dump all the details when no* arguments are provided. */
+ if (!args)
+ encoders = connectors = crtcs = planes = framebuffers = 1;
+
+ if (test_vsync && !count) {
+ fprintf(stderr, "page flipping requires at least one -s option.\n");
+ return -1;
+ }
+ if (set_preferred && count) {
+ fprintf(stderr, "cannot use -r (preferred) when -s (mode) is set\n");
+ return -1;
+ }
+
+ if (set_preferred && plane_count) {
+ fprintf(stderr, "cannot use -r (preferred) when -P (plane) is set\n");
+ return -1;
+ }
+
+ dev.fd = util_open(device, module);
+ if (dev.fd < 0)
+ return -1;
+
+ if (use_atomic) {
+ ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
+ if (ret) {
+ fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
+ drmClose(dev.fd);
+ return -1;
+ }
+ }
+
+ dev.use_atomic = use_atomic;
+
+ dev.resources = get_resources(&dev);
+ if (!dev.resources) {
+ drmClose(dev.fd);
+ return 1;
+ }
+
+#define dump_resource(dev, res) if (res) dump_##res(dev)
+
+ dump_resource(&dev, encoders);
+ dump_resource(&dev, connectors);
+ dump_resource(&dev, crtcs);
+ dump_resource(&dev, planes);
+ dump_resource(&dev, framebuffers);
+
+ for (i = 0; i < prop_count; ++i)
+ set_property(&dev, &prop_args[i]);
+
+ if (dev.use_atomic) {
+ dev.req = drmModeAtomicAlloc();
+
+ if (set_preferred || (count && plane_count)) {
+ uint64_t cap = 0;
+
+ ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+ if (ret || cap == 0) {
+ fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+ return 1;
+ }
+
+ if (set_preferred || count)
+ set_mode(&dev, pipe_args, count);
+
+ if (plane_count)
+ atomic_set_planes(&dev, plane_args, plane_count, false);
+
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret) {
+ fprintf(stderr, "Atomic Commit failed [1]\n");
+ return 1;
+ }
+
+ if (test_vsync)
+ atomic_test_page_flip(&dev, pipe_args, plane_args, plane_count);
+
+ if (drop_master)
+ drmDropMaster(dev.fd);
+
+ getchar();
+
+ drmModeAtomicFree(dev.req);
+ dev.req = drmModeAtomicAlloc();
+
+ /* XXX: properly teardown the preferred mode/plane state */
+ if (plane_count)
+ atomic_clear_planes(&dev, plane_args, plane_count);
+
+ if (count)
+ atomic_clear_mode(&dev, pipe_args, count);
+
+ ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret)
+ fprintf(stderr, "Atomic Commit failed\n");
+
+ if (plane_count)
+ atomic_clear_FB(&dev, plane_args, plane_count);
+ }
+
+ drmModeAtomicFree(dev.req);
+ } else {
+ if (set_preferred || count || plane_count) {
+ uint64_t cap = 0;
+
+ ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+ if (ret || cap == 0) {
+ fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+ return 1;
+ }
+
+ if (set_preferred || count)
+ set_mode(&dev, pipe_args, count);
+
+ if (plane_count)
+ set_planes(&dev, plane_args, plane_count);
+
+ if (test_cursor)
+ set_cursors(&dev, pipe_args, count);
+
+ if (test_vsync)
+ test_page_flip(&dev, pipe_args, count);
+
+ if (drop_master)
+ drmDropMaster(dev.fd);
+
+ getchar();
+
+ if (test_cursor)
+ clear_cursors(&dev);
+
+ if (plane_count)
+ clear_planes(&dev, plane_args, plane_count);
+
+ if (set_preferred || count)
+ clear_mode(&dev);
+ }
+ }
+
+ free_resources(dev.resources);
+ drmClose(dev.fd);
+
+ return 0;
+}
diff --git a/tests/nouveau/.gitignore b/tests/nouveau/.gitignore
new file mode 100644
index 0000000..837bfb9
--- /dev/null
+++ b/tests/nouveau/.gitignore
@@ -0,0 +1 @@
+threaded
diff --git a/tests/nouveau/meson.build b/tests/nouveau/meson.build
new file mode 100644
index 0000000..ca4d44f
--- /dev/null
+++ b/tests/nouveau/meson.build
@@ -0,0 +1,30 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+threaded = executable(
+ 'threaded',
+ files('threaded.c'),
+ dependencies : [dep_dl, dep_threads],
+ include_directories : [inc_root, inc_drm, include_directories('../../nouveau')],
+ link_with : [libdrm, libdrm_nouveau],
+ c_args : libdrm_c_args,
+)
+
+test('threaded', threaded)
diff --git a/tests/nouveau/threaded.c b/tests/nouveau/threaded.c
new file mode 100644
index 0000000..eaa469e
--- /dev/null
+++ b/tests/nouveau/threaded.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright © 2015 Canonical Ltd. (Maarten Lankhorst)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <sys/ioctl.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "xf86drm.h"
+#include "nouveau.h"
+
+static __typeof__(ioctl) *old_ioctl;
+static int failed;
+
+static int import_fd;
+
+#if defined(__GLIBC__) || defined(__FreeBSD__)
+int ioctl(int fd, unsigned long request, ...)
+#else
+int ioctl(int fd, int request, ...)
+#endif
+{
+ va_list va;
+ int ret;
+ void *arg;
+
+ va_start(va, request);
+ arg = va_arg(va, void *);
+ ret = old_ioctl(fd, request, arg);
+ va_end(va);
+
+ if (ret < 0 && request == DRM_IOCTL_GEM_CLOSE && errno == EINVAL)
+ failed = 1;
+
+ return ret;
+}
+
+static void *
+openclose(void *dev)
+{
+ struct nouveau_device *nvdev = dev;
+ struct nouveau_bo *bo = NULL;
+ int i;
+
+ for (i = 0; i < 100000; ++i) {
+ if (!nouveau_bo_prime_handle_ref(nvdev, import_fd, &bo))
+ nouveau_bo_ref(NULL, &bo);
+ }
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ drmVersionPtr version;
+ const char *device = NULL;
+ int err, fd, fd2;
+ struct nouveau_device *nvdev, *nvdev2;
+ struct nouveau_bo *bo;
+ pthread_t t1, t2;
+
+ old_ioctl = dlsym(RTLD_NEXT, "ioctl");
+
+ if (argc < 2) {
+ fd = drmOpenWithType("nouveau", NULL, DRM_NODE_RENDER);
+ if (fd >= 0)
+ fd2 = drmOpenWithType("nouveau", NULL, DRM_NODE_RENDER);
+ } else {
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd >= 0)
+ fd2 = open(device, O_RDWR);
+ else
+ fd2 = fd = -errno;
+ }
+
+ if (fd < 0) {
+ fprintf(stderr, "Opening nouveau render node failed with %i\n", fd);
+ return device ? -fd : 77;
+ }
+
+ if (fd2 < 0) {
+ fprintf(stderr, "Opening second nouveau render node failed with %i\n", -errno);
+ return errno;
+ }
+
+ version = drmGetVersion(fd);
+ if (version) {
+ printf("Version: %d.%d.%d\n", version->version_major,
+ version->version_minor, version->version_patchlevel);
+ printf(" Name: %s\n", version->name);
+ printf(" Date: %s\n", version->date);
+ printf(" Description: %s\n", version->desc);
+
+ drmFreeVersion(version);
+ }
+
+ err = nouveau_device_wrap(fd, 0, &nvdev);
+ if (!err)
+ err = nouveau_device_wrap(fd2, 0, &nvdev2);
+ if (err < 0)
+ return 1;
+
+ err = nouveau_bo_new(nvdev2, NOUVEAU_BO_GART, 0, 4096, NULL, &bo);
+ if (!err)
+ err = nouveau_bo_set_prime(bo, &import_fd);
+
+ if (!err) {
+ pthread_create(&t1, NULL, openclose, nvdev);
+ pthread_create(&t2, NULL, openclose, nvdev);
+ }
+
+ pthread_join(t1, NULL);
+ pthread_join(t2, NULL);
+
+ close(import_fd);
+ nouveau_bo_ref(NULL, &bo);
+
+ nouveau_device_del(&nvdev2);
+ nouveau_device_del(&nvdev);
+ if (device) {
+ close(fd2);
+ close(fd);
+ } else {
+ drmClose(fd2);
+ drmClose(fd);
+ }
+
+ if (failed)
+ fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed with EINVAL,\n"
+ "race in opening/closing bo is likely.\n");
+
+ return failed;
+}
diff --git a/tests/proptest/Android.mk b/tests/proptest/Android.mk
new file mode 100644
index 0000000..91a590f
--- /dev/null
+++ b/tests/proptest/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Makefile.sources
+
+LOCAL_SRC_FILES := $(PROPTEST_FILES)
+
+LOCAL_MODULE := proptest
+
+LOCAL_SHARED_LIBRARIES := libdrm
+LOCAL_STATIC_LIBRARIES := libdrm_util
+
+include $(LIBDRM_COMMON_MK)
+include $(BUILD_EXECUTABLE)
diff --git a/tests/proptest/Makefile.sources b/tests/proptest/Makefile.sources
new file mode 100644
index 0000000..446110d
--- /dev/null
+++ b/tests/proptest/Makefile.sources
@@ -0,0 +1,2 @@
+PROPTEST_FILES := \
+ proptest.c
diff --git a/tests/proptest/meson.build b/tests/proptest/meson.build
new file mode 100644
index 0000000..9c87965
--- /dev/null
+++ b/tests/proptest/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+proptest = executable(
+ 'proptest',
+ files('proptest.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_tests, inc_drm],
+ link_with : [libdrm, libutil],
+ install : with_install_tests,
+)
diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c
new file mode 100644
index 0000000..97cb01f
--- /dev/null
+++ b/tests/proptest/proptest.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Paulo Zanoni <paulo.r.zanoni@intel.com>
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "util/common.h"
+#include "util/kms.h"
+
+static inline int64_t U642I64(uint64_t val)
+{
+ return (int64_t)*((int64_t *)&val);
+}
+
+int fd;
+drmModeResPtr res = NULL;
+
+/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */
+static void
+dump_blob(uint32_t blob_id)
+{
+ uint32_t i;
+ unsigned char *blob_data;
+ drmModePropertyBlobPtr blob;
+
+ blob = drmModeGetPropertyBlob(fd, blob_id);
+ if (!blob) {
+ printf("\n");
+ return;
+ }
+
+ blob_data = blob->data;
+
+ for (i = 0; i < blob->length; i++) {
+ if (i % 16 == 0)
+ printf("\n\t\t\t");
+ printf("%.2hhx", blob_data[i]);
+ }
+ printf("\n");
+
+ drmModeFreePropertyBlob(blob);
+}
+
+static void
+dump_prop(uint32_t prop_id, uint64_t value)
+{
+ int i;
+ drmModePropertyPtr prop;
+
+ prop = drmModeGetProperty(fd, prop_id);
+
+ printf("\t%d", prop_id);
+ if (!prop) {
+ printf("\n");
+ return;
+ }
+
+ printf(" %s:\n", prop->name);
+
+ printf("\t\tflags:");
+ if (prop->flags & DRM_MODE_PROP_PENDING)
+ printf(" pending");
+ if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
+ printf(" immutable");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
+ printf(" signed range");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
+ printf(" range");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
+ printf(" enum");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
+ printf(" bitmask");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
+ printf(" blob");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
+ printf(" object");
+ printf("\n");
+
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_values; i++)
+ printf(" %"PRId64, U642I64(prop->values[i]));
+ printf("\n");
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_values; i++)
+ printf(" %"PRIu64, prop->values[i]);
+ printf("\n");
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
+ printf("\t\tenums:");
+ for (i = 0; i < prop->count_enums; i++)
+ printf(" %s=%"PRIu64, prop->enums[i].name,
+ (uint64_t)prop->enums[i].value);
+ printf("\n");
+ } else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
+ printf("\t\tvalues:");
+ for (i = 0; i < prop->count_enums; i++)
+ printf(" %s=0x%llx", prop->enums[i].name,
+ (1LL << prop->enums[i].value));
+ printf("\n");
+ } else {
+ assert(prop->count_enums == 0);
+ }
+
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
+ printf("\t\tblobs:\n");
+ for (i = 0; i < prop->count_blobs; i++)
+ dump_blob(prop->blob_ids[i]);
+ printf("\n");
+ } else {
+ assert(prop->count_blobs == 0);
+ }
+
+ printf("\t\tvalue:");
+ if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
+ dump_blob(value);
+ else if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
+ printf(" %"PRId64"\n", value);
+ else
+ printf(" %"PRIu64"\n", value);
+
+ drmModeFreeProperty(prop);
+}
+
+static void listObjectProperties(uint32_t id, uint32_t type)
+{
+ unsigned int i;
+ drmModeObjectPropertiesPtr props;
+
+ props = drmModeObjectGetProperties(fd, id, type);
+
+ if (!props) {
+ printf("\tNo properties: %s.\n", strerror(errno));
+ return;
+ }
+
+ for (i = 0; i < props->count_props; i++)
+ dump_prop(props->props[i], props->prop_values[i]);
+
+ drmModeFreeObjectProperties(props);
+}
+
+static void listConnectorProperties(void)
+{
+ int i;
+ drmModeConnectorPtr c;
+
+ for (i = 0; i < res->count_connectors; i++) {
+ c = drmModeGetConnector(fd, res->connectors[i]);
+
+ if (!c) {
+ fprintf(stderr, "Could not get connector %u: %s\n",
+ res->connectors[i], strerror(errno));
+ continue;
+ }
+
+ printf("Connector %u (%s-%u)\n", c->connector_id,
+ drmModeGetConnectorTypeName(c->connector_type),
+ c->connector_type_id);
+
+ listObjectProperties(c->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR);
+
+ drmModeFreeConnector(c);
+ }
+}
+
+static void listCrtcProperties(void)
+{
+ int i;
+ drmModeCrtcPtr c;
+
+ for (i = 0; i < res->count_crtcs; i++) {
+ c = drmModeGetCrtc(fd, res->crtcs[i]);
+
+ if (!c) {
+ fprintf(stderr, "Could not get crtc %u: %s\n",
+ res->crtcs[i], strerror(errno));
+ continue;
+ }
+
+ printf("CRTC %u\n", c->crtc_id);
+
+ listObjectProperties(c->crtc_id, DRM_MODE_OBJECT_CRTC);
+
+ drmModeFreeCrtc(c);
+ }
+}
+
+static void listAllProperties(void)
+{
+ listConnectorProperties();
+ listCrtcProperties();
+}
+
+static int setProperty(char *argv[])
+{
+ uint32_t obj_id, obj_type, prop_id;
+ uint64_t value;
+
+ obj_id = atoi(argv[0]);
+
+ if (!strcmp(argv[1], "connector")) {
+ obj_type = DRM_MODE_OBJECT_CONNECTOR;
+ } else if (!strcmp(argv[1], "crtc")) {
+ obj_type = DRM_MODE_OBJECT_CRTC;
+ } else {
+ fprintf(stderr, "Invalid object type.\n");
+ return 1;
+ }
+
+ prop_id = atoi(argv[2]);
+ value = atoll(argv[3]);
+
+ return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value);
+}
+
+static void usage(const char *program)
+{
+ printf("Usage:\n"
+" %s [options]\n"
+" %s [options] [obj id] [obj type] [prop id] [value]\n"
+"\n"
+"options:\n"
+" -D DEVICE use the given device\n"
+" -M MODULE use the given driver\n"
+"\n"
+"The first form just prints all the existing properties. The second one is\n"
+"used to set the value of a specified property. The object type can be one of\n"
+"the following strings:\n"
+" connector crtc\n"
+"\n"
+"Example:\n"
+" proptest 7 connector 2 1\n"
+"will set property 2 of connector 7 to 1\n", program, program);
+}
+
+int main(int argc, char *argv[])
+{
+ static const char optstr[] = "D:M:";
+ int c, args, ret = 0;
+ char *device = NULL;
+ char *module = NULL;
+
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'D':
+ device = optarg;
+ break;
+
+ case 'M':
+ module = optarg;
+ break;
+
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ args = argc - optind;
+
+ fd = util_open(device, module);
+ if (fd < 0)
+ return 1;
+
+ res = drmModeGetResources(fd);
+ if (!res) {
+ fprintf(stderr, "Failed to get resources: %s\n",
+ strerror(errno));
+ ret = 1;
+ goto done;
+ }
+
+ if (args < 1) {
+ listAllProperties();
+ } else if (args == 4) {
+ ret = setProperty(&argv[optind]);
+ } else {
+ usage(argv[0]);
+ ret = 1;
+ }
+
+ drmModeFreeResources(res);
+done:
+ drmClose(fd);
+ return ret;
+}
diff --git a/tests/radeon/meson.build b/tests/radeon/meson.build
new file mode 100644
index 0000000..bb345b7
--- /dev/null
+++ b/tests/radeon/meson.build
@@ -0,0 +1,27 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+radeon_ttm = executable(
+ 'radeon_ttm',
+ files('rbo.c', 'radeon_ttm.c'),
+ include_directories : [inc_root, inc_drm],
+ link_with : libdrm,
+ c_args : libdrm_c_args,
+)
diff --git a/tests/radeon/radeon_ttm.c b/tests/radeon/radeon_ttm.c
new file mode 100644
index 0000000..8346e85
--- /dev/null
+++ b/tests/radeon/radeon_ttm.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2011 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "rbo.h"
+#include "xf86drm.h"
+
+/* allocate as many single page bo to try to starve the kernel
+ * memory zone (below highmem)
+ */
+static void ttm_starve_kernel_private_memory(int fd)
+{
+ struct list_head list;
+ struct rbo *bo, *tmp;
+ unsigned nbo = 0;
+
+ printf("\n[%s]\n", __func__);
+ list_inithead(&list);
+ while (1) {
+ bo = rbo(fd, 0, 4096, 0, NULL);
+ if (bo == NULL) {
+ printf("failing after %d bo\n", nbo);
+ break;
+ }
+ nbo++;
+ list_add(&bo->list, &list);
+ }
+ LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &list, list) {
+ list_del(&bo->list);
+ rbo_decref(bo);
+ }
+}
+
+static int radeon_open_fd(void)
+{
+ return drmOpen("radeon", NULL);
+}
+
+int main(void)
+{
+ int radeonfd;
+
+ radeonfd = radeon_open_fd();
+ if (radeonfd < 0) {
+ fprintf(stderr, "failed to open radeon fd\n");
+ return -1;
+ }
+
+ ttm_starve_kernel_private_memory(radeonfd);
+
+ close(radeonfd);
+ return 0;
+}
diff --git a/tests/radeon/rbo.c b/tests/radeon/rbo.c
new file mode 100644
index 0000000..70a288c
--- /dev/null
+++ b/tests/radeon/rbo.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2011 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+#define _FILE_OFFSET_BITS 64
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include "xf86drm.h"
+#include "radeon_drm.h"
+#include "rbo.h"
+
+struct rbo *rbo(int fd, unsigned handle, unsigned size,
+ unsigned alignment, void *ptr)
+{
+ struct rbo *bo;
+ int r;
+
+ bo = calloc(1, sizeof(*bo));
+ if (bo == NULL) {
+ return NULL;
+ }
+ list_inithead(&bo->list);
+ bo->fd = fd;
+ bo->size = size;
+ bo->handle = handle;
+ bo->refcount = 1;
+ bo->alignment = alignment;
+
+ if (handle) {
+ struct drm_gem_open open_arg;
+
+ memset(&open_arg, 0, sizeof(open_arg));
+ open_arg.name = handle;
+ r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg);
+ if (r != 0) {
+ free(bo);
+ return NULL;
+ }
+ bo->handle = open_arg.handle;
+ } else {
+ struct drm_radeon_gem_create args;
+
+ args.size = size;
+ args.alignment = alignment;
+ args.initial_domain = RADEON_GEM_DOMAIN_CPU;
+ args.flags = 0;
+ args.handle = 0;
+ r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE,
+ &args, sizeof(args));
+ bo->handle = args.handle;
+ if (r) {
+ fprintf(stderr, "Failed to allocate :\n");
+ fprintf(stderr, " size : %d bytes\n", size);
+ fprintf(stderr, " alignment : %d bytes\n", alignment);
+ free(bo);
+ return NULL;
+ }
+ }
+ if (ptr) {
+ if (rbo_map(bo)) {
+ fprintf(stderr, "%s failed to copy data into bo\n", __func__);
+ return rbo_decref(bo);
+ }
+ memcpy(bo->data, ptr, size);
+ rbo_unmap(bo);
+ }
+ return bo;
+}
+
+int rbo_map(struct rbo *bo)
+{
+ struct drm_radeon_gem_mmap args;
+ void *ptr;
+ int r;
+
+ if (bo->mapcount++ != 0) {
+ return 0;
+ }
+ /* Zero out args to make valgrind happy */
+ memset(&args, 0, sizeof(args));
+ args.handle = bo->handle;
+ args.offset = 0;
+ args.size = (uint64_t)bo->size;
+ r = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_MMAP,
+ &args, sizeof(args));
+ if (r) {
+ fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
+ bo, bo->handle, r);
+ return r;
+ }
+ ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->fd, args.addr_ptr);
+ if (ptr == MAP_FAILED) {
+ fprintf(stderr, "%s failed to map bo\n", __func__);
+ return -errno;
+ }
+ bo->data = ptr;
+ return 0;
+}
+
+void rbo_unmap(struct rbo *bo)
+{
+ if (--bo->mapcount > 0) {
+ return;
+ }
+ munmap(bo->data, bo->size);
+ bo->data = NULL;
+}
+
+struct rbo *rbo_incref(struct rbo *bo)
+{
+ bo->refcount++;
+ return bo;
+}
+
+struct rbo *rbo_decref(struct rbo *bo)
+{
+ struct drm_gem_close args;
+
+ if (bo == NULL)
+ return NULL;
+ if (--bo->refcount > 0) {
+ return NULL;
+ }
+
+ munmap(bo->data, bo->size);
+ memset(&args, 0, sizeof(args));
+ args.handle = bo->handle;
+ drmIoctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &args);
+ memset(bo, 0, sizeof(struct rbo));
+ free(bo);
+ return NULL;
+}
+
+int rbo_wait(struct rbo *bo)
+{
+ struct drm_radeon_gem_wait_idle args;
+ int ret;
+
+ /* Zero out args to make valgrind happy */
+ memset(&args, 0, sizeof(args));
+ args.handle = bo->handle;
+ do {
+ ret = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_WAIT_IDLE,
+ &args, sizeof(args));
+ } while (ret == -EBUSY);
+ return ret;
+}
diff --git a/tests/radeon/rbo.h b/tests/radeon/rbo.h
new file mode 100644
index 0000000..9164091
--- /dev/null
+++ b/tests/radeon/rbo.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2011 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+#ifndef RBO_H
+#define RBO_H
+
+#include "util_double_list.h"
+
+struct rbo {
+ struct list_head list;
+ int fd;
+ unsigned refcount;
+ unsigned mapcount;
+ unsigned handle;
+ unsigned size;
+ unsigned alignment;
+ void *data;
+};
+
+struct rbo *rbo(int fd, unsigned handle, unsigned size,
+ unsigned alignment, void *ptr);
+int rbo_map(struct rbo *bo);
+void rbo_unmap(struct rbo *bo);
+struct rbo *rbo_incref(struct rbo *bo);
+struct rbo *rbo_decref(struct rbo *bo);
+int rbo_wait(struct rbo *bo);
+
+#endif
diff --git a/tests/tegra/.gitignore b/tests/tegra/.gitignore
new file mode 100644
index 0000000..0db9e54
--- /dev/null
+++ b/tests/tegra/.gitignore
@@ -0,0 +1,2 @@
+tegra-gr2d-fill
+tegra-openclose
diff --git a/tests/tegra/drm-test-tegra.c b/tests/tegra/drm-test-tegra.c
new file mode 100644
index 0000000..1a9fa89
--- /dev/null
+++ b/tests/tegra/drm-test-tegra.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "drm-test-tegra.h"
+#include "tegra.h"
+
+int drm_tegra_gr2d_open(struct drm_tegra *drm, struct drm_tegra_gr2d **gr2dp)
+{
+ struct drm_tegra_gr2d *gr2d;
+ int err;
+
+ gr2d = calloc(1, sizeof(*gr2d));
+ if (!gr2d)
+ return -ENOMEM;
+
+ gr2d->drm = drm;
+
+ err = drm_tegra_channel_open(drm, DRM_TEGRA_GR2D, &gr2d->channel);
+ if (err < 0) {
+ free(gr2d);
+ return err;
+ }
+
+ *gr2dp = gr2d;
+
+ return 0;
+}
+
+int drm_tegra_gr2d_close(struct drm_tegra_gr2d *gr2d)
+{
+ if (!gr2d)
+ return -EINVAL;
+
+ drm_tegra_channel_close(gr2d->channel);
+ free(gr2d);
+
+ return 0;
+}
+
+int drm_tegra_gr2d_fill(struct drm_tegra_gr2d *gr2d, struct drm_framebuffer *fb,
+ unsigned int x, unsigned int y, unsigned int width,
+ unsigned int height, uint32_t color)
+{
+ struct drm_tegra_bo *fbo = fb->data;
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(gr2d->channel, &job);
+ if (err < 0)
+ return err;
+
+ err = drm_tegra_channel_map(gr2d->channel, fbo, 0, &map);
+ if (err < 0)
+ return err;
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0)
+ return err;
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0)
+ return err;
+
+ *ptr++ = HOST1X_OPCODE_SETCL(0, HOST1X_CLASS_GR2D, 0);
+
+ *ptr++ = HOST1X_OPCODE_MASK(0x9, 0x9);
+ *ptr++ = 0x0000003a;
+ *ptr++ = 0x00000000;
+
+ *ptr++ = HOST1X_OPCODE_MASK(0x1e, 0x7);
+ *ptr++ = 0x00000000;
+ *ptr++ = (2 << 16) | (1 << 6) | (1 << 2);
+ *ptr++ = 0x000000cc;
+
+ *ptr++ = HOST1X_OPCODE_MASK(0x2b, 0x9);
+
+ /* relocate destination buffer */
+ err = drm_tegra_pushbuf_relocate(pushbuf, &ptr, map, 0, 0, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to relocate buffer object: %d\n", err);
+ return err;
+ }
+
+ *ptr++ = fb->pitch;
+
+ *ptr++ = HOST1X_OPCODE_NONINCR(0x35, 1);
+ *ptr++ = color;
+
+ *ptr++ = HOST1X_OPCODE_NONINCR(0x46, 1);
+ *ptr++ = 0x00000000;
+
+ *ptr++ = HOST1X_OPCODE_MASK(0x38, 0x5);
+ *ptr++ = height << 16 | width;
+ *ptr++ = y << 16 | x;
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %d\n", -err);
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %d\n", err);
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for fence: %d\n", err);
+ return err;
+ }
+
+ drm_tegra_channel_unmap(map);
+ drm_tegra_job_free(job);
+
+ return 0;
+}
diff --git a/tests/tegra/drm-test-tegra.h b/tests/tegra/drm-test-tegra.h
new file mode 100644
index 0000000..eefa954
--- /dev/null
+++ b/tests/tegra/drm-test-tegra.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEGRA_DRM_TEST_TEGRA_H
+#define TEGRA_DRM_TEST_TEGRA_H
+
+#include "drm-test.h"
+#include "tegra.h"
+
+#define HOST1X_OPCODE_SETCL(offset, classid, mask) \
+ ((0x0 << 28) | (((offset) & 0xfff) << 16) | (((classid) & 0x3ff) << 6) | ((mask) & 0x3f))
+#define HOST1X_OPCODE_INCR(offset, count) \
+ ((0x1 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff))
+#define HOST1X_OPCODE_NONINCR(offset, count) \
+ ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff))
+#define HOST1X_OPCODE_MASK(offset, mask) \
+ ((0x3 << 28) | (((offset) & 0xfff) << 16) | ((mask) & 0xffff))
+#define HOST1X_OPCODE_IMM(offset, data) \
+ ((0x4 << 28) | (((offset) & 0xfff) << 16) | ((data) & 0xffff))
+#define HOST1X_OPCODE_EXTEND(subop, value) \
+ ((0xe << 28) | (((subop) & 0xf) << 24) | ((value) & 0xffffff))
+
+#define HOST1X_CLASS_GR2D 0x51
+
+struct drm_tegra_gr2d {
+ struct drm_tegra *drm;
+ struct drm_tegra_channel *channel;
+};
+
+int drm_tegra_gr2d_open(struct drm_tegra *drm, struct drm_tegra_gr2d **gr2dp);
+int drm_tegra_gr2d_close(struct drm_tegra_gr2d *gr2d);
+int drm_tegra_gr2d_fill(struct drm_tegra_gr2d *gr2d, struct drm_framebuffer *fb,
+ unsigned int x, unsigned int y, unsigned int width,
+ unsigned int height, uint32_t color);
+
+#endif
diff --git a/tests/tegra/drm-test.c b/tests/tegra/drm-test.c
new file mode 100644
index 0000000..b1ded9c
--- /dev/null
+++ b/tests/tegra/drm-test.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "drm_fourcc.h"
+
+#include "drm-test.h"
+
+static int drm_screen_probe_connector(struct drm_screen *screen,
+ drmModeConnectorPtr connector)
+{
+ drmModeEncoderPtr encoder;
+ drmModeCrtcPtr crtc;
+ drmModeFBPtr fb;
+
+ encoder = drmModeGetEncoder(screen->fd, connector->encoder_id);
+ if (!encoder)
+ return -ENODEV;
+
+ crtc = drmModeGetCrtc(screen->fd, encoder->crtc_id);
+ if (!crtc) {
+ drmModeFreeEncoder(encoder);
+ return -ENODEV;
+ }
+
+ screen->old_fb = crtc->buffer_id;
+
+ fb = drmModeGetFB(screen->fd, crtc->buffer_id);
+ if (!fb) {
+ /* TODO: create new framebuffer */
+ drmModeFreeEncoder(encoder);
+ drmModeFreeCrtc(crtc);
+ return -ENOSYS;
+ }
+
+ screen->connector = connector->connector_id;
+ screen->old_fb = crtc->buffer_id;
+ screen->crtc = encoder->crtc_id;
+ /* TODO: check crtc->mode_valid */
+ screen->mode = crtc->mode;
+
+ screen->width = fb->width;
+ screen->height = fb->height;
+ screen->pitch = fb->pitch;
+ screen->depth = fb->depth;
+ screen->bpp = fb->bpp;
+
+ drmModeFreeEncoder(encoder);
+ drmModeFreeCrtc(crtc);
+ drmModeFreeFB(fb);
+
+ return 0;
+}
+
+int drm_screen_open(struct drm_screen **screenp, int fd)
+{
+ drmModeConnectorPtr connector;
+ struct drm_screen *screen;
+ bool found = false;
+ drmModeResPtr res;
+ unsigned int i;
+ int err;
+
+ if (!screenp || fd < 0)
+ return -EINVAL;
+
+ screen = calloc(1, sizeof(*screen));
+ if (!screen)
+ return -ENOMEM;
+
+ screen->format = DRM_FORMAT_XRGB8888;
+ screen->fd = fd;
+
+ res = drmModeGetResources(fd);
+ if (!res) {
+ free(screen);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < (unsigned int)res->count_connectors; i++) {
+ connector = drmModeGetConnector(fd, res->connectors[i]);
+ if (!connector)
+ continue;
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ err = drm_screen_probe_connector(screen, connector);
+ if (err < 0) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ drmModeFreeConnector(connector);
+ found = true;
+ break;
+ }
+
+ drmModeFreeResources(res);
+
+ if (!found) {
+ free(screen);
+ return -ENODEV;
+ }
+
+ *screenp = screen;
+
+ return 0;
+}
+
+int drm_screen_close(struct drm_screen *screen)
+{
+ int err;
+
+ err = drmModeSetCrtc(screen->fd, screen->crtc, screen->old_fb, 0, 0,
+ &screen->connector, 1, &screen->mode);
+ if (err < 0) {
+ fprintf(stderr, "drmModeSetCrtc() failed: %m\n");
+ return -errno;
+ }
+
+ free(screen);
+
+ return 0;
+}
+
+int drm_framebuffer_new(struct drm_framebuffer **fbp,
+ struct drm_screen *screen, uint32_t handle,
+ unsigned int width, unsigned int height,
+ unsigned int pitch, uint32_t format,
+ void *data)
+{
+ struct drm_framebuffer *fb;
+ uint32_t handles[4];
+ uint32_t pitches[4];
+ uint32_t offsets[4];
+ int err;
+
+ fb = calloc(1, sizeof(*fb));
+ if (!fb)
+ return -ENOMEM;
+
+ fb->fd = screen->fd;
+ fb->width = width;
+ fb->height = height;
+ fb->pitch = pitch;
+ fb->format = format;
+ fb->data = data;
+
+ handles[0] = handle;
+ pitches[0] = pitch;
+ offsets[0] = 0;
+
+ err = drmModeAddFB2(screen->fd, width, height, format, handles,
+ pitches, offsets, &fb->handle, 0);
+ if (err < 0)
+ return -errno;
+
+ *fbp = fb;
+
+ return 0;
+}
+
+int drm_framebuffer_free(struct drm_framebuffer *fb)
+{
+ int err;
+
+ err = drmModeRmFB(fb->fd, fb->handle);
+ if (err < 0)
+ return -errno;
+
+ free(fb);
+
+ return 0;
+}
+
+int drm_screen_set_framebuffer(struct drm_screen *screen,
+ struct drm_framebuffer *fb)
+{
+ int err;
+
+ err = drmModeSetCrtc(screen->fd, screen->crtc, fb->handle, 0, 0,
+ &screen->connector, 1, &screen->mode);
+ if (err < 0)
+ return -errno;
+
+ return 0;
+}
+
+int drm_open(const char *path)
+{
+ int fd, err;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ return -errno;
+
+ err = drmSetMaster(fd);
+ if (err < 0) {
+ close(fd);
+ return -errno;
+ }
+
+ return fd;
+}
+
+void drm_close(int fd)
+{
+ drmDropMaster(fd);
+ close(fd);
+}
diff --git a/tests/tegra/drm-test.h b/tests/tegra/drm-test.h
new file mode 100644
index 0000000..f11aed4
--- /dev/null
+++ b/tests/tegra/drm-test.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEGRA_DRM_TEST_H
+#define TEGRA_DRM_TEST_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "xf86drmMode.h"
+
+struct drm_screen {
+ int fd;
+
+ unsigned int width;
+ unsigned int height;
+ unsigned int pitch;
+ unsigned int depth;
+ unsigned int bpp;
+
+ drmModeModeInfo mode;
+ uint32_t connector;
+ uint32_t old_fb;
+ uint32_t format;
+ uint32_t crtc;
+};
+
+struct drm_framebuffer {
+ unsigned int width;
+ unsigned int height;
+ unsigned int pitch;
+ uint32_t format;
+ uint32_t handle;
+ void *data;
+ int fd;
+};
+
+int drm_screen_open(struct drm_screen **screenp, int fd);
+int drm_screen_close(struct drm_screen *screen);
+int drm_screen_set_framebuffer(struct drm_screen *screen,
+ struct drm_framebuffer *fb);
+
+int drm_framebuffer_new(struct drm_framebuffer **fbp,
+ struct drm_screen *screen, uint32_t handle,
+ unsigned int width, unsigned int height,
+ unsigned int pitch, uint32_t format,
+ void *data);
+int drm_framebuffer_free(struct drm_framebuffer *fb);
+
+int drm_open(const char *path);
+void drm_close(int fd);
+
+#endif
diff --git a/tests/tegra/gr2d-fill.c b/tests/tegra/gr2d-fill.c
new file mode 100644
index 0000000..d138cc4
--- /dev/null
+++ b/tests/tegra/gr2d-fill.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "drm_fourcc.h"
+
+#include "drm-test-tegra.h"
+#include "tegra.h"
+
+int main(int argc, char *argv[])
+{
+ uint32_t format = DRM_FORMAT_XRGB8888;
+ struct drm_tegra_gr2d *gr2d;
+ struct drm_framebuffer *fb;
+ struct drm_screen *screen;
+ unsigned int pitch, size;
+ struct drm_tegra_bo *bo;
+ struct drm_tegra *drm;
+ uint32_t handle;
+ int fd, err;
+ void *ptr;
+
+ fd = drm_open(argv[1]);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open DRM device %s: %s\n", argv[1],
+ strerror(errno));
+ return 1;
+ }
+
+ err = drm_screen_open(&screen, fd);
+ if (err < 0) {
+ fprintf(stderr, "failed to open screen: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to create Tegra DRM context: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_gr2d_open(drm, &gr2d);
+ if (err < 0) {
+ fprintf(stderr, "failed to open gr2d channel: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ pitch = screen->width * screen->bpp / 8;
+ size = pitch * screen->height;
+
+ err = drm_tegra_bo_new(drm, 0, size, &bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to create buffer object: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_bo_get_handle(bo, &handle);
+ if (err < 0) {
+ fprintf(stderr, "failed to get handle to buffer object: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_bo_map(bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map buffer object: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ memset(ptr, 0xff, size);
+
+ err = drm_framebuffer_new(&fb, screen, handle, screen->width,
+ screen->height, pitch, format, bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to create framebuffer: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ err = drm_screen_set_framebuffer(screen, fb);
+ if (err < 0) {
+ fprintf(stderr, "failed to display framebuffer: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ sleep(1);
+
+ err = drm_tegra_gr2d_fill(gr2d, fb, fb->width / 4, fb->height / 4,
+ fb->width / 2, fb->height / 2, 0x00000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to fill rectangle: %s\n",
+ strerror(-err));
+ return 1;
+ }
+
+ sleep(1);
+
+ drm_framebuffer_free(fb);
+ drm_tegra_bo_unref(bo);
+ drm_tegra_gr2d_close(gr2d);
+ drm_tegra_close(drm);
+ drm_screen_close(screen);
+ drm_close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/host1x.h b/tests/tegra/host1x.h
new file mode 100644
index 0000000..902b0c1
--- /dev/null
+++ b/tests/tegra/host1x.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef HOST1X_H
+#define HOST1X_H
+
+#define HOST1X_OPCODE_SETCL(offset, classid, mask) \
+ ((0x0 << 28) | (((offset) & 0xfff) << 16) | (((classid) & 0x3ff) << 6) | ((mask) & 0x3f))
+
+#define HOST1X_OPCODE_INCR(offset, count) \
+ ((0x1 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff))
+
+#define HOST1X_CLASS_VIC 0x5d
+
+#endif
diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
new file mode 100644
index 0000000..26a32e8
--- /dev/null
+++ b/tests/tegra/meson.build
@@ -0,0 +1,111 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+inc_tegra = include_directories('../../tegra')
+
+libdrm_test = static_library(
+ 'drm-test',
+ [files('drm-test.c', 'drm-test.h'), config_file ],
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ link_with : libdrm,
+)
+
+libdrm_test_tegra = static_library(
+ 'drm-test-tegra',
+ [files(
+ 'drm-test-tegra.c',
+ 'drm-test-tegra.h',
+ 'vic.c',
+ 'vic.h',
+ 'vic30.c',
+ 'vic30.h',
+ 'vic40.c',
+ 'vic40.h',
+ 'vic41.c',
+ 'vic41.h',
+ 'vic42.c',
+ 'vic42.h',
+ ), config_file ],
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ link_with : libdrm,
+)
+
+openclose = executable(
+ 'tegra-openclose',
+ files('openclose.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra],
+ install : with_install_tests,
+)
+
+gr2d_fill = executable(
+ 'tegra-gr2d-fill',
+ files('gr2d-fill.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
+
+syncpt_wait = executable(
+ 'tegra-syncpt-wait',
+ files('syncpt-wait.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
+
+syncpt_timeout = executable(
+ 'tegra-syncpt-timeout',
+ files('syncpt-timeout.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
+
+vic_clear = executable(
+ 'tegra-vic-clear',
+ files('vic-clear.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
+
+vic_blit = executable(
+ 'tegra-vic-blit',
+ files('vic-blit.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
+
+vic_flip = executable(
+ 'tegra-vic-flip',
+ files('vic-flip.c'),
+ include_directories : [inc_root, inc_drm, inc_tegra],
+ c_args : libdrm_c_args,
+ link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+ install : with_install_tests,
+)
diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c
new file mode 100644
index 0000000..61dbc2b
--- /dev/null
+++ b/tests/tegra/openclose.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "xf86drm.h"
+#include "tegra.h"
+
+static const char default_device[] = "/dev/dri/card0";
+
+int main(int argc, char *argv[])
+{
+ struct drm_tegra *tegra;
+ drmVersionPtr version;
+ const char *device;
+ int err, fd;
+
+ if (argc < 2)
+ device = default_device;
+ else
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0)
+ return 1;
+
+ version = drmGetVersion(fd);
+ if (version) {
+ printf("Version: %d.%d.%d\n", version->version_major,
+ version->version_minor, version->version_patchlevel);
+ printf(" Name: %s\n", version->name);
+ printf(" Date: %s\n", version->date);
+ printf(" Description: %s\n", version->desc);
+
+ drmFreeVersion(version);
+ }
+
+ err = drm_tegra_new(fd, &tegra);
+ if (err < 0)
+ return 1;
+
+ drm_tegra_close(tegra);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/syncpt-timeout.c b/tests/tegra/syncpt-timeout.c
new file mode 100644
index 0000000..fea3665
--- /dev/null
+++ b/tests/tegra/syncpt-timeout.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tegra.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static int channel_open(struct drm_tegra *drm,
+ struct drm_tegra_channel **channel)
+{
+ static const struct {
+ enum drm_tegra_class class;
+ const char *name;
+ } classes[] = {
+ { DRM_TEGRA_VIC, "VIC" },
+ { DRM_TEGRA_GR2D, "GR2D" },
+ };
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(classes); i++) {
+ err = drm_tegra_channel_open(drm, classes[i].class, channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel to %s: %s\n",
+ classes[i].name, strerror(-err));
+ continue;
+ }
+
+ break;
+ }
+
+ return err;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *device = "/dev/dri/renderD128";
+ struct drm_tegra_syncpoint *syncpt;
+ struct drm_tegra_channel *channel;
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ struct drm_tegra *drm;
+ uint32_t *ptr;
+ int fd, err;
+
+ if (argc > 1)
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
+ close(fd);
+ return 1;
+ }
+
+ err = drm_tegra_syncpoint_new(drm, &syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ drm_tegra_close(drm);
+ close(fd);
+ return 1;
+ }
+
+ err = channel_open(drm, &channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 8, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ /*
+ * Empty command streams will be rejected, so we use this as an easy way
+ * to add something to the command stream. But this could be any other,
+ * valid command stream.
+ */
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, syncpt,
+ DRM_TEGRA_SYNC_COND_IMMEDIATE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return 1;
+ }
+
+ /* pretend that the syncpoint was incremented a second time */
+ err = drm_tegra_pushbuf_sync(pushbuf, syncpt, 1);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_wait(job, 250000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ drm_tegra_job_free(job);
+ drm_tegra_channel_close(channel);
+ drm_tegra_syncpoint_free(syncpt);
+ drm_tegra_close(drm);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/syncpt-wait.c b/tests/tegra/syncpt-wait.c
new file mode 100644
index 0000000..f181174
--- /dev/null
+++ b/tests/tegra/syncpt-wait.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tegra.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static int channel_open(struct drm_tegra *drm,
+ struct drm_tegra_channel **channel)
+{
+ static const struct {
+ enum drm_tegra_class class;
+ const char *name;
+ } classes[] = {
+ { DRM_TEGRA_VIC, "VIC" },
+ { DRM_TEGRA_GR2D, "GR2D" },
+ };
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(classes); i++) {
+ err = drm_tegra_channel_open(drm, classes[i].class, channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel to %s: %s\n",
+ classes[i].name, strerror(-err));
+ continue;
+ }
+
+ break;
+ }
+
+ return err;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *device = "/dev/dri/renderD128";
+ struct drm_tegra_syncpoint *syncpt;
+ struct drm_tegra_channel *channel;
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ struct drm_tegra *drm;
+ uint32_t *ptr;
+ int fd, err;
+
+ if (argc > 1)
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
+ close(fd);
+ return 1;
+ }
+
+ err = drm_tegra_syncpoint_new(drm, &syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ drm_tegra_close(drm);
+ close(fd);
+ return 1;
+ }
+
+ err = channel_open(drm, &channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 4, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, syncpt,
+ DRM_TEGRA_SYNC_COND_IMMEDIATE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_wait(job, 250000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ drm_tegra_job_free(job);
+ drm_tegra_channel_close(channel);
+ drm_tegra_syncpoint_free(syncpt);
+ drm_tegra_close(drm);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/vic-blit.c b/tests/tegra/vic-blit.c
new file mode 100644
index 0000000..7baf9e7
--- /dev/null
+++ b/tests/tegra/vic-blit.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tegra.h"
+
+#include "host1x.h"
+#include "vic.h"
+
+/* clear output image to red */
+static int clear(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = vic_clear(vic, output, 1023, 1023, 0, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to clear surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+/* fill bottom half of image to blue */
+static int fill(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->fill(vic, output, 0, output->height / 2, output->width - 1,
+ output->height -1, 1023, 0, 0, 1023);
+ if (err < 0) {
+ fprintf(stderr, "failed to fill surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+/* blit image */
+static int blit(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output, struct vic_image *input)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->blit(vic, output, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to blit surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, &input, 1);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8;
+ const unsigned int kind = VIC_BLK_KIND_PITCH;
+ const unsigned int width = 16, height = 16;
+ const char *device = "/dev/dri/renderD128";
+ struct drm_tegra_channel *channel;
+ struct vic_image *input, *output;
+ struct drm_tegra *drm;
+ unsigned int version;
+ struct vic *vic;
+ int fd, err;
+
+ if (argc > 1)
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
+ close(fd);
+ return 1;
+ }
+
+ err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ version = drm_tegra_channel_get_version(channel);
+ printf("version: %08x\n", version);
+
+ err = vic_new(drm, channel, &vic);
+ if (err < 0) {
+ fprintf(stderr, "failed to create VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &input);
+ if (err < 0) {
+ fprintf(stderr, "failed to create input image: %d\n", err);
+ return 1;
+ }
+
+ err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &output);
+ if (err < 0) {
+ fprintf(stderr, "failed to create output image: %d\n", err);
+ return 1;
+ }
+
+ err = clear(vic, channel, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to clear image: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = fill(vic, channel, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = blit(vic, channel, output, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to blit image: %s\n", strerror(-err));
+ return 1;
+ }
+
+ printf("input: %ux%u\n", input->width, input->height);
+ vic_image_dump(input, stdout);
+
+ printf("output: %ux%u\n", output->width, output->height);
+ vic_image_dump(output, stdout);
+
+ vic_image_free(output);
+ vic_image_free(input);
+
+ vic_free(vic);
+ drm_tegra_channel_close(channel);
+ drm_tegra_close(drm);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/vic-clear.c b/tests/tegra/vic-clear.c
new file mode 100644
index 0000000..da72782
--- /dev/null
+++ b/tests/tegra/vic-clear.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util_math.h"
+
+#include "tegra.h"
+
+#include "host1x.h"
+#include "vic.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+int main(int argc, char *argv[])
+{
+ const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8;
+ const unsigned int kind = VIC_BLK_KIND_PITCH;
+ const unsigned int width = 16, height = 16;
+ const char *device = "/dev/dri/renderD128";
+ struct drm_tegra_channel *channel;
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ struct vic_image *output;
+ struct drm_tegra *drm;
+ unsigned int version;
+ struct vic *vic;
+ uint32_t *pb;
+ int fd, err;
+ void *ptr;
+
+ if (argc > 1)
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
+ close(fd);
+ return 1;
+ }
+
+ err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ version = drm_tegra_channel_get_version(channel);
+ printf("version: %08x\n", version);
+
+ err = vic_new(drm, channel, &vic);
+ if (err < 0) {
+ fprintf(stderr, "failed to create VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &output);
+ if (err < 0) {
+ fprintf(stderr, "failed to create output image: %d\n", err);
+ return 1;
+ }
+
+ printf("image: %zu bytes\n", output->size);
+
+ err = drm_tegra_bo_map(output->bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map output image: %d\n", err);
+ return 1;
+ }
+
+ memset(ptr, 0xff, output->size);
+ drm_tegra_bo_unmap(output->bo);
+
+ printf("output: %ux%u\n", output->width, output->height);
+ vic_image_dump(output, stdout);
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &pb);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = vic_clear(vic, output, 1023, 0, 0, 1023);
+ if (err < 0) {
+ fprintf(stderr, "failed to clear surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &pb, output, NULL, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &pb, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, pb);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ printf("output: %ux%u\n", output->width, output->height);
+ vic_image_dump(output, stdout);
+
+ drm_tegra_job_free(job);
+ vic_image_free(output);
+ vic_free(vic);
+ drm_tegra_channel_close(channel);
+ drm_tegra_close(drm);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/vic-flip.c b/tests/tegra/vic-flip.c
new file mode 100644
index 0000000..e94336b
--- /dev/null
+++ b/tests/tegra/vic-flip.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tegra.h"
+
+#include "host1x.h"
+#include "vic.h"
+
+/* clear output image to red */
+static int clear(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic_clear(vic, output, 1023, 0, 0, 1023);
+ if (err < 0) {
+ fprintf(stderr, "failed to clear surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+/* fill bottom half of image to blue */
+static int fill(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->fill(vic, output, 0, output->height / 2, output->width - 1,
+ output->height - 1, 0, 0, 1023, 1023);
+ if (err < 0) {
+ fprintf(stderr, "failed ot fill surface: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+/* flip image vertically */
+static int flip(struct vic *vic, struct drm_tegra_channel *channel,
+ struct vic_image *output, struct vic_image *input)
+{
+ struct drm_tegra_pushbuf *pushbuf;
+ struct drm_tegra_job *job;
+ uint32_t *ptr;
+ int err;
+
+ err = drm_tegra_job_new(channel, &job);
+ if (err < 0) {
+ fprintf(stderr, "failed to create job: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_job_get_pushbuf(job, &pushbuf);
+ if (err < 0) {
+ fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->flip(vic, output, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to flip: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = vic->ops->execute(vic, pushbuf, &ptr, output, &input, 1);
+ if (err < 0) {
+ fprintf(stderr, "failed to execute operation: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
+ if (err < 0) {
+ fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_pushbuf_end(pushbuf, ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_submit(job, NULL);
+ if (err < 0) {
+ fprintf(stderr, "failed to submit job: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_job_wait(job, 1000000000);
+ if (err < 0) {
+ fprintf(stderr, "failed to wait for job: %s\n", strerror(-err));
+ return err;
+ }
+
+ drm_tegra_job_free(job);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8;
+ const unsigned int kind = VIC_BLK_KIND_PITCH;
+ const unsigned int width = 16, height = 16;
+ const char *device = "/dev/dri/renderD128";
+ struct drm_tegra_channel *channel;
+ struct vic_image *input, *output;
+ struct drm_tegra *drm;
+ unsigned int version;
+ struct vic *vic;
+ int fd, err;
+
+ if (argc > 1)
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ err = drm_tegra_new(fd, &drm);
+ if (err < 0) {
+ fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err));
+ close(fd);
+ return 1;
+ }
+
+ err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel);
+ if (err < 0) {
+ fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ version = drm_tegra_channel_get_version(channel);
+ printf("version: %08x\n", version);
+
+ err = vic_new(drm, channel, &vic);
+ if (err < 0) {
+ fprintf(stderr, "failed to create VIC: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &input);
+ if (err < 0) {
+ fprintf(stderr, "failed to create input image: %d\n", err);
+ return 1;
+ }
+
+ err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &output);
+ if (err < 0) {
+ fprintf(stderr, "failed to create output image: %d\n", err);
+ return 1;
+ }
+
+ err = clear(vic, channel, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to clear image: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = fill(vic, channel, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err));
+ return 1;
+ }
+
+ err = flip(vic, channel, output, input);
+ if (err < 0) {
+ fprintf(stderr, "failed to flip image: %s\n", strerror(-err));
+ return 1;
+ }
+
+ printf("input: %ux%u\n", input->width, input->height);
+ vic_image_dump(input, stdout);
+
+ printf("output: %ux%u\n", output->width, output->height);
+ vic_image_dump(output, stdout);
+
+ vic_image_free(output);
+ vic_image_free(input);
+
+ vic_free(vic);
+ drm_tegra_channel_close(channel);
+ drm_tegra_close(drm);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
new file mode 100644
index 0000000..4163e18
--- /dev/null
+++ b/tests/tegra/vic.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdio.h> /* XXX remove */
+#include <stdlib.h>
+
+#include "util_math.h"
+
+#include "tegra.h"
+#include "host1x.h"
+#include "vic.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+const struct vic_format_info *vic_format_get_info(unsigned int format)
+{
+ static const struct vic_format_info formats[] = {
+ { .format = VIC_PIXEL_FORMAT_A8R8G8B8, .cpp = 4 },
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].format == format)
+ return &formats[i];
+ }
+
+ return 0;
+}
+
+int vic_image_new(struct vic *vic, unsigned int width, unsigned int height,
+ unsigned int format, unsigned int kind, uint32_t flags,
+ struct vic_image **imagep)
+{
+ const struct vic_format_info *info = vic_format_get_info(format);
+ struct vic_image *image;
+ int err;
+
+ if (!info)
+ return -EINVAL;
+
+ image = calloc(1, sizeof(*image));
+ if (!image)
+ return -ENOMEM;
+
+ if (kind == VIC_BLK_KIND_PITCH)
+ image->align = 256;
+ else
+ image->align = 256; /* XXX */
+
+ image->width = width;
+ image->stride = ALIGN(width, image->align);
+ image->pitch = image->stride * info->cpp;
+ image->height = height;
+ image->format = format;
+ image->kind = kind;
+
+ image->size = image->pitch * image->height;
+
+ printf("image: %ux%u align: %zu stride: %u pitch: %u size: %zu\n",
+ image->width, image->height, image->align, image->stride,
+ image->pitch, image->size);
+
+ err = drm_tegra_bo_new(vic->drm, 0, image->size, &image->bo);
+ if (err < 0) {
+ free(image);
+ return err;
+ }
+
+ err = drm_tegra_channel_map(vic->channel, image->bo, flags, &image->map);
+ if (err < 0) {
+ drm_tegra_bo_unref(image->bo);
+ free(image);
+ return err;
+ }
+
+ *imagep = image;
+ return 0;
+}
+
+void vic_image_free(struct vic_image *image)
+{
+ if (image) {
+ drm_tegra_channel_unmap(image->map);
+ drm_tegra_bo_unref(image->bo);
+ free(image);
+ }
+}
+
+void vic_image_dump(struct vic_image *image, FILE *fp)
+{
+ unsigned int i, j;
+ void *ptr;
+ int err;
+
+ err = drm_tegra_bo_map(image->bo, &ptr);
+ if (err < 0)
+ return;
+
+ for (j = 0; j < image->height; j++) {
+ uint32_t *pixels = (uint32_t *)((unsigned long)ptr + j * image->pitch);
+
+ printf(" ");
+
+ for (i = 0; i < image->width; i++)
+ printf(" %08x", pixels[i]);
+
+ printf("\n");
+ }
+
+ drm_tegra_bo_unmap(image->bo);
+}
+
+/* from vic30.c */
+int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp);
+
+/* from vic40.c */
+int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp);
+
+/* from vic41.c */
+int vic41_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp);
+
+/* from vic42.c */
+int vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp);
+
+int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp)
+{
+ unsigned int version;
+
+ version = drm_tegra_channel_get_version(channel);
+
+ switch (version) {
+ case 0x40:
+ return vic30_new(drm, channel, vicp);
+
+ case 0x21:
+ return vic40_new(drm, channel, vicp);
+
+ case 0x18:
+ return vic41_new(drm, channel, vicp);
+
+ case 0x19:
+ return vic42_new(drm, channel, vicp);
+ }
+
+ return -ENOTSUP;
+}
+
+void vic_free(struct vic *vic)
+{
+ if (vic)
+ vic->ops->free(vic);
+}
+
+int vic_clear(struct vic *vic, struct vic_image *output, unsigned int alpha,
+ unsigned int red, unsigned int green, unsigned int blue)
+{
+ return vic->ops->fill(vic, output, 0, 0, output->width - 1,
+ output->height - 1, alpha, red, green, blue);
+}
diff --git a/tests/tegra/vic.h b/tests/tegra/vic.h
new file mode 100644
index 0000000..c205666
--- /dev/null
+++ b/tests/tegra/vic.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIC_H
+#define VIC_H
+
+#include <stdio.h>
+
+#include "host1x.h"
+
+#define DXVAHD_FRAME_FORMAT_PROGRESSIVE 0
+#define DXVAHD_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST 1
+#define DXVAHD_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST 2
+#define DXVAHD_FRAME_FORMAT_TOP_FIELD 3
+#define DXVAHD_FRAME_FORMAT_BOTTOM_FIELD 4
+#define DXVAHD_FRAME_FORMAT_SUBPIC_PROGRESSIVE 5
+#define DXVAHD_FRAME_FORMAT_SUBPIC_INTERLACED_TOP_FIELD_FIRST 6
+#define DXVAHD_FRAME_FORMAT_SUBPIC_INTERLACED_BOTTOM_FIELD_FIRST 7
+#define DXVAHD_FRAME_FORMAT_SUBPIC_TOP_FIELD 8
+#define DXVAHD_FRAME_FORMAT_SUBPIC_BOTTOM_FIELD 9
+#define DXVAHD_FRAME_FORMAT_TOP_FIELD_CHROMA_BOTTOM 10
+#define DXVAHD_FRAME_FORMAT_BOTTOM_FIELD_CHROMA_TOP 11
+#define DXVAHD_FRAME_FORMAT_SUBPIC_TOP_FIELD_CHROMA_BOTTOM 12
+#define DXVAHD_FRAME_FORMAT_SUBPIC_BOTTOM_FIELD_CHROMA_TOP 13
+
+#define DXVAHD_ALPHA_FILL_MODE_OPAQUE 0
+#define DXVAHD_ALPHA_FILL_MODE_BACKGROUND 1
+#define DXVAHD_ALPHA_FILL_MODE_DESTINATION 2
+#define DXVAHD_ALPHA_FILL_MODE_SOURCE_STREAM 3
+#define DXVAHD_ALPHA_FILL_MODE_COMPOSITED 4
+#define DXVAHD_ALPHA_FILL_MODE_SOURCE_ALPHA 5
+
+#define VIC_BLEND_SRCFACTC_K1 0
+#define VIC_BLEND_SRCFACTC_K1_TIMES_DST 1
+#define VIC_BLEND_SRCFACTC_NEG_K1_TIMES_DST 2
+#define VIC_BLEND_SRCFACTC_K1_TIMES_SRC 3
+#define VIC_BLEND_SRCFACTC_ZERO 4
+
+#define VIC_BLEND_DSTFACTC_K1 0
+#define VIC_BLEND_DSTFACTC_K2 1
+#define VIC_BLEND_DSTFACTC_K1_TIMES_DST 2
+#define VIC_BLEND_DSTFACTC_NEG_K1_TIMES_DST 3
+#define VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC 4
+#define VIC_BLEND_DSTFACTC_ZERO 5
+#define VIC_BLEND_DSTFACTC_ONE 6
+
+#define VIC_BLEND_SRCFACTA_K1 0
+#define VIC_BLEND_SRCFACTA_K2 1
+#define VIC_BLEND_SRCFACTA_NEG_K1_TIMES_DST 2
+#define VIC_BLEND_SRCFACTA_ZERO 3
+
+#define VIC_BLEND_DSTFACTA_K2 0
+#define VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC 1
+#define VIC_BLEND_DSTFACTA_ZERO 2
+#define VIC_BLEND_DSTFACTA_ONE 3
+
+#define VIC_BLK_KIND_PITCH 0
+#define VIC_BLK_KIND_GENERIC_16Bx2 1
+
+#define VIC_PIXEL_FORMAT_L8 1
+#define VIC_PIXEL_FORMAT_R8 4
+#define VIC_PIXEL_FORMAT_A8R8G8B8 32
+#define VIC_PIXEL_FORMAT_R8G8B8A8 34
+#define VIC_PIXEL_FORMAT_Y8_U8V8_N420 67
+#define VIC_PIXEL_FORMAT_Y8_V8U8_N420 68
+
+#define VIC_CACHE_WIDTH_16Bx16 0 /* BL16Bx2 */
+#define VIC_CACHE_WIDTH_32Bx8 1 /* BL16Bx2 */
+#define VIC_CACHE_WIDTH_64Bx4 2 /* BL16Bx2, PL */
+#define VIC_CACHE_WIDTH_128Bx2 3 /* BL16Bx2, PL */
+#define VIC_CACHE_WIDTH_256Bx1 4 /* PL */
+
+struct vic_format_info {
+ unsigned int format;
+ unsigned int cpp;
+};
+
+
+#define VIC_UCLASS_INCR_SYNCPT 0x00
+#define VIC_UCLASS_METHOD_OFFSET 0x10
+#define VIC_UCLASS_METHOD_DATA 0x11
+
+static inline void VIC_PUSH_METHOD(struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, uint32_t method,
+ uint32_t value)
+{
+ *(*ptrp)++ = HOST1X_OPCODE_INCR(VIC_UCLASS_METHOD_OFFSET, 2);
+ *(*ptrp)++ = method >> 2;
+ *(*ptrp)++ = value;
+}
+
+static inline void VIC_PUSH_BUFFER(struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, uint32_t method,
+ struct drm_tegra_mapping *map,
+ unsigned long offset, unsigned long flags)
+{
+ *(*ptrp)++ = HOST1X_OPCODE_INCR(VIC_UCLASS_METHOD_OFFSET, 2);
+ *(*ptrp)++ = method >> 2;
+
+ drm_tegra_pushbuf_relocate(pushbuf, ptrp, map, offset, 8, flags);
+}
+
+struct vic_image;
+struct vic;
+
+struct vic_ops {
+ int (*fill)(struct vic *vic, struct vic_image *output,
+ unsigned int left, unsigned int top,
+ unsigned int right, unsigned int bottom,
+ unsigned int alpha, unsigned red,
+ unsigned int green, unsigned int blue);
+ int (*blit)(struct vic *vic, struct vic_image *output,
+ struct vic_image *input);
+ int (*flip)(struct vic *vic, struct vic_image *output,
+ struct vic_image *input);
+ int (*execute)(struct vic *vic,
+ struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp,
+ struct vic_image *output,
+ struct vic_image **inputs,
+ unsigned int num_inputs);
+ void (*free)(struct vic *vic);
+};
+
+struct vic {
+ struct drm_tegra *drm;
+ struct drm_tegra_channel *channel;
+ struct drm_tegra_syncpoint *syncpt;
+ const struct vic_ops *ops;
+ unsigned int version;
+};
+
+int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp);
+void vic_free(struct vic *vic);
+
+int vic_clear(struct vic *vic, struct vic_image *output, unsigned int alpha,
+ unsigned int red, unsigned int green, unsigned int blue);
+
+struct vic_image {
+ struct drm_tegra_bo *bo;
+ struct drm_tegra_mapping *map;
+ unsigned int width;
+ unsigned int stride;
+ unsigned int pitch;
+ unsigned int height;
+ unsigned int format;
+ unsigned int kind;
+
+ size_t align;
+ size_t size;
+};
+
+const struct vic_format_info *vic_format_get_info(unsigned int format);
+
+int vic_image_new(struct vic *vic, unsigned int width, unsigned int height,
+ unsigned int format, unsigned int kind, uint32_t flags,
+ struct vic_image **imagep);
+void vic_image_free(struct vic_image *image);
+void vic_image_dump(struct vic_image *image, FILE *fp);
+
+#endif
diff --git a/tests/tegra/vic30.c b/tests/tegra/vic30.c
new file mode 100644
index 0000000..1bea6e7
--- /dev/null
+++ b/tests/tegra/vic30.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "private.h"
+#include "tegra.h"
+#include "vic.h"
+#include "vic30.h"
+
+struct vic30 {
+ struct vic base;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } config;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } filter;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } hist;
+};
+
+static int vic30_fill(struct vic *v, struct vic_image *output,
+ unsigned int left, unsigned int top,
+ unsigned int right, unsigned int bottom,
+ unsigned int alpha, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ struct vic30 *vic = container_of(v, struct vic30, base);
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->surfaceList0Struct.TargetRectLeft = left;
+ c->surfaceList0Struct.TargetRectTop = top;
+ c->surfaceList0Struct.TargetRectRight = right;
+ c->surfaceList0Struct.TargetRectBottom = bottom;
+
+ c->blending0Struct.PixelFormat = output->format;
+ c->blending0Struct.BackgroundAlpha = alpha;
+ c->blending0Struct.BackgroundR = red;
+ c->blending0Struct.BackgroundG = green;
+ c->blending0Struct.BackgroundB = blue;
+ c->blending0Struct.LumaWidth = output->stride - 1;
+ c->blending0Struct.LumaHeight = output->height - 1;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.TargetRectLeft = left;
+ c->blending0Struct.TargetRectTop = top;
+ c->blending0Struct.TargetRectRight = right;
+ c->blending0Struct.TargetRectBottom = bottom;
+ c->blending0Struct.SurfaceWidth = output->width - 1;
+ c->blending0Struct.SurfaceHeight = output->height - 1;
+ c->blending0Struct.BlkKind = output->kind;
+ c->blending0Struct.BlkHeight = 0;
+
+ c->fetchControl0Struct.TargetRectLeft = left;
+ c->fetchControl0Struct.TargetRectTop = top;
+ c->fetchControl0Struct.TargetRectRight = right;
+ c->fetchControl0Struct.TargetRectBottom = bottom;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic30_blit(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic30 *vic = container_of(v, struct vic30, base);
+ ColorConversionLumaAlphaStruct *ccla;
+ ColorConversionMatrixStruct *ccm;
+ ColorConversionClampStruct *ccc;
+ SurfaceListSurfaceStruct *s;
+ BlendingSurfaceStruct *b;
+ SurfaceCache0Struct *sc;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->surfaceList0Struct.TargetRectLeft = 0;
+ c->surfaceList0Struct.TargetRectTop = 0;
+ c->surfaceList0Struct.TargetRectRight = output->width - 1;
+ c->surfaceList0Struct.TargetRectBottom = output->height - 1;
+
+ c->blending0Struct.PixelFormat = output->format;
+ c->blending0Struct.BackgroundAlpha = 0;
+ c->blending0Struct.BackgroundR = 0;
+ c->blending0Struct.BackgroundG = 0;
+ c->blending0Struct.BackgroundB = 0;
+ c->blending0Struct.LumaWidth = output->stride - 1;
+ c->blending0Struct.LumaHeight = output->height - 1;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.TargetRectLeft = 0;
+ c->blending0Struct.TargetRectTop = 0;
+ c->blending0Struct.TargetRectRight = output->width - 1;
+ c->blending0Struct.TargetRectBottom = output->height - 1;
+ c->blending0Struct.SurfaceWidth = output->width - 1;
+ c->blending0Struct.SurfaceHeight = output->height - 1;
+ c->blending0Struct.BlkKind = output->kind;
+ c->blending0Struct.BlkHeight = 0;
+
+ c->fetchControl0Struct.TargetRectLeft = 0;
+ c->fetchControl0Struct.TargetRectTop = 0;
+ c->fetchControl0Struct.TargetRectRight = output->width - 1;
+ c->fetchControl0Struct.TargetRectBottom = output->height - 1;
+
+ /* setup fetch parameters for slot 0 */
+ c->fetchControl0Struct.Enable0 = 0x1;
+ c->fetchControl0Struct.Iir0 = 0x300;
+
+ /* setup cache parameters for slot 0 */
+ sc = &c->surfaceCache0Struct;
+ sc->PixelFormat0 = input->format;
+
+ /* setup surface configuration for slot 0 */
+ s = &c->surfaceListSurfaceStruct[0];
+ s->Enable = 1;
+ s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
+ s->PixelFormat = input->format;
+ s->SurfaceWidth = input->width - 1;
+ s->SurfaceHeight = input->height - 1;
+ s->LumaWidth = input->stride - 1;
+ s->LumaHeight = input->height - 1;
+ s->ChromaWidth = 16383;
+ s->ChromaHeight = 16383;
+ s->CacheWidth = VIC_CACHE_WIDTH_256Bx1; //VIC_CACHE_WIDTH_16Bx16;
+ s->BlkKind = input->kind;
+ s->BlkHeight = 0;
+ s->DestRectLeft = 0;
+ s->DestRectTop = 0;
+ s->DestRectRight = output->width - 1;
+ s->DestRectBottom = output->height - 1;
+ s->SourceRectLeft = 0 << 16;
+ s->SourceRectTop = 0 << 16;
+ s->SourceRectRight = (input->width - 1) << 16;
+ s->SourceRectBottom = (input->height - 1) << 16;
+
+ /* setup color conversion for slot 0 */
+ ccla = &c->colorConversionLumaAlphaStruct[0];
+ ccla->PlanarAlpha = 1023;
+ ccla->ConstantAlpha = 0;
+
+ ccm = &c->colorConversionMatrixStruct[0];
+ ccm->c00 = 1023;
+ ccm->c11 = 1023;
+ ccm->c22 = 1023;
+
+ ccc = &c->colorConversionClampStruct[0];
+ ccc->low = 0;
+ ccc->high = 1023;
+
+ /* setup blending for slot 0 */
+ b = &c->blendingSurfaceStruct[0];
+ b->AlphaK1 = 1023;
+ b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1;
+ b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1;
+ b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC;
+ b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic30_flip(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic30 *vic = container_of(v, struct vic30, base);
+ ColorConversionLumaAlphaStruct *ccla;
+ ColorConversionMatrixStruct *ccm;
+ ColorConversionClampStruct *ccc;
+ SurfaceListSurfaceStruct *s;
+ BlendingSurfaceStruct *b;
+ SurfaceCache0Struct *sc;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->surfaceList0Struct.TargetRectLeft = 0;
+ c->surfaceList0Struct.TargetRectTop = 0;
+ c->surfaceList0Struct.TargetRectRight = output->width - 1;
+ c->surfaceList0Struct.TargetRectBottom = output->height - 1;
+
+ c->blending0Struct.PixelFormat = output->format;
+ c->blending0Struct.BackgroundAlpha = 0;
+ c->blending0Struct.BackgroundR = 0;
+ c->blending0Struct.BackgroundG = 0;
+ c->blending0Struct.BackgroundB = 0;
+ c->blending0Struct.LumaWidth = output->stride - 1;
+ c->blending0Struct.LumaHeight = output->height - 1;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.ChromaWidth = 16383;
+ c->blending0Struct.TargetRectLeft = 0;
+ c->blending0Struct.TargetRectTop = 0;
+ c->blending0Struct.TargetRectRight = output->width - 1;
+ c->blending0Struct.TargetRectBottom = output->height - 1;
+ c->blending0Struct.SurfaceWidth = output->width - 1;
+ c->blending0Struct.SurfaceHeight = output->height - 1;
+ c->blending0Struct.BlkKind = output->kind;
+ c->blending0Struct.BlkHeight = 0;
+ c->blending0Struct.OutputFlipY = 1;
+
+ c->fetchControl0Struct.TargetRectLeft = 0;
+ c->fetchControl0Struct.TargetRectTop = 0;
+ c->fetchControl0Struct.TargetRectRight = output->width - 1;
+ c->fetchControl0Struct.TargetRectBottom = output->height - 1;
+
+ /* setup fetch parameters for slot 0 */
+ c->fetchControl0Struct.Enable0 = 0x1;
+ c->fetchControl0Struct.Iir0 = 0x300;
+
+ /* setup cache parameters for slot 0 */
+ sc = &c->surfaceCache0Struct;
+ sc->PixelFormat0 = input->format;
+
+ /* setup surface configuration for slot 0 */
+ s = &c->surfaceListSurfaceStruct[0];
+ s->Enable = 1;
+ s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
+ s->PixelFormat = input->format;
+ s->SurfaceWidth = input->width - 1;
+ s->SurfaceHeight = input->height - 1;
+ s->LumaWidth = input->stride - 1;
+ s->LumaHeight = input->height - 1;
+ s->ChromaWidth = 16383;
+ s->ChromaHeight = 16383;
+ s->CacheWidth = VIC_CACHE_WIDTH_256Bx1;
+ s->BlkKind = input->kind;
+ s->BlkHeight = 0;
+ s->DestRectLeft = 0;
+ s->DestRectTop = 0;
+ s->DestRectRight = output->width - 1;
+ s->DestRectBottom = output->height - 1;
+ s->SourceRectLeft = 0 << 16;
+ s->SourceRectTop = 0 << 16;
+ s->SourceRectRight = (input->width - 1) << 16;
+ s->SourceRectBottom = (input->height - 1) << 16;
+
+ /* setup color conversion for slot 0 */
+ ccla = &c->colorConversionLumaAlphaStruct[0];
+ ccla->PlanarAlpha = 1023;
+ ccla->ConstantAlpha = 0;
+
+ ccm = &c->colorConversionMatrixStruct[0];
+ ccm->c00 = 1023;
+ ccm->c11 = 1023;
+ ccm->c22 = 1023;
+
+ ccc = &c->colorConversionClampStruct[0];
+ ccc->low = 0;
+ ccc->high = 1023;
+
+ /* setup blending for slot 0 */
+ b = &c->blendingSurfaceStruct[0];
+ b->AlphaK1 = 1023;
+ b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1;
+ b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1;
+ b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC;
+ b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic30_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, struct vic_image *output,
+ struct vic_image **inputs, unsigned int num_inputs)
+{
+ struct vic30 *vic = container_of(v, struct vic30, base);
+ unsigned int i;
+
+ if (num_inputs > 1)
+ return -EINVAL;
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET, vic->hist.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
+
+ for (i = 0; i < num_inputs; i++)
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
+
+ return 0;
+}
+
+static void vic30_free(struct vic *v)
+{
+ struct vic30 *vic = container_of(v, struct vic30, base);
+
+ drm_tegra_channel_unmap(vic->hist.map);
+ drm_tegra_bo_unref(vic->hist.bo);
+
+ drm_tegra_channel_unmap(vic->filter.map);
+ drm_tegra_bo_unref(vic->filter.bo);
+
+ drm_tegra_channel_unmap(vic->config.map);
+ drm_tegra_bo_unref(vic->config.bo);
+
+ drm_tegra_syncpoint_free(v->syncpt);
+
+ free(vic);
+}
+
+static const struct vic_ops vic30_ops = {
+ .fill = vic30_fill,
+ .blit = vic30_blit,
+ .flip = vic30_flip,
+ .execute = vic30_execute,
+ .free = vic30_free,
+};
+
+int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp)
+{
+ struct vic30 *vic;
+ void *ptr;
+ int err;
+
+ vic = calloc(1, sizeof(*vic));
+ if (!vic)
+ return -ENOMEM;
+
+ vic->base.drm = drm;
+ vic->base.channel = channel;
+ vic->base.ops = &vic30_ops;
+ vic->base.version = 0x40;
+
+ err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->config.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_map(vic->filter.bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ memset(ptr, 0, 16384);
+ drm_tegra_bo_unmap(vic->filter.bo);
+
+ err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->filter.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 4096, &vic->hist.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate history buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_map(vic->hist.bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map history buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ memset(ptr, 0, 4096);
+ drm_tegra_bo_unmap(vic->hist.bo);
+
+ err = drm_tegra_channel_map(channel, vic->hist.bo, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
+ &vic->hist.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map histogram buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ if (vicp)
+ *vicp = &vic->base;
+
+ return 0;
+}
diff --git a/tests/tegra/vic30.h b/tests/tegra/vic30.h
new file mode 100644
index 0000000..d095c0d
--- /dev/null
+++ b/tests/tegra/vic30.h
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIC30_H
+#define VIC30_H
+
+#include <stdint.h>
+
+#define NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x200
+#define NVA0B6_VIDEO_COMPOSITOR_EXECUTE 0x300
+#define NVA0B6_VIDEO_COMPOSITOR_EXECUTE_AWAKEN (1 << 8)
+#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET 0x400
+#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_U_OFFSET 0x404
+#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_V_OFFSET 0x408
+#define NVA0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x700
+#define NVA0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x720
+#define NVA0B6_VIDEO_COMPOSITOR_SET_PALETTE_OFFSET 0x724
+#define NVA0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x728
+#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x730
+#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_CHROMA_U_OFFSET 0x734
+#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_CHROMA_V_OFFSET 0x738
+
+#define VIC_PIXEL_FORMAT_L8 1
+#define VIC_PIXEL_FORMAT_R8 4
+#define VIC_PIXEL_FORMAT_A8R8G8B8 32
+#define VIC_PIXEL_FORMAT_R8G8B8A8 34
+#define VIC_PIXEL_FORMAT_Y8_U8V8_N420 67
+#define VIC_PIXEL_FORMAT_Y8_V8U8_N420 68
+
+#define VIC_BLK_KIND_PITCH 0
+#define VIC_BLK_KIND_GENERIC_16Bx2 1
+
+typedef struct {
+ uint64_t DeNoise0 : 1; /* 0 */
+ uint64_t CadenceDetect0 : 1; /* 1 */
+ uint64_t MotionMap0 : 1; /* 2 */
+ uint64_t MedianFilter0 : 1; /* 3 */
+ uint64_t DeNoise1 : 1; /* 4 */
+ uint64_t CadenceDetect1 : 1; /* 5 */
+ uint64_t MotionMap1 : 1; /* 6 */
+ uint64_t MedianFilter1 : 1; /* 7 */
+ uint64_t DeNoise2 : 1; /* 8 */
+ uint64_t CadenceDetect2 : 1; /* 9 */
+ uint64_t MotionMap2 : 1; /* 10 */
+ uint64_t MedianFilter2 : 1; /* 11 */
+ uint64_t DeNoise3 : 1; /* 12 */
+ uint64_t CadenceDetect3 : 1; /* 13 */
+ uint64_t MotionMap3 : 1; /* 14 */
+ uint64_t MedianFilter3 : 1; /* 15 */
+ uint64_t DeNoise4 : 1; /* 16 */
+ uint64_t CadenceDetect4 : 1; /* 17 */
+ uint64_t MotionMap4 : 1; /* 18 */
+ uint64_t MedianFilter4 : 1; /* 19 */
+ uint64_t IsEven0 : 1; /* 20 */
+ uint64_t IsEven1 : 1; /* 21 */
+ uint64_t IsEven2 : 1; /* 22 */
+ uint64_t IsEven3 : 1; /* 23 */
+ uint64_t IsEven4 : 1; /* 24 */
+ uint64_t MMapCombine0 : 1; /* 25 */
+ uint64_t MMapCombine1 : 1; /* 26 */
+ uint64_t MMapCombine2 : 1; /* 27 */
+ uint64_t MMapCombine3 : 1; /* 28 */
+ uint64_t MMapCombine4 : 1; /* 29 */
+ uint64_t reserved0 : 2; /* 31..30 */
+ uint64_t PixelFormat0 : 7; /* 38..32 */
+ uint64_t reserved1 : 1; /* 39 */
+ uint64_t PixelFormat1 : 7; /* 46..40 */
+ uint64_t reserved2 : 1; /* 47 */
+ uint64_t PixelFormat2 : 7; /* 54..48 */
+ uint64_t reserved3 : 1; /* 55 */
+ uint64_t PixelFormat3 : 7; /* 62..56 */
+ uint64_t reserved4 : 1; /* 63 */
+ uint64_t PixelFormat4 : 7; /* 70..64 */
+ uint64_t reserved5 : 1; /* 71 */
+ uint64_t reserved6 : 24; /* 95..72 */
+ uint64_t PPMotion0 : 1; /* 96 */
+ uint64_t PPMotion1 : 1; /* 97 */
+ uint64_t PPMotion2 : 1; /* 98 */
+ uint64_t PPMotion3 : 1; /* 99 */
+ uint64_t PPMotion4 : 1; /* 100 */
+ uint64_t reserved7 : 3; /* 103..101 */
+ uint64_t ChromaEven0 : 1; /* 104 */
+ uint64_t ChromaEven1 : 1; /* 105 */
+ uint64_t ChromaEven2 : 1; /* 106 */
+ uint64_t ChromaEven3 : 1; /* 107 */
+ uint64_t ChromaEven4 : 1; /* 108 */
+ uint64_t reserved8 : 3; /* 111..109 */
+ uint64_t AdvancedDenoise0 : 1; /* 112 */
+ uint64_t AdvancedDenoise1 : 1; /* 113 */
+ uint64_t AdvancedDenoise2 : 1; /* 114 */
+ uint64_t AdvancedDenoise3 : 1; /* 115 */
+ uint64_t AdvancedDenoise4 : 1; /* 116 */
+ uint64_t reserved9 : 3; /* 119..117 */
+ uint64_t reserved10 : 8; /* 127..120 */
+} SurfaceCache0Struct;
+
+typedef struct {
+ uint64_t ClearRectMask0 : 8; /* 7..0 */
+ uint64_t ClearRectMask1 : 8; /* 15..8 */
+ uint64_t ClearRectMask2 : 8; /* 23..16 */
+ uint64_t ClearRectMask3 : 8; /* 31..24 */
+ uint64_t ClearRectMask4 : 8; /* 39..32 */
+ uint64_t reserved0 : 22; /* 61..40 */
+ uint64_t OutputFlipX : 1; /* 62 */
+ uint64_t OutputFlipY : 1; /* 63 */
+ uint64_t TargetRectLeft : 14; /* 77..64 */
+ uint64_t reserved1 : 2; /* 79..78 */
+ uint64_t TargetRectRight : 14; /* 93..80 */
+ uint64_t reserved2 : 2; /* 95..94 */
+ uint64_t TargetRectTop : 14; /* 109..96 */
+ uint64_t reserved3 : 2; /* 111..110 */
+ uint64_t TargetRectBottom : 14; /* 125..112 */
+ uint64_t reserved4 : 2; /* 127..126 */
+} SurfaceList0Struct;
+
+typedef struct {
+ uint64_t ClearRect0Left : 14; /* 13..0 */
+ uint64_t reserved0 : 2; /* 15..14 */
+ uint64_t ClearRect0Right : 14; /* 29..16 */
+ uint64_t reserved1 : 2; /* 31..30 */
+ uint64_t ClearRect0Top : 14; /* 45..32 */
+ uint64_t reserved2 : 2; /* 47..46 */
+ uint64_t ClearRect0Bottom : 14; /* 61..48 */
+ uint64_t reserved3 : 2; /* 63..62 */
+ uint64_t ClearRect1Left : 14; /* 77..64 */
+ uint64_t reserved4 : 2; /* 79..78 */
+ uint64_t ClearRect1Right : 14; /* 93..80 */
+ uint64_t reserved5 : 2; /* 95..94 */
+ uint64_t ClearRect1Top : 14; /* 109..96 */
+ uint64_t reserved6 : 2; /* 111..110 */
+ uint64_t ClearRect1Bottom : 14; /* 125..112 */
+ uint64_t reserved7 : 2; /* 127..126 */
+} SurfaceListClearRectStruct;
+
+typedef struct {
+ uint64_t Enable : 1; /* 0 */
+ uint64_t FrameFormat : 4; /* 4..1 */
+ uint64_t PixelFormat : 7; /* 11..5 */
+ uint64_t reserved0 : 2; /* 13..12 */
+ uint64_t ChromaLocHoriz : 2; /* 15..14 */
+ uint64_t ChromaLocVert : 2; /* 17..16 */
+ uint64_t Panoramic : 12; /* 29..18 */
+ uint64_t reserved1 : 4; /* 33..30 */
+ uint64_t SurfaceWidth : 14; /* 47..34 */
+ uint64_t reserved2 : 1; /* 48 */
+ uint64_t SurfaceHeight : 14; /* 62..49 */
+ uint64_t reserved3 : 1; /* 63 */
+ uint64_t LumaWidth : 14; /* 77..64 */
+ uint64_t reserved4 : 1; /* 78 */
+ uint64_t LumaHeight : 14; /* 92..79 */
+ uint64_t reserved5 : 1; /* 93 */
+ uint64_t ChromaWidth : 14; /* 107..94 */
+ uint64_t reserved6 : 1; /* 108 */
+ uint64_t ChromaHeight : 14; /* 122..109 */
+ uint64_t reserved7 : 1; /* 123 */
+ uint64_t CacheWidth : 3; /* 126..124 */
+ uint64_t reserved8 : 1; /* 127 */
+ /* 128 */
+ uint64_t FilterLengthY : 2; /* 1..0 */
+ uint64_t FilterLengthX : 2; /* 3..2 */
+ uint64_t DetailFltClamp : 6; /* 9..4 */
+ uint64_t reserved9 : 2; /* 11..10 */
+ uint64_t LightLevel : 4; /* 15..12 */
+ uint64_t reserved10 : 4; /* 19..16 */
+ uint64_t reserved11 : 8; /* 27..20 */
+ uint64_t reserved12 : 32; /* 59..28 */
+ uint64_t BlkKind : 4; /* 63..60 */
+ uint64_t DestRectLeft : 14; /* 77..64 */
+ uint64_t reserved13 : 1; /* 78 */
+ uint64_t DestRectRight : 14; /* 92..79 */
+ uint64_t reserved14 : 1; /* 93 */
+ uint64_t DestRectTop : 14; /* 107..94 */
+ uint64_t reserved15 : 1; /* 108 */
+ uint64_t DestRectBottom : 14; /* 122..109 */
+ uint64_t reserved16 : 1; /* 123 */
+ uint64_t BlkHeight : 4; /* 127..124 */
+ /* 256 */
+ uint64_t SourceRectLeft : 30; /* 29..0 */
+ uint64_t reserved17 : 2; /* 31..30 */
+ uint64_t SourceRectRight : 30; /* 61..32 */
+ uint64_t reserved18 : 2; /* 63..62 */
+ uint64_t SourceRectTop : 30; /* 93..64 */
+ uint64_t reserved19 : 2; /* 95..94 */
+ uint64_t SourceRectBottom : 30; /* 125..96 */
+ uint64_t reserved20 : 2; /* 127..126 */
+} SurfaceListSurfaceStruct;
+
+typedef struct {
+ uint64_t l0 : 20; /* 19..0 */
+ uint64_t l1 : 20; /* 39..20 */
+ uint64_t l2 : 20; /* 59..40 */
+ uint64_t r_shift : 4; /* 63..60 */
+ uint64_t l3 : 20; /* 83..64 */
+ uint64_t PlanarAlpha : 10; /* 93..84 */
+ uint64_t ConstantAlpha : 1; /* 94 */
+ uint64_t ClipEnabled : 1; /* 95 */
+ uint64_t LumaKeyLower : 10; /* 105..96 */
+ uint64_t reserved6 : 3; /* 108..106 */
+ uint64_t StereoInterleave : 3; /* 111..109 */
+ uint64_t LumaKeyUpper : 10; /* 121..112 */
+ uint64_t reserved7 : 2; /* 123..122 */
+ uint64_t reserved8 : 1; /* 124 */
+ uint64_t LumaKeyEnabled : 1; /* 125 */
+ uint64_t reserved9 : 2; /* 127..126 */
+} ColorConversionLumaAlphaStruct;
+
+typedef struct {
+ uint64_t c00 : 20; /* 19..0 */
+ uint64_t c10 : 20; /* 39..20 */
+ uint64_t c20 : 20; /* 59..40 */
+ uint64_t r_shift : 4; /* 63..60 */
+ uint64_t c01 : 20; /* 83..64 */
+ uint64_t c11 : 20; /* 103..84 */
+ uint64_t c21 : 20; /* 123..104 */
+ uint64_t reserved0 : 4; /* 127..124 */
+ /* 128 */
+ uint64_t c02 : 20; /* 19..0 */
+ uint64_t c12 : 20; /* 39..20 */
+ uint64_t c22 : 20; /* 59..40 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t c03 : 20; /* 83..64 */
+ uint64_t c13 : 20; /* 103..84 */
+ uint64_t c23 : 20; /* 123..104 */
+ uint64_t reserved2 : 4; /* 127..124 */
+} ColorConversionMatrixStruct;
+
+typedef struct {
+ uint64_t low : 10; /* 9..0 */
+ uint64_t reserved0 : 6; /* 15..10 */
+ uint64_t high : 10; /* 25..16 */
+ uint64_t reserved1 : 6; /* 31..26 */
+ uint64_t reserved2 : 32; /* 63..32 */
+ uint64_t reserved3 : 32; /* 95..64 */
+ uint64_t reserved4 : 32; /* 127..96 */
+} ColorConversionClampStruct;
+
+typedef struct {
+ uint64_t PixelFormat : 7; /* 6..0 */
+ uint64_t reserved0 : 1; /* 7 */
+ uint64_t AlphaFillMode : 3; /* 10..8 */
+ uint64_t AlphaFillSlot : 3; /* 13..11 */
+ uint64_t BackgroundAlpha : 10; /* 23..14 */
+ uint64_t BackgroundR : 10; /* 33..24 */
+ uint64_t BackgroundG : 10; /* 43..34 */
+ uint64_t BackgroundB : 10; /* 53..44 */
+ uint64_t ChromaLocHoriz : 2; /* 55..54 */
+ uint64_t ChromaLocVert : 2; /* 57..56 */
+ uint64_t reserved1 : 6; /* 63..58 */
+ uint64_t LumaWidth : 14; /* 77..64 */
+ uint64_t reserved2 : 2; /* 79..78 */
+ uint64_t LumaHeight : 14; /* 93..80 */
+ uint64_t reserved3 : 2; /* 95..94 */
+ uint64_t ChromaWidth : 14; /* 109..96 */
+ uint64_t reserved4 : 2; /* 111..110 */
+ uint64_t ChromaHeight : 14; /* 125..112 */
+ uint64_t reserved5 : 2; /* 127..126 */
+ /* 128 */
+ uint64_t TargetRectLeft : 14; /* 13..0 */
+ uint64_t reserved6 : 2; /* 15..14 */
+ uint64_t TargetRectRight : 14; /* 29..16 */
+ uint64_t reserved7 : 2; /* 31..30 */
+ uint64_t TargetRectTop : 14; /* 45..32 */
+ uint64_t reserved8 : 2; /* 47..46 */
+ uint64_t TargetRectBottom : 14; /* 61..48 */
+ uint64_t reserved9 : 2; /* 63..62 */
+ uint64_t SurfaceWidth : 14; /* 77..64 */
+ uint64_t reserved10 : 2; /* 79..78 */
+ uint64_t SurfaceHeight : 14; /* 93..80 */
+ uint64_t reserved11 : 2; /* 95..94 */
+ uint64_t BlkKind : 4; /* 99..96 */
+ uint64_t BlkHeight : 4; /* 103..100 */
+ uint64_t OutputFlipX : 1; /* 104 */
+ uint64_t OutputFlipY : 1; /* 105 */
+ uint64_t OutputTranspose : 1; /* 106 */
+ uint64_t reserved12 : 21; /* 127..107 */
+} Blending0Struct;
+
+typedef struct {
+ uint64_t AlphaK1 : 10; /* 9..0 */
+ uint64_t reserved0 : 6; /* 15..10 */
+ uint64_t AlphaK2 : 10; /* 25..16 */
+ uint64_t reserved1 : 6; /* 31..26 */
+ uint64_t SrcFactCMatchSelect : 3; /* 34..32 */
+ uint64_t reserved2 : 1; /* 35 */
+ uint64_t DstFactCMatchSelect : 3; /* 38..36 */
+ uint64_t reserved3 : 1; /* 39 */
+ uint64_t SrcFactAMatchSelect : 3; /* 42..40 */
+ uint64_t reserved4 : 1; /* 43 */
+ uint64_t DstFactAMatchSelect : 3; /* 46..44 */
+ uint64_t reserved5 : 1; /* 47 */
+ uint64_t reserved6 : 4; /* 51..48 */
+ uint64_t reserved7 : 4; /* 55..52 */
+ uint64_t reserved8 : 4; /* 59..56 */
+ uint64_t reserved9 : 4; /* 63..60 */
+ uint64_t reserved10 : 2; /* 65..64 */
+ uint64_t OverrideR : 10; /* 75..66 */
+ uint64_t OverrideG : 10; /* 85..76 */
+ uint64_t OverrideB : 10; /* 95..86 */
+ uint64_t OverrideA : 10; /* 105..96 */
+ uint64_t reserved11 : 2; /* 107..106 */
+ uint64_t UseOverrideR : 1; /* 108 */
+ uint64_t UseOverrideG : 1; /* 109 */
+ uint64_t UseOverrideB : 1; /* 110 */
+ uint64_t UseOverrideA : 1; /* 111 */
+ uint64_t MaskR : 1; /* 112 */
+ uint64_t MaskG : 1; /* 113 */
+ uint64_t MaskB : 1; /* 114 */
+ uint64_t MaskA : 1; /* 115 */
+ uint64_t reserved12 : 12; /* 127..116 */
+} BlendingSurfaceStruct;
+
+typedef struct {
+ uint64_t TargetRectLeft : 14; /* 13..0 */
+ uint64_t reserved0 : 2; /* 15..14 */
+ uint64_t TargetRectRight : 14; /* 29..16 */
+ uint64_t reserved1 : 2; /* 31..30 */
+ uint64_t TargetRectTop : 14; /* 45..32 */
+ uint64_t reserved2 : 2; /* 47..46 */
+ uint64_t TargetRectBottom : 14; /* 61..48 */
+ uint64_t reserved3 : 2; /* 63..62 */
+ uint64_t Enable0 : 8; /* 71..64 */
+ uint64_t Enable1 : 8; /* 79..72 */
+ uint64_t Enable2 : 8; /* 87..80 */
+ uint64_t Enable3 : 8; /* 95..88 */
+ uint64_t Enable4 : 8; /* 103..96 */
+ uint64_t DownsampleHoriz : 11; /* 114..104 */
+ uint64_t reserved4 : 1; /* 115 */
+ uint64_t DownsampleVert : 11; /* 126..116 */
+ uint64_t reserved5 : 1; /* 127 */
+ /* 128 */
+ uint64_t FilterNoise0 : 10; /* 9..0 */
+ uint64_t FilterDetail0 : 10; /* 19..10 */
+ uint64_t FilterNoise1 : 10; /* 29..20 */
+ uint64_t reserved6 : 2; /* 31..30 */
+ uint64_t FilterDetail1 : 10; /* 41..32 */
+ uint64_t FilterNoise2 : 10; /* 51..42 */
+ uint64_t FilterDetail2 : 10; /* 61..52 */
+ uint64_t reserved7 : 2; /* 63..62 */
+ uint64_t FilterNoise3 : 10; /* 73..64 */
+ uint64_t FilterDetail3 : 10; /* 83..74 */
+ uint64_t FilterNoise4 : 10; /* 93..84 */
+ uint64_t reserved8 : 2; /* 95..94 */
+ uint64_t FilterDetail4 : 10; /* 105..96 */
+ uint64_t reserved9 : 22; /* 127..106 */
+ /* 256 */
+ uint64_t ChromaNoise0 : 10; /* 9..0 */
+ uint64_t ChromaDetail0 : 10; /* 19..10 */
+ uint64_t ChromaNoise1 : 10; /* 29..20 */
+ uint64_t reserved10 : 2; /* 31..30 */
+ uint64_t ChromaDetail1 : 10; /* 41..32 */
+ uint64_t ChromaNoise2 : 10; /* 51..42 */
+ uint64_t ChromaDetail2 : 10; /* 61..52 */
+ uint64_t reserved11 : 2; /* 63..62 */
+ uint64_t ChromaNoise3 : 10; /* 73..64 */
+ uint64_t ChromaDetail3 : 10; /* 83..74 */
+ uint64_t ChromaNoise4 : 10; /* 93..84 */
+ uint64_t reserved12 : 2; /* 95..94 */
+ uint64_t ChromaDetail4 : 10; /* 105..96 */
+ uint64_t reserved13 : 22; /* 127..106 */
+ /* 384 */
+ uint64_t Mode0 : 4; /* 3..0 */
+ uint64_t AccumWeight0 : 3; /* 6..4 */
+ uint64_t Iir0 : 11; /* 17..7 */
+ uint64_t reserved14 : 2; /* 19..18 */
+ uint64_t Mode1 : 4; /* 23..20 */
+ uint64_t AccumWeight1 : 3; /* 26..24 */
+ uint64_t Iir1 : 11; /* 37..27 */
+ uint64_t reserved15 : 2; /* 39..38 */
+ uint64_t Mode2 : 4; /* 43..40 */
+ uint64_t AccumWeight2 : 3; /* 46..44 */
+ uint64_t Iir2 : 11; /* 57..47 */
+ uint64_t reserved16 : 6; /* 63..58 */
+ uint64_t Mode3 : 4; /* 67..64 */
+ uint64_t AccumWeight3 : 3; /* 70..68 */
+ uint64_t Iir3 : 11; /* 81..71 */
+ uint64_t reserved17 : 2; /* 83..82 */
+ uint64_t Mode4 : 4; /* 87..84 */
+ uint64_t AccumWeight4 : 3; /* 90..88 */
+ uint64_t Iir4 : 11; /* 101..91 */
+ uint64_t reserved18 : 8; /* 109..102 */
+ uint64_t OutputFlipX : 1; /* 110 */
+ uint64_t OutputFlipY : 1; /* 111 */
+ uint64_t reserved19 : 10; /* 121..112 */
+ uint64_t reserved20 : 6; /* 127..122 */
+} FetchControl0Struct;
+
+typedef struct {
+ uint64_t f00 : 10; /* 9..0 */
+ uint64_t f10 : 10; /* 19..10 */
+ uint64_t f20 : 10; /* 29..20 */
+ uint64_t reserved0 : 2; /* 31..30 */
+ uint64_t f01 : 10; /* 41..32 */
+ uint64_t f11 : 10; /* 51..42 */
+ uint64_t f21 : 10; /* 61..52 */
+ uint64_t reserved1 : 2; /* 63..62 */
+ uint64_t f02 : 10; /* 73..64 */
+ uint64_t f12 : 10; /* 83..74 */
+ uint64_t f22 : 10; /* 93..84 */
+ uint64_t reserved2 : 2; /* 95..94 */
+ uint64_t f03 : 10; /* 105..96 */
+ uint64_t f13 : 10; /* 115..106 */
+ uint64_t f23 : 10; /* 125..116 */
+ uint64_t reserved3 : 2; /* 127..126 */
+} FetchControlCoeffStruct;
+
+typedef struct {
+ SurfaceCache0Struct surfaceCache0Struct;
+ SurfaceList0Struct surfaceList0Struct;
+ SurfaceListClearRectStruct surfaceListClearRectStruct[4];
+ SurfaceListSurfaceStruct surfaceListSurfaceStruct[5];
+ ColorConversionLumaAlphaStruct colorConversionLumaAlphaStruct[5];
+ ColorConversionMatrixStruct colorConversionMatrixStruct[5];
+ ColorConversionClampStruct colorConversionClampStruct[5];
+ Blending0Struct blending0Struct;
+ BlendingSurfaceStruct blendingSurfaceStruct[5];
+ FetchControl0Struct fetchControl0Struct;
+ FetchControlCoeffStruct fetchControlCoeffStruct[520];
+} ConfigStruct;
+
+#endif
diff --git a/tests/tegra/vic40.c b/tests/tegra/vic40.c
new file mode 100644
index 0000000..1af0925
--- /dev/null
+++ b/tests/tegra/vic40.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "private.h"
+#include "tegra.h"
+#include "vic.h"
+#include "vic40.h"
+
+struct vic40 {
+ struct vic base;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } config;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } filter;
+};
+
+static int vic40_fill(struct vic *v, struct vic_image *output,
+ unsigned int left, unsigned int top,
+ unsigned int right, unsigned int bottom,
+ unsigned int alpha, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ struct vic40 *vic = container_of(v, struct vic40, base);
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = top;
+ c->outputConfig.TargetRectLeft = left;
+ c->outputConfig.TargetRectRight = right;
+ c->outputConfig.TargetRectBottom = bottom;
+ c->outputConfig.BackgroundAlpha = alpha;
+ c->outputConfig.BackgroundR = red;
+ c->outputConfig.BackgroundG = green;
+ c->outputConfig.BackgroundB = blue;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic40_blit(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic40 *vic = container_of(v, struct vic40, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 1023;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 1023;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic40_flip(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic40 *vic = container_of(v, struct vic40, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 1023;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+ c->outputConfig.OutputFlipY = 1;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 1023;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic40_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, struct vic_image *output,
+ struct vic_image **inputs, unsigned int num_inputs)
+{
+ struct vic40 *vic = container_of(v, struct vic40, base);
+ unsigned int i;
+
+ if (num_inputs > 1)
+ return -EINVAL;
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
+
+ for (i = 0; i < num_inputs; i++)
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
+
+ return 0;
+}
+
+static void vic40_free(struct vic *v)
+{
+ struct vic40 *vic = container_of(v, struct vic40, base);
+
+ drm_tegra_channel_unmap(vic->filter.map);
+ drm_tegra_bo_unref(vic->filter.bo);
+
+ drm_tegra_channel_unmap(vic->config.map);
+ drm_tegra_bo_unref(vic->config.bo);
+
+ drm_tegra_syncpoint_free(v->syncpt);
+
+ free(vic);
+}
+
+static const struct vic_ops vic40_ops = {
+ .fill = vic40_fill,
+ .blit = vic40_blit,
+ .flip = vic40_flip,
+ .execute = vic40_execute,
+ .free = vic40_free,
+};
+
+int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp)
+{
+ struct vic40 *vic;
+ void *ptr;
+ int err;
+
+ vic = calloc(1, sizeof(*vic));
+ if (!vic)
+ return -ENOMEM;
+
+ vic->base.drm = drm;
+ vic->base.channel = channel;
+ vic->base.ops = &vic40_ops;
+ vic->base.version = 0x21;
+
+ err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate configuration structurer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->config.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_map(vic->filter.bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ memset(ptr, 0, 16384);
+ drm_tegra_bo_unmap(vic->filter.bo);
+
+ err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->filter.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ if (vicp)
+ *vicp = &vic->base;
+
+ return 0;
+}
diff --git a/tests/tegra/vic40.h b/tests/tegra/vic40.h
new file mode 100644
index 0000000..a62301a
--- /dev/null
+++ b/tests/tegra/vic40.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright © 2016-2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIC40_H
+#define VIC40_H
+
+#include <stdint.h>
+
+#define NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x00000200
+#define NVB0B6_VIDEO_COMPOSITOR_EXECUTE 0x00000300
+#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET 0x00000400
+#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_U_OFFSET 0x00000404
+#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_V_OFFSET 0x00000408
+#define NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x00000704
+#define NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x00000708
+#define NVB0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x00000714
+#define NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x00000720
+
+typedef struct {
+ uint64_t SlotEnable : 1; /* 0 */
+ uint64_t DeNoise : 1; /* 1 */
+ uint64_t AdvancedDenoise : 1; /* 2 */
+ uint64_t CadenceDetect : 1; /* 3 */
+ uint64_t MotionMap : 1; /* 4 */
+ uint64_t MMapCombine : 1; /* 5 */
+ uint64_t IsEven : 1; /* 6 */
+ uint64_t ChromaEven : 1; /* 7 */
+ uint64_t CurrentFieldEnable : 1; /* 8 */
+ uint64_t PrevFieldEnable : 1; /* 9 */
+ uint64_t NextFieldEnable : 1; /* 10 */
+ uint64_t NextNrFieldEnable : 1; /* 11 */
+ uint64_t CurMotionFieldEnable : 1; /* 12 */
+ uint64_t PrevMotionFieldEnable : 1; /* 13 */
+ uint64_t PpMotionFieldEnable : 1; /* 14 */
+ uint64_t CombMotionFieldEnable : 1; /* 15 */
+ uint64_t FrameFormat : 4; /* 19..16 */
+ uint64_t FilterLengthY : 2; /* 21..20 */
+ uint64_t FilterLengthX : 2; /* 23..22 */
+ uint64_t Panoramic : 12; /* 35..24 */
+ uint64_t reserved1 : 22; /* 57..36 */
+ uint64_t DetailFltClamp : 6; /* 63..58 */
+ uint64_t FilterNoise : 10; /* 73..64 */
+ uint64_t FilterDetail : 10; /* 83..74 */
+ uint64_t ChromaNoise : 10; /* 93..84 */
+ uint64_t ChromaDetail : 10; /* 103..94 */
+ uint64_t DeinterlaceMode : 4; /* 107..104 */
+ uint64_t MotionAccumWeight : 3; /* 110..108 */
+ uint64_t NoiseIir : 11; /* 121..111 */
+ uint64_t LightLevel : 4; /* 125..122 */
+ uint64_t reserved4 : 2; /* 127..126 */
+ /* 128 */
+ uint64_t SoftClampLow : 10; /* 9..0 */
+ uint64_t SoftClampHigh : 10; /* 19..10 */
+ uint64_t reserved5 : 3; /* 22..20 */
+ uint64_t reserved6 : 9; /* 31..23 */
+ uint64_t PlanarAlpha : 10; /* 41..32 */
+ uint64_t ConstantAlpha : 1; /* 42 */
+ uint64_t StereoInterleave : 3; /* 45..43 */
+ uint64_t ClipEnabled : 1; /* 46 */
+ uint64_t ClearRectMask : 8; /* 54..47 */
+ uint64_t DegammaMode : 2; /* 56..55 */
+ uint64_t reserved7 : 1; /* 57 */
+ uint64_t DecompressEnable : 1; /* 58 */
+ uint64_t reserved9 : 5; /* 63..59 */
+ uint64_t DecompressCtbCount : 8; /* 71..64 */
+ uint64_t DecompressZbcColor : 32; /* 103..72 */
+ uint64_t reserved12 : 24; /* 127..104 */
+ /* 256 */
+ uint64_t SourceRectLeft : 30; /* 29..0 */
+ uint64_t reserved14 : 2; /* 31..30 */
+ uint64_t SourceRectRight : 30; /* 61..32 */
+ uint64_t reserved15 : 2; /* 63..62 */
+ uint64_t SourceRectTop : 30; /* 93..64 */
+ uint64_t reserved16 : 2; /* 95..94 */
+ uint64_t SourceRectBottom : 30; /* 125..96 */
+ uint64_t reserved17 : 2; /* 127..126 */
+ /* 384 */
+ uint64_t DestRectLeft : 14; /* 13..0 */
+ uint64_t reserved18 : 2; /* 15..14 */
+ uint64_t DestRectRight : 14; /* 29..16 */
+ uint64_t reserved19 : 2; /* 31..30 */
+ uint64_t DestRectTop : 14; /* 45..32 */
+ uint64_t reserved20 : 2; /* 47..46 */
+ uint64_t DestRectBottom : 14; /* 61..48 */
+ uint64_t reserved21 : 2; /* 63..62 */
+ uint64_t reserved22 : 32; /* 95..64 */
+ uint64_t reserved23 : 32; /* 127..96 */
+} SlotConfig;
+
+typedef struct {
+ uint64_t SlotPixelFormat : 7; /* 6..0 */
+ uint64_t SlotChromaLocHoriz : 2; /* 8..7 */
+ uint64_t SlotChromaLocVert : 2; /* 10..9 */
+ uint64_t SlotBlkKind : 4; /* 14..11 */
+ uint64_t SlotBlkHeight : 4; /* 18..15 */
+ uint64_t SlotCacheWidth : 3; /* 21..19 */
+ uint64_t reserved0 : 10; /* 31..22 */
+ uint64_t SlotSurfaceWidth : 14; /* 45..32 */
+ uint64_t SlotSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t SlotLumaWidth : 14; /* 77..64 */
+ uint64_t SlotLumaHeight : 14; /* 91..78 */
+ uint64_t reserved2 : 4; /* 95..92 */
+ uint64_t SlotChromaWidth : 14; /* 109..96 */
+ uint64_t SlotChromaHeight : 14; /* 123..110 */
+ uint64_t reserved3 : 4; /* 127..124 */
+} SlotSurfaceConfig;
+
+typedef struct {
+ uint64_t luma_coeff0 : 20; /* 19..0 */
+ uint64_t luma_coeff1 : 20; /* 39..20 */
+ uint64_t luma_coeff2 : 20; /* 59..40 */
+ uint64_t luma_r_shift : 4; /* 63..60 */
+ uint64_t luma_coeff3 : 20; /* 83..64 */
+ uint64_t LumaKeyLower : 10; /* 93..84 */
+ uint64_t LumaKeyUpper : 10; /* 103..94 */
+ uint64_t LumaKeyEnabled : 1; /* 104 */
+ uint64_t reserved0 : 2; /* 106..105 */
+ uint64_t reserved1 : 21; /* 127..107 */
+} LumaKeyStruct;
+
+typedef struct {
+ uint64_t matrix_coeff00 : 20; /* 19..0 */
+ uint64_t matrix_coeff10 : 20; /* 39..20 */
+ uint64_t matrix_coeff20 : 20; /* 59..40 */
+ uint64_t matrix_r_shift : 4; /* 63..60 */
+ uint64_t matrix_coeff01 : 20; /* 83..64 */
+ uint64_t matrix_coeff11 : 20; /* 103..84 */
+ uint64_t matrix_coeff21 : 20; /* 123..104 */
+ uint64_t reserved0 : 3; /* 126..124 */
+ uint64_t matrix_enable : 1; /* 127 */
+ /* 128 */
+ uint64_t matrix_coeff02 : 20; /* 19..0 */
+ uint64_t matrix_coeff12 : 20; /* 39..20 */
+ uint64_t matrix_coeff22 : 20; /* 59..40 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t matrix_coeff03 : 20; /* 83..64 */
+ uint64_t matrix_coeff13 : 20; /* 103..84 */
+ uint64_t matrix_coeff23 : 20; /* 123..104 */
+ uint64_t reserved2 : 4; /* 127..124 */
+} MatrixStruct;
+
+typedef struct {
+ uint64_t ClearRect0Left : 14; /* 13..0 */
+ uint64_t reserved0 : 2; /* 15..14 */
+ uint64_t ClearRect0Right : 14; /* 29..16 */
+ uint64_t reserved1 : 2; /* 31..30 */
+ uint64_t ClearRect0Top : 14; /* 45..32 */
+ uint64_t reserved2 : 2; /* 47..46 */
+ uint64_t ClearRect0Bottom : 14; /* 61..48 */
+ uint64_t reserved3 : 2; /* 63..62 */
+ uint64_t ClearRect1Left : 14; /* 77..64 */
+ uint64_t reserved4 : 2; /* 79..78 */
+ uint64_t ClearRect1Right : 14; /* 93..80 */
+ uint64_t reserved5 : 2; /* 95..94 */
+ uint64_t ClearRect1Top : 14; /* 109..96 */
+ uint64_t reserved6 : 2; /* 111..110 */
+ uint64_t ClearRect1Bottom : 14; /* 125..112 */
+ uint64_t reserved7 : 2; /* 127..126 */
+} ClearRectStruct;
+
+typedef struct {
+ uint64_t AlphaK1 : 10; /* 9..0 */
+ uint64_t reserved0 : 6; /* 15..10 */
+ uint64_t AlphaK2 : 10; /* 25..16 */
+ uint64_t reserved1 : 6; /* 31..26 */
+ uint64_t SrcFactCMatchSelect : 3; /* 34..32 */
+ uint64_t reserved2 : 1; /* 35 */
+ uint64_t DstFactCMatchSelect : 3; /* 38..36 */
+ uint64_t reserved3 : 1; /* 39 */
+ uint64_t SrcFactAMatchSelect : 3; /* 42..40 */
+ uint64_t reserved4 : 1; /* 43 */
+ uint64_t DstFactAMatchSelect : 3; /* 46..44 */
+ uint64_t reserved5 : 1; /* 47 */
+ uint64_t reserved6 : 4; /* 51..48 */
+ uint64_t reserved7 : 4; /* 55..52 */
+ uint64_t reserved8 : 4; /* 59..56 */
+ uint64_t reserved9 : 4; /* 63..60 */
+ uint64_t reserved10 : 2; /* 65..64 */
+ uint64_t OverrideR : 10; /* 75..66 */
+ uint64_t OverrideG : 10; /* 85..76 */
+ uint64_t OverrideB : 10; /* 95..86 */
+ uint64_t OverrideA : 10; /* 105..96 */
+ uint64_t reserved11 : 2; /* 107..106 */
+ uint64_t UseOverrideR : 1; /* 108 */
+ uint64_t UseOverrideG : 1; /* 109 */
+ uint64_t UseOverrideB : 1; /* 110 */
+ uint64_t UseOverrideA : 1; /* 111 */
+ uint64_t MaskR : 1; /* 112 */
+ uint64_t MaskG : 1; /* 113 */
+ uint64_t MaskB : 1; /* 114 */
+ uint64_t MaskA : 1; /* 115 */
+ uint64_t reserved12 : 12; /* 127..116 */
+} BlendingSlotStruct;
+
+typedef struct {
+ uint64_t AlphaFillMode : 3; /* 2..0 */
+ uint64_t AlphaFillSlot : 3; /* 5..3 */
+ uint64_t BackgroundAlpha : 10; /* 15..6 */
+ uint64_t BackgroundR : 10; /* 25..16 */
+ uint64_t BackgroundG : 10; /* 35..26 */
+ uint64_t BackgroundB : 10; /* 45..36 */
+ uint64_t RegammaMode : 2; /* 47..46 */
+ uint64_t OutputFlipX : 1; /* 48 */
+ uint64_t OutputFlipY : 1; /* 49 */
+ uint64_t OutputTranspose : 1; /* 50 */
+ uint64_t reserved1 : 1; /* 51 */
+ uint64_t reserved2 : 12; /* 63..52 */
+ uint64_t TargetRectLeft : 14; /* 77..64 */
+ uint64_t reserved3 : 2; /* 79..78 */
+ uint64_t TargetRectRight : 14; /* 93..80 */
+ uint64_t reserved4 : 2; /* 95..94 */
+ uint64_t TargetRectTop : 14; /* 109..96 */
+ uint64_t reserved5 : 2; /* 111..110 */
+ uint64_t TargetRectBottom : 14; /* 125..112 */
+ uint64_t reserved6 : 2; /* 127..126 */
+} OutputConfig;
+
+typedef struct {
+ uint64_t OutPixelFormat : 7; /* 6..0 */
+ uint64_t OutChromaLocHoriz : 2; /* 8..7 */
+ uint64_t OutChromaLocVert : 2; /* 10..9 */
+ uint64_t OutBlkKind : 4; /* 14..11 */
+ uint64_t OutBlkHeight : 4; /* 18..15 */
+ uint64_t reserved0 : 3; /* 21..19 */
+ uint64_t reserved1 : 10; /* 31..22 */
+ uint64_t OutSurfaceWidth : 14; /* 45..32 */
+ uint64_t OutSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved2 : 4; /* 63..60 */
+ uint64_t OutLumaWidth : 14; /* 77..64 */
+ uint64_t OutLumaHeight : 14; /* 91..78 */
+ uint64_t reserved3 : 4; /* 95..92 */
+ uint64_t OutChromaWidth : 14; /* 109..96 */
+ uint64_t OutChromaHeight : 14; /* 123..110 */
+ uint64_t reserved4 : 4; /* 127..124 */
+} OutputSurfaceConfig;
+
+typedef struct {
+ uint64_t DownsampleHoriz : 11; /* 10..0 */
+ uint64_t reserved0 : 5; /* 15..11 */
+ uint64_t DownsampleVert : 11; /* 26..16 */
+ uint64_t reserved1 : 5; /* 31..27 */
+ uint64_t reserved2 : 32; /* 63..32 */
+ uint64_t reserved3 : 32; /* 95..64 */
+ uint64_t reserved4 : 32; /* 127..96 */
+} PipeConfig;
+
+typedef struct {
+ SlotConfig slotConfig;
+ SlotSurfaceConfig slotSurfaceConfig;
+ LumaKeyStruct lumaKeyStruct;
+ MatrixStruct colorMatrixStruct;
+ MatrixStruct gamutMatrixStruct;
+ BlendingSlotStruct blendingSlotStruct;
+} SlotStruct;
+
+typedef struct {
+ PipeConfig pipeConfig;
+ OutputConfig outputConfig;
+ OutputSurfaceConfig outputSurfaceConfig;
+ MatrixStruct outColorMatrixStruct;
+ ClearRectStruct clearRectStruct[4];
+ SlotStruct slotStruct[8];
+} ConfigStruct;
+
+#endif
diff --git a/tests/tegra/vic41.c b/tests/tegra/vic41.c
new file mode 100644
index 0000000..edbc748
--- /dev/null
+++ b/tests/tegra/vic41.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "private.h"
+#include "tegra.h"
+#include "vic.h"
+#include "vic41.h"
+
+struct vic41 {
+ struct vic base;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } config;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } filter;
+};
+
+static int vic41_fill(struct vic *v, struct vic_image *output,
+ unsigned int left, unsigned int top,
+ unsigned int right, unsigned int bottom,
+ unsigned int alpha, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ struct vic41 *vic = container_of(v, struct vic41, base);
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = top;
+ c->outputConfig.TargetRectLeft = left;
+ c->outputConfig.TargetRectRight = right;
+ c->outputConfig.TargetRectBottom = bottom;
+ c->outputConfig.BackgroundAlpha = alpha;
+ c->outputConfig.BackgroundR = red;
+ c->outputConfig.BackgroundG = green;
+ c->outputConfig.BackgroundB = blue;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic41_blit(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic41 *vic = container_of(v, struct vic41, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 255;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 255;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic41_flip(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic41 *vic = container_of(v, struct vic41, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 255;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+ c->outputConfig.OutputFlipY = 1;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 255;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic41_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, struct vic_image *output,
+ struct vic_image **inputs, unsigned int num_inputs)
+{
+ struct vic41 *vic = container_of(v, struct vic41, base);
+ unsigned int i;
+
+ if (num_inputs > 1)
+ return -EINVAL;
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET, vic->filter.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
+
+ for (i = 0; i < num_inputs; i++) {
+ uint32_t method = NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(0) + (i * 3) * 4;
+
+ VIC_PUSH_BUFFER(pushbuf, ptrp, method, inputs[i]->map, 0, 0);
+ }
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
+
+ return 0;
+}
+
+static void vic41_free(struct vic *v)
+{
+ struct vic41 *vic = container_of(v, struct vic41, base);
+
+ drm_tegra_channel_unmap(vic->filter.map);
+ drm_tegra_bo_unref(vic->filter.bo);
+
+ drm_tegra_channel_unmap(vic->config.map);
+ drm_tegra_bo_unref(vic->config.bo);
+
+ drm_tegra_syncpoint_free(v->syncpt);
+
+ free(vic);
+}
+
+static const struct vic_ops vic41_ops = {
+ .fill = vic41_fill,
+ .blit = vic41_blit,
+ .flip = vic41_flip,
+ .execute = vic41_execute,
+ .free = vic41_free,
+};
+
+int vic41_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp)
+{
+ struct vic41 *vic;
+ void *ptr;
+ int err;
+
+ vic = calloc(1, sizeof(*vic));
+ if (!vic)
+ return -ENOMEM;
+
+ vic->base.drm = drm;
+ vic->base.channel = channel;
+ vic->base.ops = &vic41_ops;
+ vic->base.version = 0x18;
+
+ err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate configuration structurer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->config.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_map(vic->filter.bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ memset(ptr, 0, 16384);
+ drm_tegra_bo_unmap(vic->filter.bo);
+
+ err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->filter.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ if (vicp)
+ *vicp = &vic->base;
+
+ return 0;
+}
diff --git a/tests/tegra/vic41.h b/tests/tegra/vic41.h
new file mode 100644
index 0000000..07d7019
--- /dev/null
+++ b/tests/tegra/vic41.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIC41_H
+#define VIC41_H
+
+#include <stdint.h>
+
+#define NVB1B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x00000200
+#define NVB1B6_VIDEO_COMPOSITOR_EXECUTE 0x00000300
+#define NVB1B6_VIDEO_COMPOSITOR_SET_PICTURE_INDEX 0x00000700
+#define NVB1B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x00000704
+#define NVB1B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x00000708
+#define NVB1B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET 0x0000070c
+#define NVB1B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x00000714
+#define NVB1B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x00000720
+#define NVB1B6_VIDEO_COMPOSITOR_SET_HISTORY_BUFFER_OFFSET(slot) (0x00000780 + (slot) * 4)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(slot) (0x00001200 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_U_OFFSET(slot) (0x00001204 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_V_OFFSET(slot) (0x00001208 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_LUMA_OFFSET(slot) (0x0000120c + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_U_OFFSET(slot) (0x00001210 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_V_OFFSET(slot) (0x00001214 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_LUMA_OFFSET(slot) (0x00001218 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_U_OFFSET(slot) (0x0000121c + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_V_OFFSET(slot) (0x00001220 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_LUMA_OFFSET(slot) (0x00001224 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_U_OFFSET(slot) (0x00001228 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_V_OFFSET(slot) (0x0000122c + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_LUMA_OFFSET(slot) (0x00001230 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_U_OFFSET(slot) (0x00001234 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_V_OFFSET(slot) (0x00001238 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_LUMA_OFFSET(slot) (0x0000123c + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_U_OFFSET(slot) (0x00001240 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_V_OFFSET(slot) (0x00001244 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_LUMA_OFFSET(slot) (0x00001248 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_U_OFFSET(slot) (0x0000124c + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_V_OFFSET(slot) (0x00001250 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_LUMA_OFFSET(slot) (0x00001254 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_U_OFFSET(slot) (0x00001258 + (slot) * 0x00000060)
+#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_V_OFFSET(slot) (0x0000125c + (slot) * 0x00000060)
+
+typedef struct {
+ uint64_t SlotEnable : 1; /* 0 */
+ uint64_t DeNoise : 1; /* 1 */
+ uint64_t AdvancedDenoise : 1; /* 2 */
+ uint64_t CadenceDetect : 1; /* 3 */
+ uint64_t MotionMap : 1; /* 4 */
+ uint64_t MMapCombine : 1; /* 5 */
+ uint64_t IsEven : 1; /* 6 */
+ uint64_t ChromaEven : 1; /* 7 */
+ uint64_t CurrentFieldEnable : 1; /* 8 */
+ uint64_t PrevFieldEnable : 1; /* 9 */
+ uint64_t NextFieldEnable : 1; /* 10 */
+ uint64_t NextNrFieldEnable : 1; /* 11 */
+ uint64_t CurMotionFieldEnable : 1; /* 12 */
+ uint64_t PrevMotionFieldEnable : 1; /* 13 */
+ uint64_t PpMotionFieldEnable : 1; /* 14 */
+ uint64_t CombMotionFieldEnable : 1; /* 15 */
+ uint64_t FrameFormat : 4; /* 19..16 */
+ uint64_t FilterLengthY : 2; /* 21..20 */
+ uint64_t FilterLengthX : 2; /* 23..22 */
+ uint64_t Panoramic : 12; /* 35..24 */
+ uint64_t ChromaUpLengthY : 2; /* 37..36 */
+ uint64_t ChromaUpLengthX : 2; /* 39..38 */
+ uint64_t reserved1 : 18; /* 57..40 */
+ uint64_t DetailFltClamp : 6; /* 63..58 */
+ uint64_t FilterNoise : 10; /* 73..64 */
+ uint64_t FilterDetail : 10; /* 83..74 */
+ uint64_t ChromaNoise : 10; /* 93..84 */
+ uint64_t ChromaDetail : 10; /* 103..94 */
+ uint64_t DeinterlaceMode : 4; /* 107..104 */
+ uint64_t MotionAccumWeight : 3; /* 110..108 */
+ uint64_t NoiseIir : 11; /* 121..111 */
+ uint64_t LightLevel : 4; /* 125..122 */
+ uint64_t reserved4 : 2; /* 127..126 */
+ /* 128 */
+ uint64_t SoftClampLow : 10; /* 9..0 */
+ uint64_t SoftClampHigh : 10; /* 19..10 */
+ uint64_t reserved5 : 12; /* 31..20 */
+ uint64_t reserved6 : 2; /* 33..32 */
+ uint64_t PlanarAlpha : 8; /* 41..34 */
+ uint64_t ConstantAlpha : 1; /* 42 */
+ uint64_t StereoInterleave : 3; /* 45..43 */
+ uint64_t ClipEnabled : 1; /* 46 */
+ uint64_t ClearRectMask : 8; /* 54..47 */
+ uint64_t DegammaMode : 2; /* 56..55 */
+ uint64_t reserved7 : 1; /* 57 */
+ uint64_t DecompressEnable : 1; /* 58 */
+ uint64_t DecompressKind : 4; /* 62..59 */
+ uint64_t reserved9 : 1; /* 63 */
+ uint64_t DecompressCtbCount : 8; /* 71..64 */
+ uint64_t DecompressZbcColor : 32; /* 103..72 */
+ uint64_t reserved12 : 24; /* 127..104 */
+ /* 256 */
+ uint64_t SourceRectLeft : 30; /* 29..0 */
+ uint64_t reserved14 : 2; /* 31..30 */
+ uint64_t SourceRectRight : 30; /* 61..32 */
+ uint64_t reserved15 : 2; /* 63..62 */
+ uint64_t SourceRectTop : 30; /* 93..64 */
+ uint64_t reserved16 : 2; /* 95..94 */
+ uint64_t SourceRectBottom : 30; /* 125..96 */
+ uint64_t reserved17 : 2; /* 127..126 */
+ /* 384 */
+ uint64_t DestRectLeft : 14; /* 13..0 */
+ uint64_t reserved18 : 2; /* 15..14 */
+ uint64_t DestRectRight : 14; /* 29..16 */
+ uint64_t reserved19 : 2; /* 31..30 */
+ uint64_t DestRectTop : 14; /* 45..32 */
+ uint64_t reserved20 : 2; /* 47..46 */
+ uint64_t DestRectBottom : 14; /* 61..48 */
+ uint64_t reserved21 : 2; /* 63..62 */
+ uint64_t reserved22 : 32; /* 95..64 */
+ uint64_t reserved23 : 32; /* 127..96 */
+} SlotConfig;
+
+typedef struct {
+ uint64_t SlotPixelFormat : 7; /* 6..0 */
+ uint64_t SlotChromaLocHoriz : 2; /* 8..7 */
+ uint64_t SlotChromaLocVert : 2; /* 10..9 */
+ uint64_t SlotBlkKind : 4; /* 14..11 */
+ uint64_t SlotBlkHeight : 4; /* 18..15 */
+ uint64_t SlotCacheWidth : 3; /* 21..19 */
+ uint64_t reserved0 : 10; /* 31..22 */
+ uint64_t SlotSurfaceWidth : 14; /* 45..32 */
+ uint64_t SlotSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t SlotLumaWidth : 14; /* 77..64 */
+ uint64_t SlotLumaHeight : 14; /* 91..78 */
+ uint64_t reserved2 : 4; /* 95..92 */
+ uint64_t SlotChromaWidth : 14; /* 109..96 */
+ uint64_t SlotChromaHeight : 14; /* 123..110 */
+ uint64_t reserved3 : 4; /* 127..124 */
+} SlotSurfaceConfig;
+
+typedef struct {
+ uint64_t luma_coeff0 : 20; /* 19..0 */
+ uint64_t luma_coeff1 : 20; /* 39..20 */
+ uint64_t luma_coeff2 : 20; /* 59..40 */
+ uint64_t luma_r_shift : 4; /* 63..60 */
+ uint64_t luma_coeff3 : 20; /* 83..64 */
+ uint64_t LumaKeyLower : 10; /* 93..84 */
+ uint64_t LumaKeyUpper : 10; /* 103..94 */
+ uint64_t LumaKeyEnabled : 1; /* 104 */
+ uint64_t reserved0 : 2; /* 106..105 */
+ uint64_t reserved1 : 21; /* 127..107 */
+} LumaKeyStruct;
+
+typedef struct {
+ uint64_t matrix_coeff00 : 20; /* 19..0 */
+ uint64_t matrix_coeff10 : 20; /* 39..20 */
+ uint64_t matrix_coeff20 : 20; /* 59..40 */
+ uint64_t matrix_r_shift : 4; /* 63..60 */
+ uint64_t matrix_coeff01 : 20; /* 83..64 */
+ uint64_t matrix_coeff11 : 20; /* 103..84 */
+ uint64_t matrix_coeff21 : 20; /* 123..104 */
+ uint64_t reserved0 : 3; /* 126..124 */
+ uint64_t matrix_enable : 1; /* 127 */
+ /* 128 */
+ uint64_t matrix_coeff02 : 20; /* 19..0 */
+ uint64_t matrix_coeff12 : 20; /* 39..20 */
+ uint64_t matrix_coeff22 : 20; /* 59..40 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t matrix_coeff03 : 20; /* 83..64 */
+ uint64_t matrix_coeff13 : 20; /* 103..84 */
+ uint64_t matrix_coeff23 : 20; /* 123..104 */
+ uint64_t reserved2 : 4; /* 127..124 */
+} MatrixStruct;
+
+typedef struct {
+ uint64_t ClearRect0Left : 14; /* 13..0 */
+ uint64_t reserved0 : 2; /* 15..14 */
+ uint64_t ClearRect0Right : 14; /* 29..16 */
+ uint64_t reserved1 : 2; /* 31..30 */
+ uint64_t ClearRect0Top : 14; /* 45..32 */
+ uint64_t reserved2 : 2; /* 47..46 */
+ uint64_t ClearRect0Bottom : 14; /* 61..48 */
+ uint64_t reserved3 : 2; /* 63..62 */
+ uint64_t ClearRect1Left : 14; /* 77..64 */
+ uint64_t reserved4 : 2; /* 79..78 */
+ uint64_t ClearRect1Right : 14; /* 93..80 */
+ uint64_t reserved5 : 2; /* 95..94 */
+ uint64_t ClearRect1Top : 14; /* 109..96 */
+ uint64_t reserved6 : 2; /* 111..110 */
+ uint64_t ClearRect1Bottom : 14; /* 125..112 */
+ uint64_t reserved7 : 2; /* 127..126 */
+} ClearRectStruct;
+
+typedef struct {
+ uint64_t reserved0 : 2; /* 1..0 */
+ uint64_t AlphaK1 : 8; /* 9..2 */
+ uint64_t reserved1 : 6; /* 17..10 */
+ uint64_t AlphaK2 : 8; /* 25..18 */
+ uint64_t reserved2 : 6; /* 31..26 */
+ uint64_t SrcFactCMatchSelect : 3; /* 34..32 */
+ uint64_t reserved3 : 1; /* 35 */
+ uint64_t DstFactCMatchSelect : 3; /* 38..36 */
+ uint64_t reserved4 : 1; /* 39 */
+ uint64_t SrcFactAMatchSelect : 3; /* 42..40 */
+ uint64_t reserved5 : 1; /* 43 */
+ uint64_t DstFactAMatchSelect : 3; /* 46..44 */
+ uint64_t reserved6 : 1; /* 47 */
+ uint64_t reserved7 : 4; /* 51..48 */
+ uint64_t reserved8 : 4; /* 55..52 */
+ uint64_t reserved9 : 4; /* 59..56 */
+ uint64_t reserved10 : 4; /* 63..60 */
+ uint64_t reserved11 : 2; /* 65..64 */
+ uint64_t OverrideR : 10; /* 75..66 */
+ uint64_t OverrideG : 10; /* 85..76 */
+ uint64_t OverrideB : 10; /* 95..86 */
+ uint64_t reserved12 : 2; /* 97..96 */
+ uint64_t OverrideA : 8; /* 105..98 */
+ uint64_t reserved13 : 2; /* 107..106 */
+ uint64_t UseOverrideR : 1; /* 108 */
+ uint64_t UseOverrideG : 1; /* 109 */
+ uint64_t UseOverrideB : 1; /* 110 */
+ uint64_t UseOverrideA : 1; /* 111 */
+ uint64_t MaskR : 1; /* 112 */
+ uint64_t MaskG : 1; /* 113 */
+ uint64_t MaskB : 1; /* 114 */
+ uint64_t MaskA : 1; /* 115 */
+ uint64_t reserved14 : 12; /* 127..116 */
+} BlendingSlotStruct;
+
+typedef struct {
+ uint64_t AlphaFillMode : 3; /* 2..0 */
+ uint64_t AlphaFillSlot : 3; /* 5..3 */
+ uint64_t reserved0 : 2; /* 6..5 */
+ uint64_t BackgroundAlpha : 8; /* 15..7 */
+ uint64_t BackgroundR : 10; /* 25..16 */
+ uint64_t BackgroundG : 10; /* 35..26 */
+ uint64_t BackgroundB : 10; /* 45..36 */
+ uint64_t RegammaMode : 2; /* 47..46 */
+ uint64_t OutputFlipX : 1; /* 48 */
+ uint64_t OutputFlipY : 1; /* 49 */
+ uint64_t OutputTranspose : 1; /* 50 */
+ uint64_t reserved1 : 1; /* 51 */
+ uint64_t reserved2 : 12; /* 63..52 */
+ uint64_t TargetRectLeft : 14; /* 77..64 */
+ uint64_t reserved3 : 2; /* 79..78 */
+ uint64_t TargetRectRight : 14; /* 93..80 */
+ uint64_t reserved4 : 2; /* 95..94 */
+ uint64_t TargetRectTop : 14; /* 109..96 */
+ uint64_t reserved5 : 2; /* 111..110 */
+ uint64_t TargetRectBottom : 14; /* 125..112 */
+ uint64_t reserved6 : 2; /* 127..126 */
+} OutputConfig;
+
+typedef struct {
+ uint64_t OutPixelFormat : 7; /* 6..0 */
+ uint64_t OutChromaLocHoriz : 2; /* 8..7 */
+ uint64_t OutChromaLocVert : 2; /* 10..9 */
+ uint64_t OutBlkKind : 4; /* 14..11 */
+ uint64_t OutBlkHeight : 4; /* 18..15 */
+ uint64_t reserved0 : 3; /* 21..19 */
+ uint64_t reserved1 : 10; /* 31..22 */
+ uint64_t OutSurfaceWidth : 14; /* 45..32 */
+ uint64_t OutSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved2 : 4; /* 63..60 */
+ uint64_t OutLumaWidth : 14; /* 77..64 */
+ uint64_t OutLumaHeight : 14; /* 91..78 */
+ uint64_t reserved3 : 4; /* 95..92 */
+ uint64_t OutChromaWidth : 14; /* 109..96 */
+ uint64_t OutChromaHeight : 14; /* 123..110 */
+ uint64_t reserved4 : 4; /* 127..124 */
+} OutputSurfaceConfig;
+
+typedef struct {
+ uint64_t f00 : 10; /* 9..0 */
+ uint64_t f10 : 10; /* 19..10 */
+ uint64_t f20 : 10; /* 29..20 */
+ uint64_t reserved0 : 2; /* 31..30 */
+ uint64_t f01 : 10; /* 41..32 */
+ uint64_t f11 : 10; /* 51..42 */
+ uint64_t f21 : 10; /* 61..52 */
+ uint64_t reserved1 : 2; /* 63..62 */
+ uint64_t f02 : 10; /* 73..64 */
+ uint64_t f12 : 10; /* 83..74 */
+ uint64_t f22 : 10; /* 93..84 */
+ uint64_t reserved2 : 2; /* 95..94 */
+ uint64_t f03 : 10; /* 105..96 */
+ uint64_t f13 : 10; /* 115..106 */
+ uint64_t f23 : 10; /* 125..116 */
+ uint64_t reserved3 : 2; /* 127..126 */
+} FilterCoeffStruct;
+
+typedef struct {
+ uint64_t DownsampleHoriz : 11; /* 10..0 */
+ uint64_t reserved0 : 5; /* 15..11 */
+ uint64_t DownsampleVert : 11; /* 26..16 */
+ uint64_t reserved1 : 5; /* 31..27 */
+ uint64_t reserved2 : 32; /* 63..32 */
+ uint64_t reserved3 : 32; /* 95..64 */
+ uint64_t reserved4 : 32; /* 127..96 */
+} PipeConfig;
+
+typedef struct {
+ uint64_t OldCadence : 32; /* 31..0 */
+ uint64_t OldDiff : 32; /* 63..32 */
+ uint64_t OldWeave : 32; /* 95..64 */
+ uint64_t OlderWeave : 32; /* 127..96 */
+} SlotHistoryBuffer;
+
+typedef struct {
+ uint64_t crc0 : 32; /* 31..0 */
+ uint64_t crc1 : 32; /* 63..32 */
+ uint64_t crc2 : 32; /* 95..64 */
+ uint64_t crc3 : 32; /* 127..96 */
+} PartitionCrcStruct;
+
+typedef struct {
+ uint64_t crc0 : 32; /* 31..0 */
+ uint64_t crc1 : 32; /* 63..32 */
+} SlotCrcStruct;
+
+typedef struct {
+ uint64_t ErrorStatus : 32; /* 31..0 */
+ uint64_t CycleCount : 32; /* 63..32 */
+ uint64_t reserved0 : 32; /* 95..64 */
+ uint64_t reserved1 : 32; /* 127..96 */
+} StatusStruct;
+
+typedef struct {
+ SlotConfig slotConfig;
+ SlotSurfaceConfig slotSurfaceConfig;
+ LumaKeyStruct lumaKeyStruct;
+ MatrixStruct colorMatrixStruct;
+ MatrixStruct gamutMatrixStruct;
+ BlendingSlotStruct blendingSlotStruct;
+} SlotStruct;
+
+typedef struct {
+ FilterCoeffStruct filterCoeffStruct[520];
+} FilterStruct;
+
+typedef struct {
+ PipeConfig pipeConfig;
+ OutputConfig outputConfig;
+ OutputSurfaceConfig outputSurfaceConfig;
+ MatrixStruct outColorMatrixStruct;
+ ClearRectStruct clearRectStruct[4];
+ SlotStruct slotStruct[16];
+} ConfigStruct;
+
+typedef struct {
+ PartitionCrcStruct partitionCrcStruct[4];
+} InterfaceCrcStruct;
+
+typedef struct {
+ SlotCrcStruct slotCrcStruct[16];
+} InputCrcStruct;
+
+#endif
diff --git a/tests/tegra/vic42.c b/tests/tegra/vic42.c
new file mode 100644
index 0000000..068b712
--- /dev/null
+++ b/tests/tegra/vic42.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "private.h"
+#include "tegra.h"
+#include "vic.h"
+#include "vic42.h"
+
+struct vic42 {
+ struct vic base;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } config;
+
+ struct {
+ struct drm_tegra_mapping *map;
+ struct drm_tegra_bo *bo;
+ } filter;
+};
+
+static int vic42_fill(struct vic *v, struct vic_image *output,
+ unsigned int left, unsigned int top,
+ unsigned int right, unsigned int bottom,
+ unsigned int alpha, unsigned int red,
+ unsigned int green, unsigned int blue)
+{
+ struct vic42 *vic = container_of(v, struct vic42, base);
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = top;
+ c->outputConfig.TargetRectLeft = left;
+ c->outputConfig.TargetRectRight = right;
+ c->outputConfig.TargetRectBottom = bottom;
+ c->outputConfig.BackgroundAlpha = alpha;
+ c->outputConfig.BackgroundR = red;
+ c->outputConfig.BackgroundG = green;
+ c->outputConfig.BackgroundB = blue;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic42_blit(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic42 *vic = container_of(v, struct vic42, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 255;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 255;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic42_flip(struct vic *v, struct vic_image *output,
+ struct vic_image *input)
+{
+ struct vic42 *vic = container_of(v, struct vic42, base);
+ SlotSurfaceConfig *surface;
+ SlotConfig *slot;
+ ConfigStruct *c;
+ int err;
+
+ err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ memset(c, 0, sizeof(*c));
+
+ c->outputConfig.TargetRectTop = 0;
+ c->outputConfig.TargetRectLeft = 0;
+ c->outputConfig.TargetRectRight = output->width - 1;
+ c->outputConfig.TargetRectBottom = output->height - 1;
+ c->outputConfig.BackgroundAlpha = 255;
+ c->outputConfig.BackgroundR = 1023;
+ c->outputConfig.BackgroundG = 1023;
+ c->outputConfig.BackgroundB = 1023;
+ c->outputConfig.OutputFlipY = 1;
+
+ c->outputSurfaceConfig.OutPixelFormat = output->format;
+ c->outputSurfaceConfig.OutBlkKind = output->kind;
+ c->outputSurfaceConfig.OutBlkHeight = 0;
+ c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
+ c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
+ c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
+ c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+ c->outputSurfaceConfig.OutChromaWidth = 16383;
+ c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+ slot = &c->slotStruct[0].slotConfig;
+ slot->SlotEnable = 1;
+ slot->CurrentFieldEnable = 1;
+ slot->PlanarAlpha = 255;
+ slot->ConstantAlpha = 1;
+ slot->SourceRectLeft = 0 << 16;
+ slot->SourceRectRight = (input->width - 1) << 16;
+ slot->SourceRectTop = 0 << 16;
+ slot->SourceRectBottom = (input->height - 1) << 16;
+ slot->DestRectLeft = 0;
+ slot->DestRectRight = output->width - 1;
+ slot->DestRectTop = 0;
+ slot->DestRectBottom = output->height - 1;
+ slot->SoftClampHigh = 1023;
+
+ surface = &c->slotStruct[0].slotSurfaceConfig;
+ surface->SlotPixelFormat = input->format;
+ surface->SlotBlkKind = input->kind;
+ surface->SlotBlkHeight = 0; /* XXX */
+ surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
+ surface->SlotSurfaceWidth = input->width - 1;
+ surface->SlotSurfaceHeight = input->height - 1;
+ surface->SlotLumaWidth = input->stride - 1;
+ surface->SlotLumaHeight = input->height - 1;
+ surface->SlotChromaWidth = 16383;
+ surface->SlotChromaHeight = 16383;
+
+ drm_tegra_bo_unmap(vic->config.bo);
+
+ return 0;
+}
+
+static int vic42_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
+ uint32_t **ptrp, struct vic_image *output,
+ struct vic_image **inputs, unsigned int num_inputs)
+{
+ struct vic42 *vic = container_of(v, struct vic42, base);
+ unsigned int i;
+
+ if (num_inputs > 1)
+ return -EINVAL;
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET, vic->filter.map, 0, 0);
+ VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
+
+ for (i = 0; i < num_inputs; i++) {
+ uint32_t method = NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(0) + (i * 3) * 4;
+
+ VIC_PUSH_BUFFER(pushbuf, ptrp, method, inputs[i]->map, 0, 0);
+ }
+
+ VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
+
+ return 0;
+}
+
+static void vic42_free(struct vic *v)
+{
+ struct vic42 *vic = container_of(v, struct vic42, base);
+
+ drm_tegra_channel_unmap(vic->filter.map);
+ drm_tegra_bo_unref(vic->filter.bo);
+
+ drm_tegra_channel_unmap(vic->config.map);
+ drm_tegra_bo_unref(vic->config.bo);
+
+ drm_tegra_syncpoint_free(v->syncpt);
+
+ free(vic);
+}
+
+static const struct vic_ops vic42_ops = {
+ .fill = vic42_fill,
+ .blit = vic42_blit,
+ .flip = vic42_flip,
+ .execute = vic42_execute,
+ .free = vic42_free,
+};
+
+int vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
+ struct vic **vicp)
+{
+ struct vic42 *vic;
+ void *ptr;
+ int err;
+
+ vic = calloc(1, sizeof(*vic));
+ if (!vic)
+ return -ENOMEM;
+
+ vic->base.drm = drm;
+ vic->base.channel = channel;
+ vic->base.ops = &vic42_ops;
+ vic->base.version = 0x19;
+
+ err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate configuration structurer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->config.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map configuration structure: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
+ if (err < 0) {
+ fprintf(stderr, "failed to allocate filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ err = drm_tegra_bo_map(vic->filter.bo, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
+ return err;
+ }
+
+ memset(ptr, 0, 16384);
+ drm_tegra_bo_unmap(vic->filter.bo);
+
+ err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
+ &vic->filter.map);
+ if (err < 0) {
+ fprintf(stderr, "failed to map filter buffer: %s\n",
+ strerror(-err));
+ return err;
+ }
+
+ if (vicp)
+ *vicp = &vic->base;
+
+ return 0;
+}
diff --git a/tests/tegra/vic42.h b/tests/tegra/vic42.h
new file mode 100644
index 0000000..3ed5cdb
--- /dev/null
+++ b/tests/tegra/vic42.h
@@ -0,0 +1,597 @@
+/*
+ * Copyright © 2018 NVIDIA Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIC42_H
+#define VIC42_H
+
+#include <stdint.h>
+
+#define NVC5B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x00000200
+#define NVC5B6_VIDEO_COMPOSITOR_EXECUTE 0x00000300
+#define NVC5B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x00000704
+#define NVC5B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x00000708
+#define NVC5B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET 0x0000070c
+#define NVC5B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x00000714
+#define NVC5B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x00000720
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(slot) (0x00001200 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_U_OFFSET(slot) (0x00001204 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_V_OFFSET(slot) (0x00001208 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE1_LUMA_OFFSET(slot) (0x0000120c + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_U_OFFSET(slot) (0x00001210 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_V_OFFSET(slot) (0x00001214 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE2_LUMA_OFFSET(slot) (0x00001218 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_U_OFFSET(slot) (0x0000121c + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_V_OFFSET(slot) (0x00001220 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE3_LUMA_OFFSET(slot) (0x00001224 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_U_OFFSET(slot) (0x00001228 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_V_OFFSET(slot) (0x0000122c + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE4_LUMA_OFFSET(slot) (0x00001230 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_U_OFFSET(slot) (0x00001234 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_V_OFFSET(slot) (0x00001238 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE5_LUMA_OFFSET(slot) (0x0000123c + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_U_OFFSET(slot) (0x00001240 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_V_OFFSET(slot) (0x00001244 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE6_LUMA_OFFSET(slot) (0x00001248 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_U_OFFSET(slot) (0x0000124c + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_V_OFFSET(slot) (0x00001250 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE7_LUMA_OFFSET(slot) (0x00001254 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_U_OFFSET(slot) (0x00001258 + (slot) * 0x00000060)
+#define NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_V_OFFSET(slot) (0x0000125c + (slot) * 0x00000060)
+
+typedef struct {
+ uint64_t SlotEnable : 1; /* 0 */
+ uint64_t DeNoise : 1; /* 1 */
+ uint64_t AdvancedDenoise : 1; /* 2 */
+ uint64_t CadenceDetect : 1; /* 3 */
+ uint64_t MotionMap : 1; /* 4 */
+ uint64_t MMapCombine : 1; /* 5 */
+ uint64_t IsEven : 1; /* 6 */
+ uint64_t ChromaEven : 1; /* 7 */
+ uint64_t CurrentFieldEnable : 1; /* 8 */
+ uint64_t PrevFieldEnable : 1; /* 9 */
+ uint64_t NextFieldEnable : 1; /* 10 */
+ uint64_t NextNrFieldEnable : 1; /* 11 */
+ uint64_t CurMotionFieldEnable : 1; /* 12 */
+ uint64_t PrevMotionFieldEnable : 1; /* 13 */
+ uint64_t PpMotionFieldEnable : 1; /* 14 */
+ uint64_t CombMotionFieldEnable : 1; /* 15 */
+ uint64_t FrameFormat : 4; /* 19..16 */
+ uint64_t FilterLengthY : 2; /* 21..20 */
+ uint64_t FilterLengthX : 2; /* 23..22 */
+ uint64_t Panoramic : 12; /* 35..24 */
+ uint64_t ChromaUpLengthY : 2; /* 37..36 */
+ uint64_t ChromaUpLengthX : 2; /* 39..38 */
+ uint64_t reserved1 : 18; /* 57..40 */
+ uint64_t DetailFltClamp : 6; /* 63..58 */
+ uint64_t FilterNoise : 10; /* 73..64 */
+ uint64_t FilterDetail : 10; /* 83..74 */
+ uint64_t ChromaNoise : 10; /* 93..84 */
+ uint64_t ChromaDetail : 10; /* 103..94 */
+ uint64_t DeinterlaceMode : 4; /* 107..104 */
+ uint64_t MotionAccumWeight : 3; /* 110..108 */
+ uint64_t NoiseIir : 11; /* 121..111 */
+ uint64_t LightLevel : 4; /* 125..122 */
+ uint64_t reserved4 : 2; /* 127..126 */
+ /* 128 */
+ uint64_t SoftClampLow : 10; /* 9..0 */
+ uint64_t SoftClampHigh : 10; /* 19..10 */
+ uint64_t reserved5 : 12; /* 31..20 */
+ uint64_t reserved6 : 2; /* 33..32 */
+ uint64_t PlanarAlpha : 8; /* 41..34 */
+ uint64_t ConstantAlpha : 1; /* 42 */
+ uint64_t StereoInterleave : 3; /* 45..43 */
+ uint64_t ClipEnabled : 1; /* 46 */
+ uint64_t ClearRectMask : 8; /* 54..47 */
+ uint64_t DegammaMode : 2; /* 56..55 */
+ uint64_t reserved7 : 1; /* 57 */
+ uint64_t DecompressEnable : 1; /* 58 */
+ uint64_t DecompressKind : 4; /* 62..59 */
+ uint64_t reserved9 : 1; /* 63 */
+ uint64_t DecompressCtbCount : 8; /* 71..64 */
+ uint64_t DecompressZbcColor : 32; /* 103..72 */
+ uint64_t reserved12 : 24; /* 127..104 */
+ /* 256 */
+ uint64_t SourceRectLeft : 30; /* 29..0 */
+ uint64_t reserved14 : 2; /* 31..30 */
+ uint64_t SourceRectRight : 30; /* 61..32 */
+ uint64_t reserved15 : 2; /* 63..62 */
+ uint64_t SourceRectTop : 30; /* 93..64 */
+ uint64_t reserved16 : 2; /* 95..94 */
+ uint64_t SourceRectBottom : 30; /* 125..96 */
+ uint64_t reserved17 : 2; /* 127..126 */
+ /* 384 */
+ uint64_t DestRectLeft : 14; /* 13..0 */
+ uint64_t reserved18 : 2; /* 15..14 */
+ uint64_t DestRectRight : 14; /* 29..16 */
+ uint64_t reserved19 : 2; /* 31..30 */
+ uint64_t DestRectTop : 14; /* 45..32 */
+ uint64_t reserved20 : 2; /* 47..46 */
+ uint64_t DestRectBottom : 14; /* 61..48 */
+ uint64_t reserved21 : 2; /* 63..62 */
+ uint64_t B16ScalerEnable : 1; /* 64 */
+ uint64_t reserved22 : 31; /* 95..65 */
+ uint64_t reserved23 : 32; /* 127..96 */
+} SlotConfig;
+
+typedef struct {
+ uint64_t SlotPixelFormat : 7; /* 6..0 */
+ uint64_t SlotChromaLocHORIZ : 2; /* 8..7 */
+ uint64_t SlotChromaLocVert : 2; /* 10..9 */
+ uint64_t SlotBlkKind : 4; /* 14..11 */
+ uint64_t SlotBlkHeight : 4; /* 18..15 */
+ uint64_t SlotCacheWidth : 3; /* 21..19 */
+ uint64_t reserved0 : 10; /* 31..22 */
+ uint64_t SlotSurfaceWidth : 14; /* 45..32 */
+ uint64_t SlotSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t SlotLumaWidth : 14; /* 77..64 */
+ uint64_t SlotLumaHeight : 14; /* 91..78 */
+ uint64_t reserved2 : 4; /* 95..92 */
+ uint64_t SlotChromaWidth : 14; /* 109..96 */
+ uint64_t SlotChromaHeight : 14; /* 123..110 */
+ uint64_t reserved3 : 4; /* 127..124 */
+} SlotSurfaceConfig;
+
+typedef struct {
+ uint64_t luma_coeff0 : 20; /* 19..0 */
+ uint64_t luma_coeff1 : 20; /* 39..20 */
+ uint64_t luma_coeff2 : 20; /* 59..40 */
+ uint64_t luma_r_shift : 4; /* 63..60 */
+ uint64_t luma_coeff3 : 20; /* 83..64 */
+ uint64_t LumaKeyLower : 10; /* 93..84 */
+ uint64_t LumaKeyUpper : 10; /* 103..94 */
+ uint64_t LumaKeyEnabled : 1; /* 104 */
+ uint64_t reserved0 : 2; /* 106..105 */
+ uint64_t reserved1 : 21; /* 127..107 */
+} LumaKeyStruct;
+
+typedef struct {
+ uint64_t matrix_coeff00 : 20; /* 19..0 */
+ uint64_t matrix_coeff10 : 20; /* 39..20 */
+ uint64_t matrix_coeff20 : 20; /* 59..40 */
+ uint64_t matrix_r_shift : 4; /* 63..60 */
+ uint64_t matrix_coeff01 : 20; /* 83..64 */
+ uint64_t matrix_coeff11 : 20; /* 103..84 */
+ uint64_t matrix_coeff21 : 20; /* 123..104 */
+ uint64_t reserved0 : 3; /* 126..124 */
+ uint64_t matrix_enable : 1; /* 127 */
+ /* 128 */
+ uint64_t matrix_coeff02 : 20; /* 19..0 */
+ uint64_t matrix_coeff12 : 20; /* 39..20 */
+ uint64_t matrix_coeff22 : 20; /* 59..40 */
+ uint64_t reserved1 : 4; /* 63..60 */
+ uint64_t matrix_coeff03 : 20; /* 83..64 */
+ uint64_t matrix_coeff13 : 20; /* 103..84 */
+ uint64_t matrix_coeff23 : 20; /* 123..104 */
+ uint64_t reserved2 : 4; /* 127..124 */
+} MatrixStruct;
+
+typedef struct {
+ uint64_t ClearRect0Left : 14; /* 13..0 */
+ uint64_t reserved0 : 2; /* 15..14 */
+ uint64_t ClearRect0Right : 14; /* 29..16 */
+ uint64_t reserved1 : 2; /* 31..30 */
+ uint64_t ClearRect0Top : 14; /* 45..32 */
+ uint64_t reserved2 : 2; /* 47..46 */
+ uint64_t ClearRect0Bottom : 14; /* 61..48 */
+ uint64_t reserved3 : 2; /* 63..62 */
+ uint64_t ClearRect1Left : 14; /* 77..64 */
+ uint64_t reserved4 : 2; /* 79..78 */
+ uint64_t ClearRect1Right : 14; /* 93..80 */
+ uint64_t reserved5 : 2; /* 95..94 */
+ uint64_t ClearRect1Top : 14; /* 109..96 */
+ uint64_t reserved6 : 2; /* 111..110 */
+ uint64_t ClearRect1Bottom : 14; /* 125..112 */
+ uint64_t reserved7 : 2; /* 127..126 */
+} ClearRectStruct;
+
+typedef struct {
+ uint64_t reserved0 : 2; /* 1..0 */
+ uint64_t AlphaK1 : 8; /* 9..2 */
+ uint64_t reserved1 : 6; /* 17..10 */
+ uint64_t AlphaK2 : 8; /* 25..18 */
+ uint64_t reserved2 : 6; /* 31..26 */
+ uint64_t SrcFactCMatchSelect : 3; /* 34..32 */
+ uint64_t reserved3 : 1; /* 35 */
+ uint64_t DstFactCMatchSelect : 3; /* 38..36 */
+ uint64_t reserved4 : 1; /* 39 */
+ uint64_t SrcFactAMatchSelect : 3; /* 42..40 */
+ uint64_t reserved5 : 1; /* 43 */
+ uint64_t DstFactAMatchSelect : 3; /* 46..44 */
+ uint64_t reserved6 : 1; /* 47 */
+ uint64_t reserved7 : 4; /* 51..48 */
+ uint64_t reserved8 : 4; /* 55..52 */
+ uint64_t reserved9 : 4; /* 59..56 */
+ uint64_t reserved10 : 4; /* 63..60 */
+ uint64_t reserved11 : 2; /* 65..64 */
+ uint64_t OverrideR : 10; /* 75..66 */
+ uint64_t OverrideG : 10; /* 85..76 */
+ uint64_t OverrideB : 10; /* 95..86 */
+ uint64_t reserved12 : 2; /* 97..96 */
+ uint64_t OverrideA : 8; /* 105..98 */
+ uint64_t reserved13 : 2; /* 107..106 */
+ uint64_t UseOverrideR : 1; /* 108 */
+ uint64_t UseOverrideG : 1; /* 109 */
+ uint64_t UseOverrideB : 1; /* 110 */
+ uint64_t UseOverrideA : 1; /* 111 */
+ uint64_t MaskR : 1; /* 112 */
+ uint64_t MaskG : 1; /* 113 */
+ uint64_t MaskB : 1; /* 114 */
+ uint64_t MaskA : 1; /* 115 */
+ uint64_t reserved14 : 12; /* 127..116 */
+} BlendingSlotStruct;
+
+typedef struct {
+ uint64_t AlphaFillMode : 3; /* 2..0 */
+ uint64_t AlphaFillSlot : 3; /* 5..3 */
+ uint64_t reserved0 : 2; /* 6..5 */
+ uint64_t BackgroundAlpha : 8; /* 15..7 */
+ uint64_t BackgroundR : 10; /* 25..16 */
+ uint64_t BackgroundG : 10; /* 35..26 */
+ uint64_t BackgroundB : 10; /* 45..36 */
+ uint64_t RegammaMode : 2; /* 47..46 */
+ uint64_t OutputFlipX : 1; /* 48 */
+ uint64_t OutputFlipY : 1; /* 49 */
+ uint64_t OutputTranspose : 1; /* 50 */
+ uint64_t reserved1 : 1; /* 51 */
+ uint64_t reserved2 : 12; /* 63..52 */
+ uint64_t TargetRectLeft : 14; /* 77..64 */
+ uint64_t reserved3 : 2; /* 79..78 */
+ uint64_t TargetRectRight : 14; /* 93..80 */
+ uint64_t reserved4 : 2; /* 95..94 */
+ uint64_t TargetRectTop : 14; /* 109..96 */
+ uint64_t reserved5 : 2; /* 111..110 */
+ uint64_t TargetRectBottom : 14; /* 125..112 */
+ uint64_t reserved6 : 2; /* 127..126 */
+} OutputConfig;
+
+typedef struct {
+ uint64_t OutPixelFormat : 7; /* 6..0 */
+ uint64_t OutChromaLocHoriz : 2; /* 8..7 */
+ uint64_t OutChromaLocVert : 2; /* 10..9 */
+ uint64_t OutBlkKind : 4; /* 14..11 */
+ uint64_t OutBlkHeight : 4; /* 18..15 */
+ uint64_t reserved0 : 3; /* 21..19 */
+ uint64_t reserved1 : 10; /* 31..22 */
+ uint64_t OutSurfaceWidth : 14; /* 45..32 */
+ uint64_t OutSurfaceHeight : 14; /* 59..46 */
+ uint64_t reserved2 : 4; /* 63..60 */
+ uint64_t OutLumaWidth : 14; /* 77..64 */
+ uint64_t OutLumaHeight : 14; /* 91..78 */
+ uint64_t reserved3 : 4; /* 95..92 */
+ uint64_t OutChromaWidth : 14; /* 109..96 */
+ uint64_t OutChromaHeight : 14; /* 123..110 */
+ uint64_t reserved4 : 4; /* 127..124 */
+} OutputSurfaceConfig;
+
+typedef struct {
+ uint64_t f00 : 10; /* 9..0 */
+ uint64_t f10 : 10; /* 19..10 */
+ uint64_t f20 : 10; /* 29..20 */
+ uint64_t reserved0 : 2; /* 31..30 */
+ uint64_t f01 : 10; /* 41..32 */
+ uint64_t f11 : 10; /* 51..42 */
+ uint64_t f21 : 10; /* 61..52 */
+ uint64_t reserved1 : 2; /* 63..62 */
+ uint64_t f02 : 10; /* 73..64 */
+ uint64_t f12 : 10; /* 83..74 */
+ uint64_t f22 : 10; /* 93..84 */
+ uint64_t reserved2 : 2; /* 95..94 */
+ uint64_t f03 : 10; /* 105..96 */
+ uint64_t f13 : 10; /* 115..106 */
+ uint64_t f23 : 10; /* 125..116 */
+ uint64_t reserved3 : 2; /* 127..126 */
+} FilterCoeffStruct;
+
+typedef struct {
+ uint64_t DownsampleHoriz : 11; /* 10..0 */
+ uint64_t reserved0 : 5; /* 15..11 */
+ uint64_t DownsampleVert : 11; /* 26..16 */
+ uint64_t reserved1 : 5; /* 31..27 */
+ uint64_t reserved2 : 32; /* 63..32 */
+ uint64_t reserved3 : 32; /* 95..64 */
+ uint64_t reserved4 : 32; /* 127..96 */
+} PipeConfig;
+
+typedef struct {
+ uint64_t OldCadence : 32; /* 31..0 */
+ uint64_t OldDiff : 32; /* 63..32 */
+ uint64_t OldWeave : 32; /* 95..64 */
+ uint64_t OlderWeave : 32; /* 127..96 */
+} SlotHistoryBuffer;
+
+typedef struct {
+ uint64_t crc0 : 32; /* 31..0 */
+ uint64_t crc1 : 32; /* 63..32 */
+ uint64_t crc2 : 32; /* 95..64 */
+ uint64_t crc3 : 32; /* 127..96 */
+} PartitionCrcStruct;
+
+typedef struct {
+ uint64_t crc0 : 32; /* 31..0 */
+ uint64_t crc1 : 32; /* 63..32 */
+} SlotCrcStruct;
+
+typedef struct {
+ uint64_t ErrorStatus : 32; /* 31..0 */
+ uint64_t CycleCount : 32; /* 63..32 */
+ uint64_t reserved0 : 32; /* 95..64 */
+ uint64_t reserved1 : 32; /* 127..96 */
+} StatusStruct;
+
+typedef struct {
+ uint64_t coeff_0 : 10; /* 9..0 */
+ uint64_t reserved0 : 6; /* 15..10 */
+ uint64_t coeff_1 : 10; /* 25..16 */
+ uint64_t reserved1 : 6; /* 31..26 */
+ uint64_t coeff_2 : 10; /* 41..32 */
+ uint64_t reserved2 : 6; /* 47..42 */
+ uint64_t coeff_3 : 10; /* 57..48 */
+ uint64_t reserved3 : 6; /* 63..58 */
+} CoeffPhaseParamStruct;
+
+typedef struct {
+ uint64_t GeoTranEn : 1; /* 0 */
+ uint64_t GeoTranMode : 2; /* 2..1 */
+ uint64_t IPTMode : 1; /* 3 */
+ uint64_t PixelFilterType : 2; /* 5..4 */
+ uint64_t PixelFormat : 7; /* 12..6 */
+ uint64_t CacheWidth : 3; /* 15..13 */
+ uint64_t SrcBlkKind : 4; /* 19..16 */
+ uint64_t SrcBlkHeight : 4; /* 23..20 */
+ uint64_t DestBlkKind : 4; /* 27..24 */
+ uint64_t DestBlkHeight : 4; /* 31..28 */
+ uint64_t MskBitMapEn : 1; /* 32 */
+ uint64_t MaskedPixelFillMode : 1; /* 33 */
+ uint64_t XSobelMode : 2; /* 35..34 */
+ uint64_t SubFrameEn : 1; /* 36 */
+ uint64_t reserved0 : 3; /* 39..37 */
+ uint64_t XSobelBlkKind : 4; /* 43..40 */
+ uint64_t XSobelBlkHeight : 4; /* 47..44 */
+ uint64_t XSobelDSBlkKind : 4; /* 51..48 */
+ uint64_t XSobelDSBlkHeight : 4; /* 55..52 */
+ uint64_t reserved1 : 8; /* 63..56 */
+ uint64_t NonFixedPatchEn : 1; /* 64 */
+ uint64_t HorRegionNum : 2; /* 66..65 */
+ uint64_t VerRegionNum : 2; /* 68..67 */
+ uint64_t reserved2 : 3; /* 71..69 */
+ uint64_t log2HorSpace_0 : 3; /* 74..72 */
+ uint64_t log2VerSpace_0 : 3; /* 77..75 */
+ uint64_t log2HorSpace_1 : 3; /* 80..78 */
+ uint64_t log2VerSpace_1 : 3; /* 83..81 */
+ uint64_t log2HorSpace_2 : 3; /* 86..84 */
+ uint64_t log2VerSpace_2 : 3; /* 89..87 */
+ uint64_t log2HorSpace_3 : 3; /* 92..90 */
+ uint64_t log2VerSpace_3 : 3; /* 95..93 */
+ uint64_t horRegionWidth_0 : 14; /* 109..96 */
+ uint64_t reserved3 : 2; /* 111..110 */
+ uint64_t horRegionWidth_1 : 14; /* 125..112 */
+ uint64_t reserved4 : 2; /* 127..126 */
+ uint64_t horRegionWidth_2 : 14; /* 141..128 */
+ uint64_t reserved5 : 2; /* 143..142 */
+ uint64_t horRegionWidth_3 : 14; /* 157..144 */
+ uint64_t reserved6 : 2; /* 159..158 */
+ uint64_t verRegionHeight_0 : 14; /* 173..160 */
+ uint64_t reserved7 : 2; /* 175..174 */
+ uint64_t verRegionHeight_1 : 14; /* 189..176 */
+ uint64_t reserved8 : 2; /* 191..190 */
+ uint64_t verRegionHeight_2 : 14; /* 205..192 */
+ uint64_t reserved9 : 2; /* 207..206 */
+ uint64_t verRegionHeight_3 : 14; /* 221..208 */
+ uint64_t reserved10 : 2; /* 223..222 */
+ uint64_t IPT_M11 : 32; /* 255..224 */
+ uint64_t IPT_M12 : 32; /* 287..256 */
+ uint64_t IPT_M13 : 32; /* 319..288 */
+ uint64_t IPT_M21 : 32; /* 351..320 */
+ uint64_t IPT_M22 : 32; /* 383..352 */
+ uint64_t IPT_M23 : 32; /* 415..384 */
+ uint64_t IPT_M31 : 32; /* 447..416 */
+ uint64_t IPT_M32 : 32; /* 479..448 */
+ uint64_t IPT_M33 : 32; /* 511..480 */
+ uint64_t SourceRectLeft : 14; /* 525..512 */
+ uint64_t reserved11 : 2; /* 527..526 */
+ uint64_t SourceRectRight : 14; /* 541..528 */
+ uint64_t reserved12 : 2; /* 543..542 */
+ uint64_t SourceRectTop : 14; /* 557..544 */
+ uint64_t reserved13 : 2; /* 559..558 */
+ uint64_t SourceRectBottom : 14; /* 573..560 */
+ uint64_t reserved14; /* 575..574 */
+ uint64_t SrcImgWidth : 14; /* 589..576 */
+ uint64_t reserved15 : 2; /* 591..590 */
+ uint64_t SrcImgHeight : 14; /* 605..592 */
+ uint64_t reserved16 : 2; /* 607..606 */
+ uint64_t SrcSfcLumaWidth : 14; /* 621..608 */
+ uint64_t reserved17 : 2; /* 623..622 */
+ uint64_t SrcSfcLumaHeight : 14; /* 637..624 */
+ uint64_t reserved18 : 2; /* 639..638 */
+ uint64_t SrcSfcChromaWidth : 14; /* 653..640 */
+ uint64_t reserved19 : 2; /* 655..654 */
+ uint64_t SrcSfcChromaHeight : 14; /* 669..656 */
+ uint64_t reserved20 : 2; /* 671..670 */
+ uint64_t DestRectLeft : 14; /* 685..672 */
+ uint64_t reserved21 : 2; /* 687..686 */
+ uint64_t DestRectRight : 14; /* 701..688 */
+ uint64_t reserved22 : 2; /* 703..702 */
+ uint64_t DestRectTop : 14; /* 717..704 */
+ uint64_t reserved23 : 2; /* 719..718 */
+ uint64_t DestRectBottom : 14; /* 733..720 */
+ uint64_t reserved24 : 2; /* 735..734 */
+ uint64_t SubFrameRectTop : 14; /* 749..736 */
+ uint64_t reserved25 : 2; /* 751..750 */
+ uint64_t SubFrameRectBottom : 14; /* 765..752 */
+ uint64_t reserved26 : 2; /* 767..766 */
+ uint64_t DestSfcLumaWidth : 14; /* 781..768 */
+ uint64_t reserved27 : 2; /* 783..782 */
+ uint64_t DestSfcLumaHeight : 14; /* 797..784 */
+ uint64_t reserved28 : 2; /* 799..798 */
+ uint64_t DestSfcChromaWidth : 14; /* 813..800 */
+ uint64_t reserved29 : 2; /* 815..814 */
+ uint64_t DestSfcChromaHeight : 14; /* 829..816 */
+ uint64_t reserved30 : 2; /* 831..830 */
+ uint64_t SparseWarpMapWidth : 14; /* 845..832 */
+ uint64_t reserved31 : 2; /* 847..846 */
+ uint64_t SparseWarpMapHeight : 14; /* 861..848 */
+ uint64_t reserved32 : 2; /* 863..862 */
+ uint64_t SparseWarpMapStride : 14; /* 877..864 */
+ uint64_t reserved33 : 2; /* 879..878 */
+ uint64_t MaskBitMapWidth : 14; /* 893..880 */
+ uint64_t reserved34 : 2; /* 895..894 */
+ uint64_t MaskBitMapHeight : 14; /* 909..896 */
+ uint64_t reserved35 : 2; /* 911..910 */
+ uint64_t MaskBitMapStride : 14; /* 925..912 */
+ uint64_t reserved36 : 2; /* 927..926 */
+ uint64_t XSobelWidth : 14; /* 941..928 */
+ uint64_t reserved37 : 2; /* 943..942 */
+ uint64_t XSobelHeight : 14; /* 957..944 */
+ uint64_t reserved38 : 2; /* 959..958 */
+ uint64_t XSobelStride : 14; /* 973..960 */
+ uint64_t reserved39 : 2; /* 975..974 */
+ uint64_t DSStride : 14; /* 989..976 */
+ uint64_t reserved40 : 2; /* 991..990 */
+ uint64_t XSobelTopOffset : 32; /* 1023..992 */
+ uint64_t reserved41 : 32; /* 1055..1024 */
+ uint64_t maskY : 16; /* 1071..1056 */
+ uint64_t maskU : 16; /* 1087..1072 */
+ uint64_t maskV : 16; /* 1103..1088 */
+ uint64_t reserved42 : 16; /* 1119..1104 */
+} GeoTranConfigParamStruct;
+
+typedef struct {
+ uint64_t TNR3En : 1; /* 0 */
+ uint64_t BetaBlendingEn : 1; /* 1 */
+ uint64_t AlphaBlendingEn : 1; /* 2 */
+ uint64_t AlphaSmoothEn : 1; /* 3 */
+ uint64_t TempAlphaRestrictEn : 1; /* 4 */
+ uint64_t AlphaClipEn : 1; /* 5 */
+ uint64_t BFRangeEn : 1; /* 6 */
+ uint64_t BFDomainEn : 1; /* 7 */
+ uint64_t BFRangeLumaShift : 4; /* 11..8 */
+ uint64_t BFRangeChromaShift : 4; /* 15..12 */
+ uint64_t SADMultiplier : 6; /* 21..16 */
+ uint64_t reserved1 : 2; /* 23..22 */
+ uint64_t SADWeightLuma : 6; /* 29..24 */
+ uint64_t reserved2 : 2; /* 31..30 */
+ uint64_t TempAlphaRestrictIncCap : 11; /* 42..32 */
+ uint64_t reserved3 : 5; /* 47..43 */
+ uint64_t AlphaScaleIIR : 11; /* 58..48 */
+ uint64_t reserved4 : 5; /* 63..59 */
+ uint64_t AlphaClipMaxLuma : 11; /* 74..64 */
+ uint64_t reserved5 : 5; /* 79..75 */
+ uint64_t AlphaClipMinLuma : 11; /* 90..80 */
+ uint64_t reserved6 : 5; /* 95..91 */
+ uint64_t AlphaClipMaxChroma : 11; /* 106..96 */
+ uint64_t reserved7 : 5; /* 111..107 */
+ uint64_t AlphaClipMinChroma : 11; /* 122..112 */
+ uint64_t reserved8 : 5; /* 127..123 */
+ uint64_t BetaCalcMaxBeta : 11; /* 138..128 */
+ uint64_t reserved9 : 5; /* 143..139 */
+ uint64_t BetaCalcMinBeta : 11; /* 154..144 */
+ uint64_t reserved10 : 5; /* 159..155 */
+ uint64_t BetaCalcBetaX1 : 11; /* 170..160 */
+ uint64_t reserved11 : 5; /* 175..171 */
+ uint64_t BetaCalcBetaX2 : 11; /* 186..176 */
+ uint64_t reserved12 : 5; /* 191..187 */
+ uint64_t BetaCalcStepBeta : 11; /* 202..192 */
+ uint64_t reserved13 : 5; /* 207..203 */
+ uint64_t reserved14 : 16; /* 223..208 */
+ uint64_t BFDomainLumaCoeffC00 : 7; /* 230..224 */
+ uint64_t reserved15 : 1; /* 231 */
+ uint64_t BFDomainLumaCoeffC01 : 7; /* 238..232 */
+ uint64_t reserved16 : 1; /* 239 */
+ uint64_t BFDomainLumaCoeffC02 : 7; /* 246..240 */
+ uint64_t reserved17 : 1; /* 247 */
+ uint64_t BFDomainLumaCoeffC11 : 7; /* 254..248 */
+ uint64_t reserved18 : 1; /* 255 */
+ uint64_t BFDomainLumaCoeffC12 : 7; /* 262..256 */
+ uint64_t reserved19 : 1; /* 263 */
+ uint64_t BFDomainLumaCoeffC22 : 7; /* 270..264 */
+ uint64_t reserved20 : 1; /* 271 */
+ uint64_t reserved21 : 16; /* 287..272 */
+ uint64_t BFDomainChromaCoeffC00 : 7; /* 294..288 */
+ uint64_t reserved22 : 1; /* 295 */
+ uint64_t BFDomainChromaCoeffC01 : 7; /* 302..296 */
+ uint64_t reserved23 : 1; /* 303 */
+ uint64_t BFDomainChromaCoeffC02 : 7; /* 310..304 */
+ uint64_t reserved24 : 1; /* 311 */
+ uint64_t BFDomainChromaCoeffC11 : 7; /* 318..312 */
+ uint64_t reserved25 : 1; /* 319 */
+ uint64_t BFDomainChromaCoeffC12 : 7; /* 326..320 */
+ uint64_t reserved26 : 1; /* 327 */
+ uint64_t BFDomainChromaCoeffC22 : 7; /* 334..328 */
+ uint64_t reserved27 : 1; /* 335 */
+ uint64_t reserved28 : 16; /* 351..336 */
+ uint64_t LeftBufSize : 32; /* 383..352 */
+ uint64_t TopBufSize : 32; /* 415..384 */
+ uint64_t AlphaSufStride : 14; /* 429..416 */
+ uint64_t reserved29 : 18; /* 447..430 */
+} TNR3ConfigParamStruct;
+
+typedef struct {
+ uint64_t item0 : 7; /* 6..0 */
+ uint64_t reserved0 : 9; /* 15..7 */
+ uint64_t item1 : 7; /* 22..16 */
+ uint64_t reserved1 : 9; /* 31..23 */
+ uint64_t item2 : 7; /* 38..32 */
+ uint64_t reserved2 : 9; /* 47..39 */
+ uint64_t item3 : 7; /* 54..48 */
+ uint64_t reserved3 : 9; /* 63..55 */
+} BFRangeTableItems;
+
+typedef struct {
+ SlotConfig slotConfig;
+ SlotSurfaceConfig slotSurfaceConfig;
+ LumaKeyStruct lumaKeyStruct;
+ MatrixStruct colorMatrixStruct;
+ MatrixStruct gamutMatrixStruct;
+ BlendingSlotStruct blendingSlotStruct;
+} SlotStruct;
+
+typedef struct {
+ FilterCoeffStruct filterCoeffStruct[520];
+} FilterStruct;
+
+typedef struct {
+ PipeConfig pipeConfig;
+ OutputConfig outputConfig;
+ OutputSurfaceConfig outputSurfaceConfig;
+ MatrixStruct outColorMatrixStruct;
+ ClearRectStruct clearRectStruct[4];
+ SlotStruct slotStruct[16];
+} ConfigStruct;
+
+typedef struct {
+ PartitionCrcStruct partitionCrcStruct[2];
+} InterfaceCrcStruct;
+
+typedef struct {
+ SlotCrcStruct slotCrcStruct[16];
+} InputCrcStruct;
+
+typedef struct {
+ GeoTranConfigParamStruct paramConfig;
+ CoeffPhaseParamStruct FilterCoeff[17];
+ TNR3ConfigParamStruct tnr3Config;
+ BFRangeTableItems BFRangeTableLuma[16];
+ BFRangeTableItems BFRangeTableChroma[16];
+} GeoTranConfigStruct;
+
+#endif
diff --git a/tests/ttmtest/AUTHORS b/tests/ttmtest/AUTHORS
new file mode 100644
index 0000000..fa4a089
--- /dev/null
+++ b/tests/ttmtest/AUTHORS
@@ -0,0 +1 @@
+Thomas Hellström <thomas-at-tungstengraphics.com> and others.
diff --git a/tests/ttmtest/ChangeLog b/tests/ttmtest/ChangeLog
new file mode 100644
index 0000000..4588c8d
--- /dev/null
+++ b/tests/ttmtest/ChangeLog
@@ -0,0 +1,23 @@
+2006-01-24 Thomas Hellström <thomas-at-tungstengraphics.com>
+
+ * configure.ac:
+ * src/ttmtest.c:
+
+ Fixed include path.
+
+2006-01-24 Thomas Hellström <thomas-at-tungstengraphics.com>
+
+ * AUTHORS:
+ * Makefile.am:
+ * configure.ac:
+ * reconf:
+ * src/Makefile.am:
+ * src/ttmtest.c: (fastrdtsc), (time_diff), (releaseContext),
+ (testAGP), (main):
+ * src/xf86dri.c: (uniDRIDestroyContext), (uniDRICreateDrawable),
+ (uniDRIDestroyDrawable), (uniDRIGetDrawableInfo):
+ * src/xf86dri.h:
+ * src/xf86dristr.h:
+
+ Initial import of the ttmtest utility.
+ \ No newline at end of file
diff --git a/tests/ttmtest/Makefile.am b/tests/ttmtest/Makefile.am
new file mode 100644
index 0000000..af437a6
--- /dev/null
+++ b/tests/ttmtest/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/tests/ttmtest/NEWS b/tests/ttmtest/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/ttmtest/NEWS
diff --git a/tests/ttmtest/README b/tests/ttmtest/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/ttmtest/README
diff --git a/tests/ttmtest/configure.ac b/tests/ttmtest/configure.ac
new file mode 100644
index 0000000..c41e91a
--- /dev/null
+++ b/tests/ttmtest/configure.ac
@@ -0,0 +1,33 @@
+AC_INIT
+AC_PROG_CC
+AC_PATH_X
+if test "x$no_x" != "xyes"; then
+ savecpp="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$x_includes"
+ AC_CHECK_HEADER($x_includes/X11/Xlib.h,,\
+ [AC_MSG_ERROR(Could not find X installation.)])
+ CPPFLAGS="$savecpp"
+ MDRIINC="-I$x_includes"
+ LIBS="-L$x_libraries $LIBS"
+else
+ AC_MSG_ERROR(Could not find X installation. Aborting.)
+fi
+AC_ARG_WITH(libdrm,
+ AC_HELP_STRING([--with-libdrm=DIR],
+ [Installation prefix of libdrm [[default=/usr]]]),
+ [libdrmpref="$withval"],
+ [libdrmpref="/usr"])
+savecpp="$CPPFLAGS"
+MDRIINC="-I$libdrmpref/include -I$libdrmpref/include/drm -I$x_includes"
+CPPFLAGS="$CPPFLAGS $MDRIINC"
+AC_CHECK_HEADER(xf86drm.h,,\
+ [AC_MSG_ERROR(Could not find libdrm installation. Use --with-libdrm=<libdrm_installation_prefix>)])
+AC_CHECK_HEADER(drm.h,,\
+ [AC_MSG_ERROR(Could not find libdrm installation. Use --with-libdrm=<libdrm_installation_prefix>)])
+CPPFLAGS="$savecpp"
+LIBS="-L$libdrmpref/lib64 -L$libdrmpref/lib $LIBS"
+AC_SUBST(MDRIINC)
+AC_SYS_LARGEFILE
+AM_INIT_AUTOMAKE(minidri,0.1.0)
+AM_CONFIG_HEADER(config.h)
+AC_OUTPUT([Makefile src/Makefile])
diff --git a/tests/ttmtest/reconf b/tests/ttmtest/reconf
new file mode 100755
index 0000000..e64d00a
--- /dev/null
+++ b/tests/ttmtest/reconf
@@ -0,0 +1,2 @@
+#!/bin/sh
+autoreconf -v --install || exit 1 \ No newline at end of file
diff --git a/tests/ttmtest/src/Makefile.am b/tests/ttmtest/src/Makefile.am
new file mode 100644
index 0000000..b7ee829
--- /dev/null
+++ b/tests/ttmtest/src/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = @MDRIINC@
+bin_PROGRAMS = ttmtest
+ttmtest_SOURCES = \
+ ttmtest.c \
+ xf86dri.c \
+ xf86dri.h \
+ xf86dristr.h
+ttmtest_LDADD = -ldrm -lXext -lX11
diff --git a/tests/ttmtest/src/ttmtest.c b/tests/ttmtest/src/ttmtest.c
new file mode 100644
index 0000000..36df242
--- /dev/null
+++ b/tests/ttmtest/src/ttmtest.c
@@ -0,0 +1,430 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdint.h>
+#include <drm/drm.h>
+#include "xf86dri.h"
+#include "xf86drm.h"
+#include "stdio.h"
+#include "sys/types.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "sys/mman.h"
+
+typedef struct
+{
+ enum
+ {
+ haveNothing,
+ haveDisplay,
+ haveConnection,
+ haveDriverName,
+ haveDeviceInfo,
+ haveDRM,
+ haveContext
+ }
+ state;
+
+ Display *display;
+ int screen;
+ drm_handle_t sAreaOffset;
+ char *curBusID;
+ char *driverName;
+ int drmFD;
+ XVisualInfo visualInfo;
+ XID id;
+ drm_context_t hwContext;
+ void *driPriv;
+ int driPrivSize;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ drm_handle_t fbHandle;
+ int ddxDriverMajor;
+ int ddxDriverMinor;
+ int ddxDriverPatch;
+} TinyDRIContext;
+
+#ifndef __x86_64__
+static unsigned
+fastrdtsc(void)
+{
+ unsigned eax;
+ __asm__ volatile ("\t"
+ "pushl %%ebx\n\t"
+ "cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
+ :"0"(0)
+ :"ecx", "edx", "cc");
+
+ return eax;
+}
+#else
+static unsigned
+fastrdtsc(void)
+{
+ unsigned eax;
+ __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax)
+ :"0"(0)
+ :"ecx", "edx", "ebx", "cc");
+
+ return eax;
+}
+#endif
+
+void
+bmError(int val, const char *file, const char *function, int line)
+{
+ fprintf(stderr, "Fatal video memory manager error \"%s\".\n"
+ "Check kernel logs or set the LIBGL_DEBUG\n"
+ "environment variable to \"verbose\" for more info.\n"
+ "Detected in file %s, line %d, function %s.\n",
+ strerror(-val), file, line, function);
+ abort();
+}
+
+#define BM_CKFATAL(val) \
+ do{ \
+ int tstVal = (val); \
+ if (tstVal) \
+ bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
+ } while(0);
+
+static unsigned
+time_diff(unsigned t, unsigned t2)
+{
+ return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
+}
+
+static int
+releaseContext(TinyDRIContext * ctx)
+{
+ switch (ctx->state) {
+ case haveContext:
+ uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id);
+ case haveDRM:
+ drmClose(ctx->drmFD);
+ case haveDeviceInfo:
+ XFree(ctx->driPriv);
+ case haveDriverName:
+ XFree(ctx->driverName);
+ case haveConnection:
+ XFree(ctx->curBusID);
+ uniDRICloseConnection(ctx->display, ctx->screen);
+ case haveDisplay:
+ XCloseDisplay(ctx->display);
+ default:
+ break;
+ }
+ return -1;
+}
+
+static void
+readBuf(void *buf, unsigned long size)
+{
+ volatile unsigned *buf32 = (unsigned *)buf;
+ unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32);
+
+ while (buf32 < end) {
+ (void)*buf32++;
+ }
+}
+
+static int
+benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
+ unsigned long *ticks)
+{
+ unsigned long curTime, oldTime;
+ int ret;
+ drmBO buf;
+ void *virtual;
+
+ /*
+ * Test system memory objects.
+ */
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOCreate(ctx->drmFD, size, 0, NULL,
+ DRM_BO_FLAG_READ |
+ DRM_BO_FLAG_WRITE |
+ DRM_BO_FLAG_MEM_LOCAL, 0, &buf));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
+ DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0xF0, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0x0F, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ readBuf(virtual, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ /*
+ * Test TT bound buffer objects.
+ */
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
+ DRM_BO_FLAG_MEM_TT,
+ DRM_BO_MASK_MEM,
+ 0,0,0));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
+ DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0xF0, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0x0F, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ readBuf(virtual, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
+ DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 0, 0,0));
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ /*
+ * Test cached buffers objects.
+ */
+
+ oldTime = fastrdtsc();
+ ret = drmBOSetStatus(ctx->drmFD, &buf,
+ DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_CACHED |
+ DRM_BO_FLAG_FORCE_CACHING,
+ DRM_BO_MASK_MEMTYPE |
+ DRM_BO_FLAG_FORCE_CACHING,
+ 0, 0, 0);
+ curTime = fastrdtsc();
+
+ if (ret) {
+ printf("Couldn't bind cached. Probably no support\n");
+ BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
+ return 1;
+ }
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
+ DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
+
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0xF0, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ memset(virtual, 0x0F, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ oldTime = fastrdtsc();
+ readBuf(virtual, buf.size);
+ curTime = fastrdtsc();
+ *ticks++ = time_diff(oldTime, curTime);
+
+ BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
+ BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
+
+ return 0;
+}
+
+static void
+testAGP(TinyDRIContext * ctx)
+{
+ unsigned long ticks[128], *pTicks;
+ unsigned long size = 8 * 1024;
+ int ret;
+
+ ret = benchmarkBuffer(ctx, size, ticks);
+ if (ret < 0) {
+ fprintf(stderr, "Buffer error %s\n", strerror(-ret));
+ return;
+ }
+ pTicks = ticks;
+
+ printf("Buffer size %d bytes\n", size);
+ printf("System memory timings ********************************\n");
+ printf("Creation took %12lu ticks\n", *pTicks++);
+ printf("Mapping took %12lu ticks\n", *pTicks++);
+ printf("Writing took %12lu ticks\n", *pTicks++);
+ printf("Writing Again took %12lu ticks\n", *pTicks++);
+ printf("Reading took %12lu ticks\n", *pTicks++);
+ printf("Unmapping took %12lu ticks\n", *pTicks++);
+
+ printf("\nTT Memory timings ************************************\n");
+ printf("Moving to TT took %12lu ticks\n", *pTicks++);
+ printf("Mapping in TT took %12lu ticks\n", *pTicks++);
+ printf("Writing to TT took %12lu ticks\n", *pTicks++);
+ printf("Writing again to TT took %12lu ticks\n", *pTicks++);
+ printf("Reading from TT took %12lu ticks\n", *pTicks++);
+ printf("Moving to system took %12lu ticks\n", *pTicks++);
+
+ if (ret == 1)
+ return;
+
+ printf("\nCached TT Memory timings *****************************\n");
+ printf("Moving to CTT took %12lu ticks\n", *pTicks++);
+ printf("Mapping in CTT took %12lu ticks\n", *pTicks++);
+ printf("Writing to CTT took %12lu ticks\n", *pTicks++);
+ printf("Re-writing to CTT took %12lu ticks\n", *pTicks++);
+ printf("Reading from CTT took %12lu ticks\n", *pTicks++);
+ printf("\n\n");
+}
+
+int
+main()
+{
+ int ret, screen, isCapable;
+ char *displayName = ":0";
+ TinyDRIContext ctx;
+ unsigned magic;
+
+ ctx.screen = 0;
+ ctx.state = haveNothing;
+ ctx.display = XOpenDisplay(displayName);
+ if (!ctx.display) {
+ fprintf(stderr, "Could not open display\n");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveDisplay;
+
+ ret =
+ uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen,
+ &isCapable);
+ if (!ret || !isCapable) {
+ fprintf(stderr, "No DRI on this display:sceen\n");
+ return releaseContext(&ctx);
+ }
+
+ if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset,
+ &ctx.curBusID)) {
+ fprintf(stderr, "Could not open DRI connection.\n");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveConnection;
+
+ if (!uniDRIGetClientDriverName(ctx.display, ctx.screen,
+ &ctx.ddxDriverMajor, &ctx.ddxDriverMinor,
+ &ctx.ddxDriverPatch, &ctx.driverName)) {
+ fprintf(stderr, "Could not get DRI driver name.\n");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveDriverName;
+
+ if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen,
+ &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize,
+ &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) {
+ fprintf(stderr, "Could not get DRI device info.\n");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveDriverName;
+
+ if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) {
+ perror("DRM Device could not be opened");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveDRM;
+
+ drmGetMagic(ctx.drmFD, &magic);
+ if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) {
+ fprintf(stderr, "Could not get X server to authenticate us.\n");
+ return releaseContext(&ctx);
+ }
+
+ ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor,
+ &ctx.visualInfo);
+ if (!ret) {
+ ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor,
+ &ctx.visualInfo);
+ if (!ret) {
+ fprintf(stderr, "Could not find a matching visual.\n");
+ return releaseContext(&ctx);
+ }
+ }
+
+ if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual,
+ &ctx.id, &ctx.hwContext)) {
+ fprintf(stderr, "Could not create DRI context.\n");
+ return releaseContext(&ctx);
+ }
+ ctx.state = haveContext;
+
+ testAGP(&ctx);
+
+ releaseContext(&ctx);
+ printf("Terminating normally\n");
+ return 0;
+}
diff --git a/tests/ttmtest/src/xf86dri.c b/tests/ttmtest/src/xf86dri.c
new file mode 100644
index 0000000..e6e0b89
--- /dev/null
+++ b/tests/ttmtest/src/xf86dri.c
@@ -0,0 +1,603 @@
+/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <stdint.h>
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define uniDRICheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display * dpy, XExtCodes * extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static
+XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info,
+ xf86dri_extension_name, &xf86dri_extension_hooks, 0, NULL)
+
+ static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info)
+
+/*****************************************************************************
+ * *
+ * public XFree86-DRI Extension routines *
+ * *
+ *****************************************************************************/
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+ Bool uniDRIQueryExtension(dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+Bool
+uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display *dpy;
+ int *majorVersion;
+ int *minorVersion;
+ int *patchVersion;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryVersion;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+Bool
+uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display *dpy;
+ int screen;
+ Bool *isCapable;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryDirectRenderingCapable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return False");
+ return False;
+ }
+ *isCapable = rep.isCapable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return True");
+ return True;
+}
+
+Bool
+uniDRIOpenConnection(dpy, screen, hSAREA, busIdString)
+ Display *dpy;
+ int screen;
+ drm_handle_t *hSAREA;
+ char **busIdString;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIOpenConnectionReply rep;
+ xXF86DRIOpenConnectionReq *req;
+
+ TRACE("OpenConnection...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIOpenConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIOpenConnection;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+
+ *hSAREA = rep.hSAREALow;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32;
+ }
+#endif
+ if (rep.length) {
+ if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+ _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+ _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+ } else {
+ *busIdString = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return True");
+ return True;
+}
+
+Bool
+uniDRIAuthConnection(dpy, screen, magic)
+ Display *dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIAuthConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIAuthConnection;
+ req->screen = screen;
+ req->magic = magic;
+ rep.authenticated = 0;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return True");
+ return True;
+}
+
+Bool
+uniDRICloseConnection(dpy, screen)
+ Display *dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICloseConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICloseConnection;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CloseConnection... return True");
+ return True;
+}
+
+Bool
+uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
+ ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+ Display *dpy;
+ int screen;
+ int *ddxDriverMajorVersion;
+ int *ddxDriverMinorVersion;
+ int *ddxDriverPatchVersion;
+ char **clientDriverName;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetClientDriverNameReply rep;
+ xXF86DRIGetClientDriverNameReq *req;
+
+ TRACE("GetClientDriverName...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetClientDriverName, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetClientDriverName;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+
+ *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+ *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+ *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+ if (rep.length) {
+ if (!(*clientDriverName =
+ (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+ _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+ _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+ } else {
+ *clientDriverName = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return True");
+ return True;
+}
+
+Bool
+uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext)
+ Display *dpy;
+ int screen;
+ int configID;
+ XID *context;
+ drm_context_t *hHWContext;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICreateContextReply rep;
+ xXF86DRICreateContextReq *req;
+
+ TRACE("CreateContext...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateContext;
+ req->visual = configID;
+ req->screen = screen;
+ *context = XAllocID(dpy);
+ req->context = *context;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return False");
+ return False;
+ }
+ *hHWContext = rep.hHWContext;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return True");
+ return True;
+}
+
+Bool
+uniDRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display *dpy;
+ int screen;
+ Visual *visual;
+ XID *context;
+ drm_context_t *hHWContext;
+{
+ return uniDRICreateContextWithConfig(dpy, screen, visual->visualid,
+ context, hHWContext);
+}
+
+Bool
+uniDRIDestroyContext(Display * ndpy, int screen, XID context)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyContext;
+ req->screen = screen;
+ req->context = context;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyContext... return True");
+ return True;
+}
+
+Bool
+uniDRICreateDrawable(Display * ndpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICreateDrawableReply rep;
+ xXF86DRICreateDrawableReq *req;
+
+ TRACE("CreateDrawable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return False");
+ return False;
+ }
+ *hHWDrawable = rep.hHWDrawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return True");
+ return True;
+}
+
+Bool
+uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyDrawable... return True");
+ return True;
+}
+
+Bool
+uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects, drm_clip_rect_t ** pBackClipRects)
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetDrawableInfoReply rep;
+ xXF86DRIGetDrawableInfoReq *req;
+ int total_rects;
+
+ TRACE("GetDrawableInfo...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDrawableInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDrawableInfo;
+ req->screen = screen;
+ req->drawable = drawable;
+
+ if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+ *index = rep.drawableTableIndex;
+ *stamp = rep.drawableTableStamp;
+ *X = (int)rep.drawableX;
+ *Y = (int)rep.drawableY;
+ *W = (int)rep.drawableWidth;
+ *H = (int)rep.drawableHeight;
+ *numClipRects = rep.numClipRects;
+ total_rects = *numClipRects;
+
+ *backX = rep.backX;
+ *backY = rep.backY;
+ *numBackClipRects = rep.numBackClipRects;
+ total_rects += *numBackClipRects;
+
+#if 0
+ /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+ * backwards compatibility (Because of the >> 2 shift) but the fix
+ * enables multi-threaded apps to work.
+ */
+ if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+ SIZEOF(xGenericReply) +
+ total_rects * sizeof(drm_clip_rect_t)) +
+ 3) & ~3) >> 2)) {
+ _XEatData(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+#endif
+
+ if (*numClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+ *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+ if (*pClipRects)
+ _XRead(dpy, (char *)*pClipRects, len);
+ } else {
+ *pClipRects = NULL;
+ }
+
+ if (*numBackClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+ *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+ if (*pBackClipRects)
+ _XRead(dpy, (char *)*pBackClipRects, len);
+ } else {
+ *pBackClipRects = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return True");
+ return True;
+}
+
+Bool
+uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer,
+ fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+ Display *dpy;
+ int screen;
+ drm_handle_t *hFrameBuffer;
+ int *fbOrigin;
+ int *fbSize;
+ int *fbStride;
+ int *devPrivateSize;
+ void **pDevPrivate;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetDeviceInfoReply rep;
+ xXF86DRIGetDeviceInfoReq *req;
+
+ TRACE("GetDeviceInfo...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDeviceInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDeviceInfo;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+
+ *hFrameBuffer = rep.hFrameBufferLow;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32;
+ }
+#endif
+
+ *fbOrigin = rep.framebufferOrigin;
+ *fbSize = rep.framebufferSize;
+ *fbStride = rep.framebufferStride;
+ *devPrivateSize = rep.devPrivateSize;
+
+ if (rep.length) {
+ if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+ _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+ _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize);
+ } else {
+ *pDevPrivate = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return True");
+ return True;
+}
diff --git a/tests/ttmtest/src/xf86dri.h b/tests/ttmtest/src/xf86dri.h
new file mode 100644
index 0000000..8fb7896
--- /dev/null
+++ b/tests/ttmtest/src/xf86dri.h
@@ -0,0 +1,116 @@
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.8 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <drm/drm.h>
+
+#define X_XF86DRIQueryVersion 0
+#define X_XF86DRIQueryDirectRenderingCapable 1
+#define X_XF86DRIOpenConnection 2
+#define X_XF86DRICloseConnection 3
+#define X_XF86DRIGetClientDriverName 4
+#define X_XF86DRICreateContext 5
+#define X_XF86DRIDestroyContext 6
+#define X_XF86DRICreateDrawable 7
+#define X_XF86DRIDestroyDrawable 8
+#define X_XF86DRIGetDrawableInfo 9
+#define X_XF86DRIGetDeviceInfo 10
+#define X_XF86DRIAuthConnection 11
+#define X_XF86DRIOpenFullScreen 12 /* Deprecated */
+#define X_XF86DRICloseFullScreen 13 /* Deprecated */
+
+#define XF86DRINumberEvents 0
+
+#define XF86DRIClientNotLocal 0
+#define XF86DRIOperationNotSupported 1
+#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+ Bool uniDRIQueryExtension(Display * dpy, int *event_base,
+ int *error_base);
+
+Bool uniDRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion);
+
+Bool uniDRIQueryDirectRenderingCapable(Display * dpy, int screen,
+ Bool * isCapable);
+
+Bool uniDRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA,
+ char **busIDString);
+
+Bool uniDRIAuthConnection(Display * dpy, int screen, drm_magic_t magic);
+
+Bool uniDRICloseConnection(Display * dpy, int screen);
+
+Bool uniDRIGetClientDriverName(Display * dpy, int screen,
+ int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion, char **clientDriverName);
+
+Bool uniDRICreateContext(Display * dpy, int screen, Visual * visual,
+ XID * ptr_to_returned_context_id, drm_context_t * hHWContext);
+
+Bool uniDRICreateContextWithConfig(Display * dpy, int screen, int configID,
+ XID * ptr_to_returned_context_id, drm_context_t * hHWContext);
+
+extern Bool uniDRIDestroyContext(Display * dpy, int screen, XID context_id);
+
+extern Bool uniDRICreateDrawable(Display * dpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable);
+
+extern Bool uniDRIDestroyDrawable(Display * dpy, int screen,
+ Drawable drawable);
+
+Bool uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects, drm_clip_rect_t ** pBackClipRects);
+
+Bool uniDRIGetDeviceInfo(Display * dpy, int screen,
+ drm_handle_t * hFrameBuffer, int *fbOrigin, int *fbSize,
+ int *fbStride, int *devPrivateSize, void **pDevPrivate);
+
+_XFUNCPROTOEND
+#endif /* _XF86DRI_SERVER_ */
+#endif /* _XF86DRI_H_ */
diff --git a/tests/ttmtest/src/xf86dristr.h b/tests/ttmtest/src/xf86dristr.h
new file mode 100644
index 0000000..2730d1a
--- /dev/null
+++ b/tests/ttmtest/src/xf86dristr.h
@@ -0,0 +1,390 @@
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.10 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number. This was originally set to be the same as the
+ * XFree86 version number. However, this version is really independent of
+ * the XFree86 version.
+ *
+ * Version History:
+ * 4.0.0: Original
+ * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION 4
+#define XF86DRI_MINOR_VERSION 1
+#define XF86DRI_PATCH_VERSION 0
+
+typedef struct _XF86DRIQueryVersion
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIQueryVersion */
+ CARD16 length B16;
+} xXF86DRIQueryVersionReq;
+
+#define sz_xXF86DRIQueryVersionReq 4
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of DRI protocol */
+ CARD16 minorVersion B16; /* minor version of DRI protocol */
+ CARD32 patchVersion B32; /* patch version of DRI protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIQueryVersionReply;
+
+#define sz_xXF86DRIQueryVersionReply 32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+
+#define sz_xXF86DRIQueryDirectRenderingCapableReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+
+#define sz_xXF86DRIQueryDirectRenderingCapableReply 32
+
+typedef struct _XF86DRIOpenConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIOpenConnectionReq;
+
+#define sz_xXF86DRIOpenConnectionReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hSAREALow B32;
+ CARD32 hSAREAHigh B32;
+ CARD32 busIdStringLength B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xXF86DRIOpenConnectionReply;
+
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xXF86DRIAuthConnectionReq;
+
+#define sz_xXF86DRIAuthConnectionReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIAuthConnectionReply;
+
+#define zx_xXF86DRIAuthConnectionReply 32
+
+typedef struct _XF86DRICloseConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRICloseConnectionReq;
+
+#define sz_xXF86DRICloseConnectionReq 8
+
+typedef struct _XF86DRIGetClientDriverName
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetClientDriverName */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetClientDriverNameReq;
+
+#define sz_xXF86DRIGetClientDriverNameReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ddxDriverMajorVersion B32;
+ CARD32 ddxDriverMinorVersion B32;
+ CARD32 ddxDriverPatchVersion B32;
+ CARD32 clientDriverNameLength B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+
+#define sz_xXF86DRIGetClientDriverNameReply 32
+
+typedef struct _XF86DRICreateContext
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 visual B32;
+ CARD32 context B32;
+} xXF86DRICreateContextReq;
+
+#define sz_xXF86DRICreateContextReq 16
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWContext B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateContextReply;
+
+#define sz_xXF86DRICreateContextReply 32
+
+typedef struct _XF86DRIDestroyContext
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 context B32;
+} xXF86DRIDestroyContextReq;
+
+#define sz_xXF86DRIDestroyContextReq 12
+
+typedef struct _XF86DRICreateDrawable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICreateDrawableReq;
+
+#define sz_xXF86DRICreateDrawableReq 12
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWDrawable B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateDrawableReply;
+
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIDestroyDrawableReq;
+
+#define sz_xXF86DRIDestroyDrawableReq 12
+
+typedef struct _XF86DRIGetDrawableInfo
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDrawableInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+
+#define sz_xXF86DRIGetDrawableInfoReq 12
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 drawableTableIndex B32;
+ CARD32 drawableTableStamp B32;
+ INT16 drawableX B16;
+ INT16 drawableY B16;
+ INT16 drawableWidth B16;
+ INT16 drawableHeight B16;
+ CARD32 numClipRects B32;
+ INT16 backX B16;
+ INT16 backY B16;
+ CARD32 numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply 36
+
+typedef struct _XF86DRIGetDeviceInfo
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDeviceInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetDeviceInfoReq;
+
+#define sz_xXF86DRIGetDeviceInfoReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hFrameBufferLow B32;
+ CARD32 hFrameBufferHigh B32;
+ CARD32 framebufferOrigin B32;
+ CARD32 framebufferSize B32;
+ CARD32 framebufferStride B32;
+ CARD32 devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+
+#define sz_xXF86DRIGetDeviceInfoReply 32
+
+typedef struct _XF86DRIOpenFullScreen
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIOpenFullScreenReq;
+
+#define sz_xXF86DRIOpenFullScreenReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isFullScreen B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+
+#define sz_xXF86DRIOpenFullScreenReply 32
+
+typedef struct _XF86DRICloseFullScreen
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICloseFullScreenReq;
+
+#define sz_xXF86DRICloseFullScreenReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xXF86DRICloseFullScreenReply;
+
+#define sz_xXF86DRICloseFullScreenReply 32
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/tests/util/Android.mk b/tests/util/Android.mk
new file mode 100644
index 0000000..12eccb4
--- /dev/null
+++ b/tests/util/Android.mk
@@ -0,0 +1,38 @@
+#
+# Copyright © 2015 NVIDIA Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/Makefile.sources
+
+LOCAL_MODULE := libdrm_util
+
+LOCAL_SHARED_LIBRARIES := libdrm
+
+LOCAL_SRC_FILES := $(UTIL_FILES)
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LIBDRM_TOP)/tests
+
+include $(LIBDRM_COMMON_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/tests/util/Makefile.sources b/tests/util/Makefile.sources
new file mode 100644
index 0000000..e5f8511
--- /dev/null
+++ b/tests/util/Makefile.sources
@@ -0,0 +1,8 @@
+UTIL_FILES := \
+ common.h \
+ format.c \
+ format.h \
+ kms.c \
+ kms.h \
+ pattern.c \
+ pattern.h
diff --git a/tests/util/common.h b/tests/util/common.h
new file mode 100644
index 0000000..5d572c2
--- /dev/null
+++ b/tests/util/common.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UTIL_COMMON_H
+#define UTIL_COMMON_H
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#endif /* UTIL_COMMON_H */
diff --git a/tests/util/format.c b/tests/util/format.c
new file mode 100644
index 0000000..1ca1b82
--- /dev/null
+++ b/tests/util/format.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drm_fourcc.h>
+
+#include "common.h"
+#include "format.h"
+
+#define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \
+ .rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } }
+
+#define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
+ .yuv = { (order), (xsub), (ysub), (chroma_stride) }
+
+static const struct util_format_info format_info[] = {
+ /* Indexed */
+ { DRM_FORMAT_C8, "C8" },
+ /* YUV packed */
+ { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
+ { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
+ { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
+ { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
+ /* YUV semi-planar */
+ { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
+ { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
+ { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
+ { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
+ /* YUV planar */
+ { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) },
+ { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
+ /* RGB16 */
+ { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) },
+ { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) },
+ { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) },
+ { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) },
+ { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) },
+ { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) },
+ { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) },
+ { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) },
+ { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
+ { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
+ { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) },
+ { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) },
+ { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) },
+ { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) },
+ { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) },
+ { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) },
+ { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
+ { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) },
+ /* RGB24 */
+ { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
+ { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+ /* RGB32 */
+ { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
+ { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
+ { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) },
+ { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
+ { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) },
+ { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) },
+ { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
+ { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
+ { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) },
+ { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) },
+ { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) },
+ { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) },
+ { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) },
+ { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) },
+ { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) },
+ { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) },
+ { DRM_FORMAT_XRGB16161616F, "XR4H", MAKE_RGB_INFO(16, 32, 16, 16, 16, 0, 0, 0) },
+ { DRM_FORMAT_XBGR16161616F, "XB4H", MAKE_RGB_INFO(16, 0, 16, 16, 16, 32, 0, 0) },
+ { DRM_FORMAT_ARGB16161616F, "AR4H", MAKE_RGB_INFO(16, 32, 16, 16, 16, 0, 16, 48) },
+ { DRM_FORMAT_ABGR16161616F, "AB4H", MAKE_RGB_INFO(16, 0, 16, 16, 16, 32, 16, 48) },
+
+};
+
+uint32_t util_format_fourcc(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(format_info); i++)
+ if (!strcmp(format_info[i].name, name))
+ return format_info[i].format;
+
+ return 0;
+}
+
+const struct util_format_info *util_format_info_find(uint32_t format)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(format_info); i++)
+ if (format_info[i].format == format)
+ return &format_info[i];
+
+ return NULL;
+}
diff --git a/tests/util/format.h b/tests/util/format.h
new file mode 100644
index 0000000..2ce1c02
--- /dev/null
+++ b/tests/util/format.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UTIL_FORMAT_H
+#define UTIL_FORMAT_H
+
+struct util_color_component {
+ unsigned int length;
+ unsigned int offset;
+};
+
+struct util_rgb_info {
+ struct util_color_component red;
+ struct util_color_component green;
+ struct util_color_component blue;
+ struct util_color_component alpha;
+};
+
+enum util_yuv_order {
+ YUV_YCbCr = 1,
+ YUV_YCrCb = 2,
+ YUV_YC = 4,
+ YUV_CY = 8,
+};
+
+struct util_yuv_info {
+ enum util_yuv_order order;
+ unsigned int xsub;
+ unsigned int ysub;
+ unsigned int chroma_stride;
+};
+
+struct util_format_info {
+ uint32_t format;
+ const char *name;
+ const struct util_rgb_info rgb;
+ const struct util_yuv_info yuv;
+};
+
+uint32_t util_format_fourcc(const char *name);
+const struct util_format_info *util_format_info_find(uint32_t format);
+
+#endif /* UTIL_FORMAT_H */
diff --git a/tests/util/kms.c b/tests/util/kms.c
new file mode 100644
index 0000000..95b7a45
--- /dev/null
+++ b/tests/util/kms.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This fairly simple test program dumps output in a similar format to the
+ * "xrandr" tool everyone knows & loves. It's necessarily slightly different
+ * since the kernel separates outputs into encoder and connector structures,
+ * each with their own unique ID. The program also allows test testing of the
+ * memory management and mode setting APIs by allowing the user to specify a
+ * connector and mode to use for mode setting. If all works as expected, a
+ * blue background should be painted on the monitor attached to the specified
+ * connector after the selected mode is set.
+ *
+ * TODO: use cairo to write the mode info on the selected output once
+ * the mode has been programmed, along with possible test patterns.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "common.h"
+
+struct type_name {
+ unsigned int type;
+ const char *name;
+};
+
+static const char *util_lookup_type_name(unsigned int type,
+ const struct type_name *table,
+ unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ if (table[i].type == type)
+ return table[i].name;
+
+ return NULL;
+}
+
+static const struct type_name encoder_type_names[] = {
+ { DRM_MODE_ENCODER_NONE, "none" },
+ { DRM_MODE_ENCODER_DAC, "DAC" },
+ { DRM_MODE_ENCODER_TMDS, "TMDS" },
+ { DRM_MODE_ENCODER_LVDS, "LVDS" },
+ { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+ { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
+ { DRM_MODE_ENCODER_DSI, "DSI" },
+ { DRM_MODE_ENCODER_DPMST, "DPMST" },
+ { DRM_MODE_ENCODER_DPI, "DPI" },
+};
+
+const char *util_lookup_encoder_type_name(unsigned int type)
+{
+ return util_lookup_type_name(type, encoder_type_names,
+ ARRAY_SIZE(encoder_type_names));
+}
+
+static const struct type_name connector_status_names[] = {
+ { DRM_MODE_CONNECTED, "connected" },
+ { DRM_MODE_DISCONNECTED, "disconnected" },
+ { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+const char *util_lookup_connector_status_name(unsigned int status)
+{
+ return util_lookup_type_name(status, connector_status_names,
+ ARRAY_SIZE(connector_status_names));
+}
+
+static const char * const modules[] = {
+ "i915",
+ "amdgpu",
+ "radeon",
+ "nouveau",
+ "vmwgfx",
+ "omapdrm",
+ "exynos",
+ "tilcdc",
+ "msm",
+ "sti",
+ "tegra",
+ "imx-drm",
+ "rockchip",
+ "atmel-hlcdc",
+ "fsl-dcu-drm",
+ "vc4",
+ "virtio_gpu",
+ "mediatek",
+ "meson",
+ "pl111",
+ "stm",
+ "sun4i-drm",
+ "armada-drm",
+ "komeda",
+ "imx-dcss",
+ "mxsfb-drm",
+ "simpledrm",
+ "imx-lcdif",
+};
+
+int util_open(const char *device, const char *module)
+{
+ int fd;
+
+ if (module) {
+ fd = drmOpen(module, device);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open device '%s': %s\n",
+ module, strerror(errno));
+ return -errno;
+ }
+ } else {
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(modules); i++) {
+ printf("trying to open device '%s'...", modules[i]);
+
+ fd = drmOpen(modules[i], device);
+ if (fd < 0) {
+ printf("failed\n");
+ } else {
+ printf("done\n");
+ break;
+ }
+ }
+
+ if (fd < 0) {
+ fprintf(stderr, "no device found\n");
+ return -ENODEV;
+ }
+ }
+
+ return fd;
+}
diff --git a/tests/util/kms.h b/tests/util/kms.h
new file mode 100644
index 0000000..f79f461
--- /dev/null
+++ b/tests/util/kms.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UTIL_KMS_H
+#define UTIL_KMS_H
+
+const char *util_lookup_encoder_type_name(unsigned int type);
+const char *util_lookup_connector_status_name(unsigned int type);
+
+int util_open(const char *device, const char *module);
+
+#endif /* UTIL_KMS_H */
diff --git a/tests/util/meson.build b/tests/util/meson.build
new file mode 100644
index 0000000..7fa1a4b
--- /dev/null
+++ b/tests/util/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+libutil = static_library(
+ 'util',
+ [files('format.c', 'kms.c', 'pattern.c'), config_file],
+ include_directories : [inc_root, inc_drm],
+ link_with : libdrm,
+ dependencies : dep_cairo
+)
diff --git a/tests/util/pattern.c b/tests/util/pattern.c
new file mode 100644
index 0000000..158c0b1
--- /dev/null
+++ b/tests/util/pattern.c
@@ -0,0 +1,1282 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drm_fourcc.h>
+
+#if HAVE_CAIRO
+#include <cairo.h>
+#include <math.h>
+#endif
+
+#include "common.h"
+#include "format.h"
+#include "pattern.h"
+
+struct color_rgb24 {
+ unsigned int value:24;
+} __attribute__((__packed__));
+
+struct color_yuv {
+ unsigned char y;
+ unsigned char u;
+ unsigned char v;
+};
+
+#define MAKE_YUV_601_Y(r, g, b) \
+ ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
+#define MAKE_YUV_601_U(r, g, b) \
+ (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
+#define MAKE_YUV_601_V(r, g, b) \
+ (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
+
+#define MAKE_YUV_601(r, g, b) \
+ { .y = MAKE_YUV_601_Y(r, g, b), \
+ .u = MAKE_YUV_601_U(r, g, b), \
+ .v = MAKE_YUV_601_V(r, g, b) }
+
+/* This function takes 8-bit color values */
+static inline uint32_t shiftcolor8(const struct util_color_component *comp,
+ uint32_t value)
+{
+ value &= 0xff;
+ /* Fill the low bits with the high bits. */
+ value = (value << 8) | value;
+ /* Shift down to remove unwanted low bits */
+ value = value >> (16 - comp->length);
+ /* Shift back up to where the value should be */
+ return value << comp->offset;
+}
+
+/* This function takes 10-bit color values */
+static inline uint32_t shiftcolor10(const struct util_color_component *comp,
+ uint32_t value)
+{
+ value &= 0x3ff;
+ /* Fill the low bits with the high bits. */
+ value = (value << 6) | (value >> 4);
+ /* Shift down to remove unwanted low bits */
+ value = value >> (16 - comp->length);
+ /* Shift back up to where the value should be */
+ return value << comp->offset;
+}
+
+/* This function takes 16-bit color values */
+static inline uint64_t shiftcolor16(const struct util_color_component *comp,
+ uint64_t value)
+{
+ value &= 0xffff;
+ /* Shift down to remove unwanted low bits */
+ value = value >> (16 - comp->length);
+ /* Shift back up to where the value should be */
+ return value << comp->offset;
+}
+
+#define MAKE_RGBA10(rgb, r, g, b, a) \
+ (shiftcolor10(&(rgb)->red, (r)) | \
+ shiftcolor10(&(rgb)->green, (g)) | \
+ shiftcolor10(&(rgb)->blue, (b)) | \
+ shiftcolor10(&(rgb)->alpha, (a)))
+
+#define MAKE_RGBA(rgb, r, g, b, a) \
+ (shiftcolor8(&(rgb)->red, (r)) | \
+ shiftcolor8(&(rgb)->green, (g)) | \
+ shiftcolor8(&(rgb)->blue, (b)) | \
+ shiftcolor8(&(rgb)->alpha, (a)))
+
+#define MAKE_RGB24(rgb, r, g, b) \
+ { .value = MAKE_RGBA(rgb, r, g, b, 0) }
+
+
+/**
+ * Takes a uint16_t, divides by 65536, converts the infinite-precision
+ * result to fp16 with round-to-zero.
+ *
+ * Copied from mesa:src/util/half_float.c
+ */
+static uint16_t uint16_div_64k_to_half(uint16_t v)
+{
+ /* Zero or subnormal. Set the mantissa to (v << 8) and return. */
+ if (v < 4)
+ return v << 8;
+
+ /* Count the leading 0s in the uint16_t */
+ int n = __builtin_clz(v) - 16;
+
+ /* Shift the mantissa up so bit 16 is the hidden 1 bit,
+ * mask it off, then shift back down to 10 bits
+ */
+ int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
+
+ /* (0{n} 1 X{15-n}) * 2^-16
+ * = 1.X * 2^(15-n-16)
+ * = 1.X * 2^(14-n - 15)
+ * which is the FP16 form with e = 14 - n
+ */
+ int e = 14 - n;
+
+ return (e << 10) | m;
+}
+
+#define MAKE_RGBA8FP16(rgb, r, g, b, a) \
+ (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \
+ shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \
+ shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \
+ shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8)))
+
+#define MAKE_RGBA10FP16(rgb, r, g, b, a) \
+ (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \
+ shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \
+ shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \
+ shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6)))
+
+static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
+ unsigned char *y_mem, unsigned char *u_mem,
+ unsigned char *v_mem, unsigned int width,
+ unsigned int height, unsigned int stride)
+{
+ const struct color_yuv colors_top[] = {
+ MAKE_YUV_601(191, 192, 192), /* grey */
+ MAKE_YUV_601(192, 192, 0), /* yellow */
+ MAKE_YUV_601(0, 192, 192), /* cyan */
+ MAKE_YUV_601(0, 192, 0), /* green */
+ MAKE_YUV_601(192, 0, 192), /* magenta */
+ MAKE_YUV_601(192, 0, 0), /* red */
+ MAKE_YUV_601(0, 0, 192), /* blue */
+ };
+ const struct color_yuv colors_middle[] = {
+ MAKE_YUV_601(0, 0, 192), /* blue */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(192, 0, 192), /* magenta */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(0, 192, 192), /* cyan */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(192, 192, 192), /* grey */
+ };
+ const struct color_yuv colors_bottom[] = {
+ MAKE_YUV_601(0, 33, 76), /* in-phase */
+ MAKE_YUV_601(255, 255, 255), /* super white */
+ MAKE_YUV_601(50, 0, 106), /* quadrature */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(9, 9, 9), /* 3.5% */
+ MAKE_YUV_601(19, 19, 19), /* 7.5% */
+ MAKE_YUV_601(29, 29, 29), /* 11.5% */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ };
+ unsigned int cs = yuv->chroma_stride;
+ unsigned int xsub = yuv->xsub;
+ unsigned int ysub = yuv->ysub;
+ unsigned int x;
+ unsigned int y;
+
+ /* Luma */
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ y_mem[x] = colors_top[x * 7 / width].y;
+ y_mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ y_mem[x] = colors_middle[x * 7 / width].y;
+ y_mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
+ for (; x < width * 6 / 7; ++x)
+ y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4].y;
+ for (; x < width; ++x)
+ y_mem[x] = colors_bottom[7].y;
+ y_mem += stride;
+ }
+
+ /* Chroma */
+ for (y = 0; y < height / ysub * 6 / 9; ++y) {
+ for (x = 0; x < width; x += xsub) {
+ u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
+ v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
+ }
+ u_mem += stride * cs / xsub;
+ v_mem += stride * cs / xsub;
+ }
+
+ for (; y < height / ysub * 7 / 9; ++y) {
+ for (x = 0; x < width; x += xsub) {
+ u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
+ v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
+ }
+ u_mem += stride * cs / xsub;
+ v_mem += stride * cs / xsub;
+ }
+
+ for (; y < height / ysub; ++y) {
+ for (x = 0; x < width * 5 / 7; x += xsub) {
+ u_mem[x*cs/xsub] =
+ colors_bottom[x * 4 / (width * 5 / 7)].u;
+ v_mem[x*cs/xsub] =
+ colors_bottom[x * 4 / (width * 5 / 7)].v;
+ }
+ for (; x < width * 6 / 7; x += xsub) {
+ u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
+ 3 / (width / 7) + 4].u;
+ v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
+ 3 / (width / 7) + 4].v;
+ }
+ for (; x < width; x += xsub) {
+ u_mem[x*cs/xsub] = colors_bottom[7].u;
+ v_mem[x*cs/xsub] = colors_bottom[7].v;
+ }
+ u_mem += stride * cs / xsub;
+ v_mem += stride * cs / xsub;
+ }
+}
+
+static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct color_yuv colors_top[] = {
+ MAKE_YUV_601(191, 192, 192), /* grey */
+ MAKE_YUV_601(192, 192, 0), /* yellow */
+ MAKE_YUV_601(0, 192, 192), /* cyan */
+ MAKE_YUV_601(0, 192, 0), /* green */
+ MAKE_YUV_601(192, 0, 192), /* magenta */
+ MAKE_YUV_601(192, 0, 0), /* red */
+ MAKE_YUV_601(0, 0, 192), /* blue */
+ };
+ const struct color_yuv colors_middle[] = {
+ MAKE_YUV_601(0, 0, 192), /* blue */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(192, 0, 192), /* magenta */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(0, 192, 192), /* cyan */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(192, 192, 192), /* grey */
+ };
+ const struct color_yuv colors_bottom[] = {
+ MAKE_YUV_601(0, 33, 76), /* in-phase */
+ MAKE_YUV_601(255, 255, 255), /* super white */
+ MAKE_YUV_601(50, 0, 106), /* quadrature */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ MAKE_YUV_601(9, 9, 9), /* 3.5% */
+ MAKE_YUV_601(19, 19, 19), /* 7.5% */
+ MAKE_YUV_601(29, 29, 29), /* 11.5% */
+ MAKE_YUV_601(19, 19, 19), /* black */
+ };
+ unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
+ unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
+ unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
+ unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
+ unsigned int x;
+ unsigned int y;
+
+ /* Luma */
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ y_mem[2*x] = colors_top[x * 7 / width].y;
+ y_mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ y_mem[2*x] = colors_middle[x * 7 / width].y;
+ y_mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
+ for (; x < width * 6 / 7; ++x)
+ y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4].y;
+ for (; x < width; ++x)
+ y_mem[2*x] = colors_bottom[7].y;
+ y_mem += stride;
+ }
+
+ /* Chroma */
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; x += 2) {
+ c_mem[2*x+u] = colors_top[x * 7 / width].u;
+ c_mem[2*x+v] = colors_top[x * 7 / width].v;
+ }
+ c_mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; x += 2) {
+ c_mem[2*x+u] = colors_middle[x * 7 / width].u;
+ c_mem[2*x+v] = colors_middle[x * 7 / width].v;
+ }
+ c_mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; x += 2) {
+ c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
+ c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
+ }
+ for (; x < width * 6 / 7; x += 2) {
+ c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
+ 3 / (width / 7) + 4].u;
+ c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
+ 3 / (width / 7) + 4].v;
+ }
+ for (; x < width; x += 2) {
+ c_mem[2*x+u] = colors_bottom[7].u;
+ c_mem[2*x+v] = colors_bottom[7].v;
+ }
+ c_mem += stride;
+ }
+}
+
+static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const uint16_t colors_top[] = {
+ MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
+ MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
+ MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
+ MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
+ MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
+ MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
+ MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
+ };
+ const uint16_t colors_middle[] = {
+ MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
+ };
+ const uint16_t colors_bottom[] = {
+ MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
+ MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
+ MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
+ MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
+ MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
+ };
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ ((uint16_t *)mem)[x] =
+ colors_bottom[x * 4 / (width * 5 / 7)];
+ for (; x < width * 6 / 7; ++x)
+ ((uint16_t *)mem)[x] =
+ colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4];
+ for (; x < width; ++x)
+ ((uint16_t *)mem)[x] = colors_bottom[7];
+ mem += stride;
+ }
+}
+
+static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct color_rgb24 colors_top[] = {
+ MAKE_RGB24(rgb, 192, 192, 192), /* grey */
+ MAKE_RGB24(rgb, 192, 192, 0), /* yellow */
+ MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
+ MAKE_RGB24(rgb, 0, 192, 0), /* green */
+ MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
+ MAKE_RGB24(rgb, 192, 0, 0), /* red */
+ MAKE_RGB24(rgb, 0, 0, 192), /* blue */
+ };
+ const struct color_rgb24 colors_middle[] = {
+ MAKE_RGB24(rgb, 0, 0, 192), /* blue */
+ MAKE_RGB24(rgb, 19, 19, 19), /* black */
+ MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
+ MAKE_RGB24(rgb, 19, 19, 19), /* black */
+ MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
+ MAKE_RGB24(rgb, 19, 19, 19), /* black */
+ MAKE_RGB24(rgb, 192, 192, 192), /* grey */
+ };
+ const struct color_rgb24 colors_bottom[] = {
+ MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */
+ MAKE_RGB24(rgb, 255, 255, 255), /* super white */
+ MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */
+ MAKE_RGB24(rgb, 19, 19, 19), /* black */
+ MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */
+ MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */
+ MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */
+ MAKE_RGB24(rgb, 19, 19, 19), /* black */
+ };
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((struct color_rgb24 *)mem)[x] =
+ colors_top[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((struct color_rgb24 *)mem)[x] =
+ colors_middle[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ ((struct color_rgb24 *)mem)[x] =
+ colors_bottom[x * 4 / (width * 5 / 7)];
+ for (; x < width * 6 / 7; ++x)
+ ((struct color_rgb24 *)mem)[x] =
+ colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4];
+ for (; x < width; ++x)
+ ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
+ mem += stride;
+ }
+}
+
+static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const uint32_t colors_top[] = {
+ MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
+ MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
+ MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
+ MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
+ MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
+ MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
+ MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
+ };
+ const uint32_t colors_middle[] = {
+ MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
+ MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
+ };
+ const uint32_t colors_bottom[] = {
+ MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
+ MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
+ MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
+ MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
+ MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
+ MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
+ };
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ ((uint32_t *)mem)[x] =
+ colors_bottom[x * 4 / (width * 5 / 7)];
+ for (; x < width * 6 / 7; ++x)
+ ((uint32_t *)mem)[x] =
+ colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4];
+ for (; x < width; ++x)
+ ((uint32_t *)mem)[x] = colors_bottom[7];
+ mem += stride;
+ }
+}
+
+static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const uint64_t colors_top[] = {
+ MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */
+ MAKE_RGBA8FP16(rgb, 192, 192, 0, 255), /* yellow */
+ MAKE_RGBA8FP16(rgb, 0, 192, 192, 255), /* cyan */
+ MAKE_RGBA8FP16(rgb, 0, 192, 0, 255), /* green */
+ MAKE_RGBA8FP16(rgb, 192, 0, 192, 255), /* magenta */
+ MAKE_RGBA8FP16(rgb, 192, 0, 0, 255), /* red */
+ MAKE_RGBA8FP16(rgb, 0, 0, 192, 255), /* blue */
+ };
+ const uint64_t colors_middle[] = {
+ MAKE_RGBA8FP16(rgb, 0, 0, 192, 127), /* blue */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA8FP16(rgb, 192, 0, 192, 127), /* magenta */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA8FP16(rgb, 0, 192, 192, 127), /* cyan */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
+ MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */
+ };
+ const uint64_t colors_bottom[] = {
+ MAKE_RGBA8FP16(rgb, 0, 33, 76, 255), /* in-phase */
+ MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */
+ MAKE_RGBA8FP16(rgb, 50, 0, 106, 255), /* quadrature */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */
+ MAKE_RGBA8FP16(rgb, 9, 9, 9, 255), /* 3.5% */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* 7.5% */
+ MAKE_RGBA8FP16(rgb, 29, 29, 29, 255), /* 11.5% */
+ MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */
+ };
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint64_t *)mem)[x] = colors_top[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
+ mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ ((uint64_t *)mem)[x] =
+ colors_bottom[x * 4 / (width * 5 / 7)];
+ for (; x < width * 6 / 7; ++x)
+ ((uint64_t *)mem)[x] =
+ colors_bottom[(x - width * 5 / 7) * 3
+ / (width / 7) + 4];
+ for (; x < width; ++x)
+ ((uint64_t *)mem)[x] = colors_bottom[7];
+ mem += stride;
+ }
+}
+
+static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height * 6 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint8_t *)mem)[x] = x * 7 / width;
+ mem += stride;
+ }
+
+ for (; y < height * 7 / 9; ++y) {
+ for (x = 0; x < width; ++x)
+ ((uint8_t *)mem)[x] = 7 + (x * 7 / width);
+ mem += stride;
+ }
+
+ for (; y < height; ++y) {
+ for (x = 0; x < width * 5 / 7; ++x)
+ ((uint8_t *)mem)[x] =
+ 14 + (x * 4 / (width * 5 / 7));
+ for (; x < width * 6 / 7; ++x)
+ ((uint8_t *)mem)[x] =
+ 14 + ((x - width * 5 / 7) * 3
+ / (width / 7) + 4);
+ for (; x < width; ++x)
+ ((uint8_t *)mem)[x] = 14 + 7;
+ mem += stride;
+ }
+}
+
+void util_smpte_c8_gamma(unsigned size, struct drm_color_lut *lut)
+{
+ if (size < 7 + 7 + 8) {
+ printf("Error: gamma too small: %d < %d\n", size, 7 + 7 + 8);
+ return;
+ }
+ memset(lut, 0, size * sizeof(struct drm_color_lut));
+
+#define FILL_COLOR(idx, r, g, b) \
+ lut[idx].red = (r) << 8; \
+ lut[idx].green = (g) << 8; \
+ lut[idx].blue = (b) << 8
+
+ FILL_COLOR( 0, 192, 192, 192); /* grey */
+ FILL_COLOR( 1, 192, 192, 0 ); /* yellow */
+ FILL_COLOR( 2, 0, 192, 192); /* cyan */
+ FILL_COLOR( 3, 0, 192, 0 ); /* green */
+ FILL_COLOR( 4, 192, 0, 192); /* magenta */
+ FILL_COLOR( 5, 192, 0, 0 ); /* red */
+ FILL_COLOR( 6, 0, 0, 192); /* blue */
+
+ FILL_COLOR( 7, 0, 0, 192); /* blue */
+ FILL_COLOR( 8, 19, 19, 19 ); /* black */
+ FILL_COLOR( 9, 192, 0, 192); /* magenta */
+ FILL_COLOR(10, 19, 19, 19 ); /* black */
+ FILL_COLOR(11, 0, 192, 192); /* cyan */
+ FILL_COLOR(12, 19, 19, 19 ); /* black */
+ FILL_COLOR(13, 192, 192, 192); /* grey */
+
+ FILL_COLOR(14, 0, 33, 76); /* in-phase */
+ FILL_COLOR(15, 255, 255, 255); /* super white */
+ FILL_COLOR(16, 50, 0, 106); /* quadrature */
+ FILL_COLOR(17, 19, 19, 19); /* black */
+ FILL_COLOR(18, 9, 9, 9); /* 3.5% */
+ FILL_COLOR(19, 19, 19, 19); /* 7.5% */
+ FILL_COLOR(20, 29, 29, 29); /* 11.5% */
+ FILL_COLOR(21, 19, 19, 19); /* black */
+
+#undef FILL_COLOR
+}
+
+static void fill_smpte(const struct util_format_info *info, void *planes[3],
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ unsigned char *u, *v;
+
+ switch (info->format) {
+ case DRM_FORMAT_C8:
+ return fill_smpte_c8(planes[0], width, height, stride);
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
+ height, stride);
+
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
+ v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
+ return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
+ width, height, stride);
+
+ case DRM_FORMAT_YUV420:
+ return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
+ planes[2], width, height, stride);
+
+ case DRM_FORMAT_YVU420:
+ return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
+ planes[1], width, height, stride);
+
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX5551:
+ return fill_smpte_rgb16(&info->rgb, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ return fill_smpte_rgb24(&info->rgb, planes[0],
+ width, height, stride);
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ return fill_smpte_rgb32(&info->rgb, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ return fill_smpte_rgb16fp(&info->rgb, planes[0],
+ width, height, stride);
+ }
+}
+
+/* swap these for big endian.. */
+#define RED 2
+#define GREEN 1
+#define BLUE 0
+
+static void make_pwetty(void *data, unsigned int width, unsigned int height,
+ unsigned int stride, uint32_t format)
+{
+#if HAVE_CAIRO
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ cairo_format_t cairo_format;
+
+ /* we can ignore the order of R,G,B channels */
+ switch (format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ cairo_format = CAIRO_FORMAT_ARGB32;
+ break;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ cairo_format = CAIRO_FORMAT_RGB16_565;
+ break;
+#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ cairo_format = CAIRO_FORMAT_RGB30;
+ break;
+#endif
+ default:
+ return;
+ }
+
+ surface = cairo_image_surface_create_for_data(data,
+ cairo_format,
+ width, height,
+ stride);
+ cr = cairo_create(surface);
+ cairo_surface_destroy(surface);
+
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+ for (unsigned x = 0; x < width; x += 250)
+ for (unsigned y = 0; y < height; y += 250) {
+ char buf[64];
+
+ cairo_move_to(cr, x, y - 20);
+ cairo_line_to(cr, x, y + 20);
+ cairo_move_to(cr, x - 20, y);
+ cairo_line_to(cr, x + 20, y);
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, x, y, 10, 0, M_PI * 2);
+ cairo_set_line_width(cr, 4);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_set_line_width(cr, 2);
+ cairo_stroke(cr);
+
+ snprintf(buf, sizeof buf, "%d, %d", x, y);
+ cairo_move_to(cr, x + 20, y + 20);
+ cairo_text_path(cr, buf);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+ }
+
+ cairo_destroy(cr);
+#endif
+}
+
+static void fill_tiles_yuv_planar(const struct util_format_info *info,
+ unsigned char *y_mem, unsigned char *u_mem,
+ unsigned char *v_mem, unsigned int width,
+ unsigned int height, unsigned int stride)
+{
+ const struct util_yuv_info *yuv = &info->yuv;
+ unsigned int cs = yuv->chroma_stride;
+ unsigned int xsub = yuv->xsub;
+ unsigned int ysub = yuv->ysub;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ struct color_yuv color =
+ MAKE_YUV_601((rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+ y_mem[x] = color.y;
+ u_mem[x/xsub*cs] = color.u;
+ v_mem[x/xsub*cs] = color.v;
+ }
+
+ y_mem += stride;
+ if ((y + 1) % ysub == 0) {
+ u_mem += stride * cs / xsub;
+ v_mem += stride * cs / xsub;
+ }
+ }
+}
+
+static void fill_tiles_yuv_packed(const struct util_format_info *info,
+ void *mem, unsigned int width,
+ unsigned int height, unsigned int stride)
+{
+ const struct util_yuv_info *yuv = &info->yuv;
+ unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
+ unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
+ unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
+ unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; x += 2) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ struct color_yuv color =
+ MAKE_YUV_601((rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+ y_mem[2*x] = color.y;
+ c_mem[2*x+u] = color.u;
+ y_mem[2*x+2] = color.y;
+ c_mem[2*x+v] = color.v;
+ }
+
+ y_mem += stride;
+ c_mem += stride;
+ }
+}
+
+static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct util_rgb_info *rgb = &info->rgb;
+ void *mem_base = mem;
+ unsigned int x, y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ uint16_t color =
+ MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+ 255);
+
+ ((uint16_t *)mem)[x] = color;
+ }
+ mem += stride;
+ }
+
+ make_pwetty(mem_base, width, height, stride, info->format);
+}
+
+static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct util_rgb_info *rgb = &info->rgb;
+ unsigned int x, y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ struct color_rgb24 color =
+ MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff);
+
+ ((struct color_rgb24 *)mem)[x] = color;
+ }
+ mem += stride;
+ }
+}
+
+static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct util_rgb_info *rgb = &info->rgb;
+ void *mem_base = mem;
+ unsigned int x, y;
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
+ uint32_t color =
+ MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+ alpha);
+
+ ((uint32_t *)mem)[x] = color;
+ }
+ mem += stride;
+ }
+
+ make_pwetty(mem_base, width, height, stride, info->format);
+}
+
+static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ const struct util_rgb_info *rgb = &info->rgb;
+ unsigned int x, y;
+
+ /* TODO: Give this actual fp16 precision */
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ div_t d = div(x+y, width);
+ uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
+ + 0x000a1120 * (d.rem >> 6);
+ uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
+ uint64_t color =
+ MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
+ (rgb32 >> 8) & 0xff, rgb32 & 0xff,
+ alpha);
+
+ ((uint64_t *)mem)[x] = color;
+ }
+ mem += stride;
+ }
+}
+
+static void fill_tiles(const struct util_format_info *info, void *planes[3],
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ unsigned char *u, *v;
+
+ switch (info->format) {
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ return fill_tiles_yuv_packed(info, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV61:
+ u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
+ v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
+ return fill_tiles_yuv_planar(info, planes[0], u, v,
+ width, height, stride);
+
+ case DRM_FORMAT_YUV420:
+ return fill_tiles_yuv_planar(info, planes[0], planes[1],
+ planes[2], width, height, stride);
+
+ case DRM_FORMAT_YVU420:
+ return fill_tiles_yuv_planar(info, planes[0], planes[2],
+ planes[1], width, height, stride);
+
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX5551:
+ return fill_tiles_rgb16(info, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ return fill_tiles_rgb24(info, planes[0],
+ width, height, stride);
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ return fill_tiles_rgb32(info, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ return fill_tiles_rgb16fp(info, planes[0],
+ width, height, stride);
+ }
+}
+
+static void fill_plain(const struct util_format_info *info, void *planes[3],
+ unsigned int height,
+ unsigned int stride)
+{
+ switch (info->format) {
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ /* 0x3838 = 0.5273 */
+ memset(planes[0], 0x38, stride * height);
+ break;
+ default:
+ memset(planes[0], 0x77, stride * height);
+ break;
+ }
+}
+
+static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
+ void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < height / 2; i++) {
+ uint32_t *row = mem;
+
+ for (j = 0; j < width / 2; j++) {
+ uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
+ row[2*j] = row[2*j+1] = value;
+ }
+ mem += stride;
+ }
+
+ for (; i < height; i++) {
+ uint32_t *row = mem;
+
+ for (j = 0; j < width / 2; j++) {
+ uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
+ row[2*j] = row[2*j+1] = value;
+ }
+ mem += stride;
+ }
+}
+
+static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
+ void *mem,
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < height / 2; i++) {
+ uint64_t *row = mem;
+
+ for (j = 0; j < width / 2; j++) {
+ uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
+ row[2*j] = row[2*j+1] = value;
+ }
+ mem += stride;
+ }
+
+ for (; i < height; i++) {
+ uint64_t *row = mem;
+
+ for (j = 0; j < width / 2; j++) {
+ uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
+ row[2*j] = row[2*j+1] = value;
+ }
+ mem += stride;
+ }
+}
+
+/* The gradient pattern creates two horizontal gray gradients, split
+ * into two halves. The top half has 10bpc precision, the bottom half
+ * has 8bpc precision. When using with a 10bpc fb format, there are 3
+ * possible outcomes:
+ *
+ * - Pixel data is encoded as 8bpc to the display, no dithering. This
+ * would lead to the top and bottom halves looking identical.
+ *
+ * - Pixel data is encoded as 8bpc to the display, with dithering. This
+ * would lead to there being a visible difference between the two halves,
+ * but the top half would look a little speck-y due to the dithering.
+ *
+ * - Pixel data is encoded at 10bpc+ to the display (which implies
+ * the display is able to show this level of depth). This should
+ * lead to the top half being a very clean gradient, and visibly different
+ * from the bottom half.
+ *
+ * Once we support additional fb formats, this approach could be extended
+ * to distinguish even higher bpc precisions.
+ *
+ * Note that due to practical size considerations, for the screens
+ * where this matters, the pattern actually emits stripes 2-pixels
+ * wide for each gradient color. Otherwise the difference may be a bit
+ * hard to notice.
+ */
+static void fill_gradient(const struct util_format_info *info, void *planes[3],
+ unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+ switch (info->format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ return fill_gradient_rgb32(&info->rgb, planes[0],
+ width, height, stride);
+
+ case DRM_FORMAT_XRGB16161616F:
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ARGB16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ return fill_gradient_rgb16fp(&info->rgb, planes[0],
+ width, height, stride);
+ }
+}
+
+/*
+ * util_fill_pattern - Fill a buffer with a test pattern
+ * @format: Pixel format
+ * @pattern: Test pattern
+ * @planes: Array of buffers
+ * @width: Width in pixels
+ * @height: Height in pixels
+ * @stride: Line stride (pitch) in bytes
+ *
+ * Fill the buffers with the test pattern specified by the pattern parameter.
+ * Supported formats vary depending on the selected pattern.
+ */
+void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
+ void *planes[3], unsigned int width,
+ unsigned int height, unsigned int stride)
+{
+ const struct util_format_info *info;
+
+ info = util_format_info_find(format);
+ if (info == NULL)
+ return;
+
+ switch (pattern) {
+ case UTIL_PATTERN_TILES:
+ return fill_tiles(info, planes, width, height, stride);
+
+ case UTIL_PATTERN_SMPTE:
+ return fill_smpte(info, planes, width, height, stride);
+
+ case UTIL_PATTERN_PLAIN:
+ return fill_plain(info, planes, height, stride);
+
+ case UTIL_PATTERN_GRADIENT:
+ return fill_gradient(info, planes, width, height, stride);
+
+ default:
+ printf("Error: unsupported test pattern %u.\n", pattern);
+ break;
+ }
+}
+
+static const char *pattern_names[] = {
+ [UTIL_PATTERN_TILES] = "tiles",
+ [UTIL_PATTERN_SMPTE] = "smpte",
+ [UTIL_PATTERN_PLAIN] = "plain",
+ [UTIL_PATTERN_GRADIENT] = "gradient",
+};
+
+enum util_fill_pattern util_pattern_enum(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
+ if (!strcmp(pattern_names[i], name))
+ return (enum util_fill_pattern)i;
+
+ printf("Error: unsupported test pattern %s.\n", name);
+ return UTIL_PATTERN_SMPTE;
+}
diff --git a/tests/util/pattern.h b/tests/util/pattern.h
new file mode 100644
index 0000000..ea38caf
--- /dev/null
+++ b/tests/util/pattern.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UTIL_PATTERN_H
+#define UTIL_PATTERN_H
+
+#include <drm_mode.h>
+
+enum util_fill_pattern {
+ UTIL_PATTERN_TILES,
+ UTIL_PATTERN_PLAIN,
+ UTIL_PATTERN_SMPTE,
+ UTIL_PATTERN_GRADIENT,
+};
+
+void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
+ void *planes[3], unsigned int width,
+ unsigned int height, unsigned int stride);
+
+void util_smpte_c8_gamma(unsigned size, struct drm_color_lut *lut);
+
+enum util_fill_pattern util_pattern_enum(const char *name);
+
+#endif /* UTIL_PATTERN_H */
diff --git a/tests/vbltest/meson.build b/tests/vbltest/meson.build
new file mode 100644
index 0000000..6339feb
--- /dev/null
+++ b/tests/vbltest/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+vbltest = executable(
+ 'vbltest',
+ files('vbltest.c'),
+ c_args : libdrm_c_args,
+ include_directories : [inc_root, inc_tests, inc_drm],
+ link_with : [libdrm, libutil],
+ install : with_install_tests,
+)
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
new file mode 100644
index 0000000..1c2b519
--- /dev/null
+++ b/tests/vbltest/vbltest.c
@@ -0,0 +1,186 @@
+/*
+ * DRM based vblank test program
+ * Copyright 2008 Tungsten Graphics
+ * Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <poll.h>
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "util/common.h"
+#include "util/kms.h"
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "D:M:s";
+
+int secondary = 0;
+
+struct vbl_info {
+ unsigned int vbl_count;
+ struct timeval start;
+};
+
+static void vblank_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *data)
+{
+ drmVBlank vbl;
+ struct timeval end;
+ struct vbl_info *info = data;
+ double t;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ if (secondary)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 1;
+ vbl.request.signal = (unsigned long)data;
+
+ drmWaitVBlank(fd, &vbl);
+
+ info->vbl_count++;
+
+ if (info->vbl_count == 60) {
+ gettimeofday(&end, NULL);
+ t = end.tv_sec + end.tv_usec * 1e-6 -
+ (info->start.tv_sec + info->start.tv_usec * 1e-6);
+ fprintf(stderr, "freq: %.02fHz\n", info->vbl_count / t);
+ info->vbl_count = 0;
+ info->start = end;
+ }
+}
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-DMs]\n", name);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -D DEVICE open the given device\n");
+ fprintf(stderr, " -M MODULE open the given module\n");
+ fprintf(stderr, " -s use secondary pipe\n");
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ const char *device = NULL, *module = NULL;
+ int c, fd, ret;
+ drmVBlank vbl;
+ drmEventContext evctx;
+ struct vbl_info handler_info;
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'D':
+ device = optarg;
+ break;
+ case 'M':
+ module = optarg;
+ break;
+ case 's':
+ secondary = 1;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ fd = util_open(device, module);
+ if (fd < 0)
+ return 1;
+
+ /* Get current count first */
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if (secondary)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ ret = drmWaitVBlank(fd, &vbl);
+ if (ret != 0) {
+ printf("drmWaitVBlank (relative) failed ret: %i\n", ret);
+ return -1;
+ }
+
+ printf("starting count: %d\n", vbl.request.sequence);
+
+ handler_info.vbl_count = 0;
+ gettimeofday(&handler_info.start, NULL);
+
+ /* Queue an event for frame + 1 */
+ vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ if (secondary)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 1;
+ vbl.request.signal = (unsigned long)&handler_info;
+ ret = drmWaitVBlank(fd, &vbl);
+ if (ret != 0) {
+ printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret);
+ return -1;
+ }
+
+ /* Set up our event handler */
+ memset(&evctx, 0, sizeof evctx);
+ evctx.version = DRM_EVENT_CONTEXT_VERSION;
+ evctx.vblank_handler = vblank_handler;
+ evctx.page_flip_handler = NULL;
+
+ /* Poll for events */
+ while (1) {
+ struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ FD_SET(fd, &fds);
+ ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+
+ if (ret <= 0) {
+ fprintf(stderr, "select timed out or error (ret %d)\n",
+ ret);
+ continue;
+ } else if (FD_ISSET(0, &fds)) {
+ break;
+ }
+
+ ret = drmHandleEvent(fd, &evctx);
+ if (ret != 0) {
+ printf("drmHandleEvent failed: %i\n", ret);
+ return -1;
+ }
+ }
+
+ return 0;
+}