All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH libdrm 00/25] Update Tegra support
@ 2021-08-27 13:22 Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 01/25] tegra: Indent according to .editorconfig Thierry Reding
                   ` (25 more replies)
  0 siblings, 26 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Hi all,

this is the userspace part of the kernel patches that were recently
merged into drm-next:

  https://patchwork.freedesktop.org/series/92378/

The goal is to provide a userspace implementation of the UAPI exposed by
the kernel and show its usage in some test programs that can also be
used for basic sanity testing. More complete userspace implementations
are available here:

  * https://github.com/cyndis/vaapi-tegra-driver
  * https://github.com/grate-driver/xf86-video-opentegra
  * https://github.com/grate-driver/grate

Thierry

Thierry Reding (25):
  tegra: Indent according to .editorconfig
  tegra: Remove unused IOCTL implementations
  tegra: Extract common buffer object allocation code
  tegra: Fix mmap() of GEM buffer objects
  tegra: Add flink helpers
  tegra: Add PRIME support helpers
  tegra: Make API more consistent
  tegra: Install tegra-openclose test
  tegra: Update for new UABI
  tegra: Include private.h in list of source files
  tegra: Add channel APIs
  tegra: Add job and push buffer APIs
  tegra: Add syncpoint APIs
  tests: tegra: Add helper library for tests
  tests: tegra: Add gr2d-fill test
  tests: tegra: Add syncpt-wait test
  tests: tegra: Add syncpoint timeout test
  tests: tegra: Add VIC support
  tests: tegra: Add VIC 3.0 support
  tests: tegra: Add VIC 4.0 support
  tests: tegra: Add VIC 4.1 support
  tests: tegra: Add VIC 4.2 support
  tests: tegra: Add VIC clear test
  tests: tegra: Add VIC blit test
  tests: tegra: Add VIC flip test

 include/drm/tegra_drm.h      | 429 +++++++++++++++++++++++--
 tegra/channel.c              | 195 ++++++++++++
 tegra/job.c                  | 187 +++++++++++
 tegra/meson.build            |   7 +-
 tegra/private.h              |  85 ++++-
 tegra/pushbuf.c              | 184 +++++++++++
 tegra/syncpt.c               | 101 ++++++
 tegra/tegra-symbols.txt      |  27 +-
 tegra/tegra.c                | 392 ++++++++++++-----------
 tegra/tegra.h                |  95 +++++-
 tests/tegra/.gitignore       |   3 +-
 tests/tegra/drm-test-tegra.c | 147 +++++++++
 tests/tegra/drm-test-tegra.h |  55 ++++
 tests/tegra/drm-test.c       | 248 +++++++++++++++
 tests/tegra/drm-test.h       |  72 +++++
 tests/tegra/gr2d-fill.c      | 146 +++++++++
 tests/tegra/host1x.h         |  34 ++
 tests/tegra/meson.build      |  88 +++++-
 tests/tegra/openclose.c      |  52 +--
 tests/tegra/syncpt-timeout.c | 163 ++++++++++
 tests/tegra/syncpt-wait.c    | 151 +++++++++
 tests/tegra/vic-blit.c       | 333 +++++++++++++++++++
 tests/tegra/vic-clear.c      | 173 ++++++++++
 tests/tegra/vic-flip.c       | 333 +++++++++++++++++++
 tests/tegra/vic.c            | 177 +++++++++++
 tests/tegra/vic.h            | 181 +++++++++++
 tests/tegra/vic30.c          | 509 +++++++++++++++++++++++++++++
 tests/tegra/vic30.h          | 439 ++++++++++++++++++++++++++
 tests/tegra/vic40.c          | 412 ++++++++++++++++++++++++
 tests/tegra/vic40.h          | 285 +++++++++++++++++
 tests/tegra/vic41.c          | 416 ++++++++++++++++++++++++
 tests/tegra/vic41.h          | 372 ++++++++++++++++++++++
 tests/tegra/vic42.c          | 423 +++++++++++++++++++++++++
 tests/tegra/vic42.h          | 597 +++++++++++++++++++++++++++++++++++
 34 files changed, 7248 insertions(+), 263 deletions(-)
 create mode 100644 tegra/channel.c
 create mode 100644 tegra/job.c
 create mode 100644 tegra/pushbuf.c
 create mode 100644 tegra/syncpt.c
 create mode 100644 tests/tegra/drm-test-tegra.c
 create mode 100644 tests/tegra/drm-test-tegra.h
 create mode 100644 tests/tegra/drm-test.c
 create mode 100644 tests/tegra/drm-test.h
 create mode 100644 tests/tegra/gr2d-fill.c
 create mode 100644 tests/tegra/host1x.h
 create mode 100644 tests/tegra/syncpt-timeout.c
 create mode 100644 tests/tegra/syncpt-wait.c
 create mode 100644 tests/tegra/vic-blit.c
 create mode 100644 tests/tegra/vic-clear.c
 create mode 100644 tests/tegra/vic-flip.c
 create mode 100644 tests/tegra/vic.c
 create mode 100644 tests/tegra/vic.h
 create mode 100644 tests/tegra/vic30.c
 create mode 100644 tests/tegra/vic30.h
 create mode 100644 tests/tegra/vic40.c
 create mode 100644 tests/tegra/vic40.h
 create mode 100644 tests/tegra/vic41.c
 create mode 100644 tests/tegra/vic41.h
 create mode 100644 tests/tegra/vic42.c
 create mode 100644 tests/tegra/vic42.h

-- 
2.32.0


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH libdrm 01/25] tegra: Indent according to .editorconfig
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 02/25] tegra: Remove unused IOCTL implementations Thierry Reding
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Reindent the sources according to the settings found in the newly added
.editorconfig.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/private.h         |  18 +-
 tegra/tegra.c           | 354 ++++++++++++++++++++--------------------
 tegra/tegra.h           |  12 +-
 tests/tegra/openclose.c |  52 +++---
 4 files changed, 220 insertions(+), 216 deletions(-)

diff --git a/tegra/private.h b/tegra/private.h
index bb6c1a516530..215dd3309bce 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -34,18 +34,18 @@
 #include "tegra.h"
 
 struct drm_tegra {
-	bool close;
-	int fd;
+    bool close;
+    int fd;
 };
 
 struct drm_tegra_bo {
-	struct drm_tegra *drm;
-	uint32_t handle;
-	uint32_t offset;
-	uint32_t flags;
-	uint32_t size;
-	atomic_t ref;
-	void *map;
+    struct drm_tegra *drm;
+    uint32_t handle;
+    uint32_t offset;
+    uint32_t flags;
+    uint32_t size;
+    atomic_t ref;
+    void *map;
 };
 
 #endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/tegra.c b/tegra/tegra.c
index cf00a3cac6d8..3caf0bc4e65e 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -37,292 +37,296 @@
 
 static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
 {
-	struct drm_tegra *drm = bo->drm;
-	struct drm_gem_close args;
+    struct drm_tegra *drm = bo->drm;
+    struct drm_gem_close args;
 
-	if (bo->map)
-		munmap(bo->map, bo->size);
+    if (bo->map)
+        munmap(bo->map, bo->size);
 
-	memset(&args, 0, sizeof(args));
-	args.handle = bo->handle;
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
 
-	drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
+    drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
 
-	free(bo);
+    free(bo);
 }
 
 static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
 {
-	struct drm_tegra *drm;
+    struct drm_tegra *drm;
 
-	if (fd < 0 || !drmp)
-		return -EINVAL;
+    if (fd < 0 || !drmp)
+        return -EINVAL;
 
-	drm = calloc(1, sizeof(*drm));
-	if (!drm)
-		return -ENOMEM;
+    drm = calloc(1, sizeof(*drm));
+    if (!drm)
+        return -ENOMEM;
 
-	drm->close = close;
-	drm->fd = fd;
+    drm->close = close;
+    drm->fd = fd;
 
-	*drmp = drm;
+    *drmp = drm;
 
-	return 0;
+    return 0;
 }
 
 drm_public int drm_tegra_new(struct drm_tegra **drmp, int fd)
 {
-	bool supported = false;
-	drmVersionPtr version;
+    bool supported = false;
+    drmVersionPtr version;
 
-	version = drmGetVersion(fd);
-	if (!version)
-		return -ENOMEM;
+    version = drmGetVersion(fd);
+    if (!version)
+        return -ENOMEM;
 
-	if (!strncmp(version->name, "tegra", version->name_len))
-		supported = true;
+    if (!strncmp(version->name, "tegra", version->name_len))
+        supported = true;
 
-	drmFreeVersion(version);
+    drmFreeVersion(version);
 
-	if (!supported)
-		return -ENOTSUP;
+    if (!supported)
+        return -ENOTSUP;
 
-	return drm_tegra_wrap(drmp, fd, false);
+    return drm_tegra_wrap(drmp, fd, false);
 }
 
 drm_public void drm_tegra_close(struct drm_tegra *drm)
 {
-	if (!drm)
-		return;
+    if (!drm)
+        return;
 
-	if (drm->close)
-		close(drm->fd);
+    if (drm->close)
+        close(drm->fd);
 
-	free(drm);
+    free(drm);
 }
 
-drm_public int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-		     uint32_t flags, uint32_t size)
+drm_public int
+drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+                 uint32_t flags, uint32_t size)
 {
-	struct drm_tegra_gem_create args;
-	struct drm_tegra_bo *bo;
-	int err;
+    struct drm_tegra_gem_create args;
+    struct drm_tegra_bo *bo;
+    int err;
 
-	if (!drm || size == 0 || !bop)
-		return -EINVAL;
+    if (!drm || size == 0 || !bop)
+        return -EINVAL;
 
-	bo = calloc(1, sizeof(*bo));
-	if (!bo)
-		return -ENOMEM;
+    bo = calloc(1, sizeof(*bo));
+    if (!bo)
+        return -ENOMEM;
 
-	atomic_set(&bo->ref, 1);
-	bo->flags = flags;
-	bo->size = size;
-	bo->drm = drm;
+    atomic_set(&bo->ref, 1);
+    bo->flags = flags;
+    bo->size = size;
+    bo->drm = drm;
 
-	memset(&args, 0, sizeof(args));
-	args.flags = flags;
-	args.size = size;
+    memset(&args, 0, sizeof(args));
+    args.flags = flags;
+    args.size = size;
 
-	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
-				  sizeof(args));
-	if (err < 0) {
-		err = -errno;
-		free(bo);
-		return err;
-	}
+    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
+                              sizeof(args));
+    if (err < 0) {
+        err = -errno;
+        free(bo);
+        return err;
+    }
 
-	bo->handle = args.handle;
+    bo->handle = args.handle;
 
-	*bop = bo;
+    *bop = bo;
 
-	return 0;
+    return 0;
 }
 
-drm_public int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-		      uint32_t handle, uint32_t flags, uint32_t size)
+drm_public int
+drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+                  uint32_t handle, uint32_t flags, uint32_t size)
 {
-	struct drm_tegra_bo *bo;
+    struct drm_tegra_bo *bo;
 
-	if (!drm || !bop)
-		return -EINVAL;
+    if (!drm || !bop)
+        return -EINVAL;
 
-	bo = calloc(1, sizeof(*bo));
-	if (!bo)
-		return -ENOMEM;
+    bo = calloc(1, sizeof(*bo));
+    if (!bo)
+        return -ENOMEM;
 
-	atomic_set(&bo->ref, 1);
-	bo->handle = handle;
-	bo->flags = flags;
-	bo->size = size;
-	bo->drm = drm;
+    atomic_set(&bo->ref, 1);
+    bo->handle = handle;
+    bo->flags = flags;
+    bo->size = size;
+    bo->drm = drm;
 
-	*bop = bo;
+    *bop = bo;
 
-	return 0;
+    return 0;
 }
 
 drm_public struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
 {
-	if (bo)
-		atomic_inc(&bo->ref);
+    if (bo)
+        atomic_inc(&bo->ref);
 
-	return bo;
+    return bo;
 }
 
 drm_public void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
 {
-	if (bo && atomic_dec_and_test(&bo->ref))
-		drm_tegra_bo_free(bo);
+    if (bo && atomic_dec_and_test(&bo->ref))
+        drm_tegra_bo_free(bo);
 }
 
 drm_public int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
 {
-	if (!bo || !handle)
-		return -EINVAL;
+    if (!bo || !handle)
+        return -EINVAL;
 
-	*handle = bo->handle;
+    *handle = bo->handle;
 
-	return 0;
+    return 0;
 }
 
 drm_public int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
 {
-	struct drm_tegra *drm = bo->drm;
+    struct drm_tegra *drm = bo->drm;
 
-	if (!bo->map) {
-		struct drm_tegra_gem_mmap args;
-		int err;
+    if (!bo->map) {
+        struct drm_tegra_gem_mmap args;
+        int err;
 
-		memset(&args, 0, sizeof(args));
-		args.handle = bo->handle;
+        memset(&args, 0, sizeof(args));
+        args.handle = bo->handle;
 
-		err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
-					  sizeof(args));
-		if (err < 0)
-			return -errno;
+        err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
+                                  sizeof(args));
+        if (err < 0)
+            return -errno;
 
-		bo->offset = args.offset;
+        bo->offset = args.offset;
 
-		bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
-			       drm->fd, bo->offset);
-		if (bo->map == MAP_FAILED) {
-			bo->map = NULL;
-			return -errno;
-		}
-	}
+        bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                       drm->fd, bo->offset);
+        if (bo->map == MAP_FAILED) {
+            bo->map = NULL;
+            return -errno;
+        }
+    }
 
-	if (ptr)
-		*ptr = bo->map;
+    if (ptr)
+        *ptr = bo->map;
 
-	return 0;
+    return 0;
 }
 
 drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
 {
-	if (!bo)
-		return -EINVAL;
+    if (!bo)
+        return -EINVAL;
 
-	if (!bo->map)
-		return 0;
+    if (!bo->map)
+        return 0;
 
-	if (munmap(bo->map, bo->size))
-		return -errno;
+    if (munmap(bo->map, bo->size))
+        return -errno;
 
-	bo->map = NULL;
+    bo->map = NULL;
 
-	return 0;
+    return 0;
 }
 
 drm_public int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags)
 {
-	struct drm_tegra_gem_get_flags args;
-	struct drm_tegra *drm = bo->drm;
-	int err;
+    struct drm_tegra_gem_get_flags args;
+    struct drm_tegra *drm = bo->drm;
+    int err;
 
-	if (!bo)
-		return -EINVAL;
+    if (!bo)
+        return -EINVAL;
 
-	memset(&args, 0, sizeof(args));
-	args.handle = bo->handle;
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
 
-	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
-				  sizeof(args));
-	if (err < 0)
-		return -errno;
+    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
+                              sizeof(args));
+    if (err < 0)
+        return -errno;
 
-	if (flags)
-		*flags = args.flags;
+    if (flags)
+        *flags = args.flags;
 
-	return 0;
+    return 0;
 }
 
 drm_public int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags)
 {
-	struct drm_tegra_gem_get_flags args;
-	struct drm_tegra *drm = bo->drm;
-	int err;
+    struct drm_tegra_gem_get_flags args;
+    struct drm_tegra *drm = bo->drm;
+    int err;
 
-	if (!bo)
-		return -EINVAL;
+    if (!bo)
+        return -EINVAL;
 
-	memset(&args, 0, sizeof(args));
-	args.handle = bo->handle;
-	args.flags = flags;
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
+    args.flags = flags;
 
-	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
-				  sizeof(args));
-	if (err < 0)
-		return -errno;
+    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
+                              sizeof(args));
+    if (err < 0)
+        return -errno;
 
-	return 0;
+    return 0;
 }
 
-drm_public int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
-			    struct drm_tegra_bo_tiling *tiling)
+drm_public int
+drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
+                        struct drm_tegra_bo_tiling *tiling)
 {
-	struct drm_tegra_gem_get_tiling args;
-	struct drm_tegra *drm = bo->drm;
-	int err;
+    struct drm_tegra_gem_get_tiling args;
+    struct drm_tegra *drm = bo->drm;
+    int err;
 
-	if (!bo)
-		return -EINVAL;
+    if (!bo)
+        return -EINVAL;
 
-	memset(&args, 0, sizeof(args));
-	args.handle = bo->handle;
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
 
-	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
-				  sizeof(args));
-	if (err < 0)
-		return -errno;
+    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
+                              sizeof(args));
+    if (err < 0)
+        return -errno;
 
-	if (tiling) {
-		tiling->mode = args.mode;
-		tiling->value = args.value;
-	}
+    if (tiling) {
+        tiling->mode = args.mode;
+        tiling->value = args.value;
+    }
 
-	return 0;
+    return 0;
 }
 
-drm_public int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
-			    const struct drm_tegra_bo_tiling *tiling)
+drm_public int
+drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
+                        const struct drm_tegra_bo_tiling *tiling)
 {
-	struct drm_tegra_gem_set_tiling args;
-	struct drm_tegra *drm = bo->drm;
-	int err;
+    struct drm_tegra_gem_set_tiling args;
+    struct drm_tegra *drm = bo->drm;
+    int err;
 
-	if (!bo)
-		return -EINVAL;
+    if (!bo)
+        return -EINVAL;
 
-	memset(&args, 0, sizeof(args));
-	args.handle = bo->handle;
-	args.mode = tiling->mode;
-	args.value = tiling->value;
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
+    args.mode = tiling->mode;
+    args.value = tiling->value;
 
-	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
-				  sizeof(args));
-	if (err < 0)
-		return -errno;
+    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
+                              sizeof(args));
+    if (err < 0)
+        return -errno;
 
-	return 0;
+    return 0;
 }
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 31b0995ad691..62205a5174b4 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -35,9 +35,9 @@ int drm_tegra_new(struct drm_tegra **drmp, int fd);
 void drm_tegra_close(struct drm_tegra *drm);
 
 int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-		     uint32_t flags, uint32_t size);
+                     uint32_t flags, uint32_t size);
 int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-		      uint32_t handle, uint32_t flags, uint32_t size);
+                      uint32_t handle, uint32_t flags, uint32_t size);
 struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo);
 void drm_tegra_bo_unref(struct drm_tegra_bo *bo);
 int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
@@ -48,13 +48,13 @@ int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags);
 int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags);
 
 struct drm_tegra_bo_tiling {
-	uint32_t mode;
-	uint32_t value;
+    uint32_t mode;
+    uint32_t value;
 };
 
 int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
-			    struct drm_tegra_bo_tiling *tiling);
+                            struct drm_tegra_bo_tiling *tiling);
 int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
-			    const struct drm_tegra_bo_tiling *tiling);
+                            const struct drm_tegra_bo_tiling *tiling);
 
 #endif /* __DRM_TEGRA_H__ */
diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c
index f80f52d477ee..104e83806f3a 100644
--- a/tests/tegra/openclose.c
+++ b/tests/tegra/openclose.c
@@ -31,37 +31,37 @@ 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;
+    struct drm_tegra *tegra;
+    drmVersionPtr version;
+    const char *device;
+    int err, fd;
 
-	if (argc < 2)
-		device = default_device;
-	else
-		device = argv[1];
+    if (argc < 2)
+        device = default_device;
+    else
+        device = argv[1];
 
-	fd = open(device, O_RDWR);
-	if (fd < 0)
-		return 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);
+    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);
-	}
+        drmFreeVersion(version);
+    }
 
-	err = drm_tegra_new(&tegra, fd);
-	if (err < 0)
-		return 1;
+    err = drm_tegra_new(&tegra, fd);
+    if (err < 0)
+        return 1;
 
-	drm_tegra_close(tegra);
-	close(fd);
+    drm_tegra_close(tegra);
+    close(fd);
 
-	return 0;
+    return 0;
 }
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 02/25] tegra: Remove unused IOCTL implementations
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 01/25] tegra: Indent according to .editorconfig Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 03/25] tegra: Extract common buffer object allocation code Thierry Reding
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

The DRM_TEGRA_GEM_{GET,SET}_FLAGS and DRM_TEGRA_GEM_{GET,SET}_TILING
IOCTLs were badly designed and have since been obsoleted by framebuffer
modifiers. Remove these implementations to make it clear their usage is
discouraged.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/tegra-symbols.txt |  4 --
 tegra/tegra.c           | 95 -----------------------------------------
 tegra/tegra.h           | 12 ------
 3 files changed, 111 deletions(-)

diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index 5e3e955f2901..9422696c1416 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -1,11 +1,7 @@
-drm_tegra_bo_get_flags
 drm_tegra_bo_get_handle
-drm_tegra_bo_get_tiling
 drm_tegra_bo_map
 drm_tegra_bo_new
 drm_tegra_bo_ref
-drm_tegra_bo_set_flags
-drm_tegra_bo_set_tiling
 drm_tegra_bo_unmap
 drm_tegra_bo_unref
 drm_tegra_bo_wrap
diff --git a/tegra/tegra.c b/tegra/tegra.c
index 3caf0bc4e65e..94840ad42795 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -235,98 +235,3 @@ drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
 
     return 0;
 }
-
-drm_public int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags)
-{
-    struct drm_tegra_gem_get_flags args;
-    struct drm_tegra *drm = bo->drm;
-    int err;
-
-    if (!bo)
-        return -EINVAL;
-
-    memset(&args, 0, sizeof(args));
-    args.handle = bo->handle;
-
-    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
-                              sizeof(args));
-    if (err < 0)
-        return -errno;
-
-    if (flags)
-        *flags = args.flags;
-
-    return 0;
-}
-
-drm_public int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags)
-{
-    struct drm_tegra_gem_get_flags args;
-    struct drm_tegra *drm = bo->drm;
-    int err;
-
-    if (!bo)
-        return -EINVAL;
-
-    memset(&args, 0, sizeof(args));
-    args.handle = bo->handle;
-    args.flags = flags;
-
-    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
-                              sizeof(args));
-    if (err < 0)
-        return -errno;
-
-    return 0;
-}
-
-drm_public int
-drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
-                        struct drm_tegra_bo_tiling *tiling)
-{
-    struct drm_tegra_gem_get_tiling args;
-    struct drm_tegra *drm = bo->drm;
-    int err;
-
-    if (!bo)
-        return -EINVAL;
-
-    memset(&args, 0, sizeof(args));
-    args.handle = bo->handle;
-
-    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
-                              sizeof(args));
-    if (err < 0)
-        return -errno;
-
-    if (tiling) {
-        tiling->mode = args.mode;
-        tiling->value = args.value;
-    }
-
-    return 0;
-}
-
-drm_public int
-drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
-                        const struct drm_tegra_bo_tiling *tiling)
-{
-    struct drm_tegra_gem_set_tiling args;
-    struct drm_tegra *drm = bo->drm;
-    int err;
-
-    if (!bo)
-        return -EINVAL;
-
-    memset(&args, 0, sizeof(args));
-    args.handle = bo->handle;
-    args.mode = tiling->mode;
-    args.value = tiling->value;
-
-    err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
-                              sizeof(args));
-    if (err < 0)
-        return -errno;
-
-    return 0;
-}
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 62205a5174b4..c6b4f984de45 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -44,17 +44,5 @@ int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
 int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr);
 int drm_tegra_bo_unmap(struct drm_tegra_bo *bo);
 
-int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags);
-int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags);
-
-struct drm_tegra_bo_tiling {
-    uint32_t mode;
-    uint32_t value;
-};
-
-int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
-                            struct drm_tegra_bo_tiling *tiling);
-int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
-                            const struct drm_tegra_bo_tiling *tiling);
 
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 03/25] tegra: Extract common buffer object allocation code
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 01/25] tegra: Indent according to .editorconfig Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 02/25] tegra: Remove unused IOCTL implementations Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 04/25] tegra: Fix mmap() of GEM buffer objects Thierry Reding
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

All of the buffer object allocation functions use the same boilerplate
code. Move that code into a separate function that can be reused.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/tegra.c | 35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/tegra/tegra.c b/tegra/tegra.c
index 94840ad42795..bf8e5c9213ca 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -101,6 +101,26 @@ drm_public void drm_tegra_close(struct drm_tegra *drm)
     free(drm);
 }
 
+static struct drm_tegra_bo *drm_tegra_bo_alloc(struct drm_tegra *drm,
+                                               uint32_t handle,
+                                               uint32_t flags,
+                                               uint32_t size)
+{
+    struct drm_tegra_bo *bo;
+
+    bo = calloc(1, sizeof(*bo));
+    if (!bo)
+        return NULL;
+
+    atomic_set(&bo->ref, 1);
+    bo->handle = handle;
+    bo->flags = flags;
+    bo->size = size;
+    bo->drm = drm;
+
+    return bo;
+}
+
 drm_public int
 drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
                  uint32_t flags, uint32_t size)
@@ -112,15 +132,10 @@ drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
     if (!drm || size == 0 || !bop)
         return -EINVAL;
 
-    bo = calloc(1, sizeof(*bo));
+    bo = drm_tegra_bo_alloc(drm, 0, flags, size);
     if (!bo)
         return -ENOMEM;
 
-    atomic_set(&bo->ref, 1);
-    bo->flags = flags;
-    bo->size = size;
-    bo->drm = drm;
-
     memset(&args, 0, sizeof(args));
     args.flags = flags;
     args.size = size;
@@ -149,16 +164,10 @@ drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
     if (!drm || !bop)
         return -EINVAL;
 
-    bo = calloc(1, sizeof(*bo));
+    bo = drm_tegra_bo_alloc(drm, handle, flags, size);
     if (!bo)
         return -ENOMEM;
 
-    atomic_set(&bo->ref, 1);
-    bo->handle = handle;
-    bo->flags = flags;
-    bo->size = size;
-    bo->drm = drm;
-
     *bop = bo;
 
     return 0;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 04/25] tegra: Fix mmap() of GEM buffer objects
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (2 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 03/25] tegra: Extract common buffer object allocation code Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 05/25] tegra: Add flink helpers Thierry Reding
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Store 64-bit offset values and use libdrm's built-in drm_mmap() function
instead of mmap() to ensure the full 64-bit offset is used.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/private.h | 2 +-
 tegra/tegra.c   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tegra/private.h b/tegra/private.h
index 215dd3309bce..d0f2944bfb3a 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -41,7 +41,7 @@ struct drm_tegra {
 struct drm_tegra_bo {
     struct drm_tegra *drm;
     uint32_t handle;
-    uint32_t offset;
+    uint64_t offset;
     uint32_t flags;
     uint32_t size;
     atomic_t ref;
diff --git a/tegra/tegra.c b/tegra/tegra.c
index bf8e5c9213ca..5225ad052fb3 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -215,8 +215,8 @@ drm_public int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
 
         bo->offset = args.offset;
 
-        bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
-                       drm->fd, bo->offset);
+        bo->map = drm_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                           drm->fd, bo->offset);
         if (bo->map == MAP_FAILED) {
             bo->map = NULL;
             return -errno;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 05/25] tegra: Add flink helpers
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (3 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 04/25] tegra: Fix mmap() of GEM buffer objects Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 06/25] tegra: Add PRIME support helpers Thierry Reding
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Add helpers to export and import buffer objects via flink names.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- add drm_public annotations
---
 tegra/tegra-symbols.txt |  2 ++
 tegra/tegra.c           | 50 +++++++++++++++++++++++++++++++++++++++++
 tegra/tegra.h           |  3 +++
 3 files changed, 55 insertions(+)

diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index 9422696c1416..630e075fa5d7 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -1,6 +1,8 @@
 drm_tegra_bo_get_handle
+drm_tegra_bo_get_name
 drm_tegra_bo_map
 drm_tegra_bo_new
+drm_tegra_bo_open
 drm_tegra_bo_ref
 drm_tegra_bo_unmap
 drm_tegra_bo_unref
diff --git a/tegra/tegra.c b/tegra/tegra.c
index 5225ad052fb3..5eb8518104ef 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -244,3 +244,53 @@ drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
 
     return 0;
 }
+
+drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name)
+{
+    struct drm_tegra *drm = bo->drm;
+    struct drm_gem_flink args;
+    int err;
+
+    memset(&args, 0, sizeof(args));
+    args.handle = bo->handle;
+
+    err = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &args);
+    if (err < 0)
+        return err;
+
+    if (name)
+        *name = args.name;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags,
+                  struct drm_tegra_bo **bop)
+{
+    struct drm_gem_open args;
+    struct drm_tegra_bo *bo;
+    int err;
+
+    bo = drm_tegra_bo_alloc(drm, 0, flags, 0);
+    if (!bo)
+        return -ENOMEM;
+
+    memset(&args, 0, sizeof(args));
+    args.name = name;
+
+    err = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &args);
+    if (err < 0)
+        goto free;
+
+    bo->handle = args.handle;
+    bo->size = args.size;
+
+    *bop = bo;
+
+    return 0;
+
+free:
+    free(bo);
+    return err;
+}
diff --git a/tegra/tegra.h b/tegra/tegra.h
index c6b4f984de45..333690f23118 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -44,5 +44,8 @@ int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
 int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr);
 int drm_tegra_bo_unmap(struct drm_tegra_bo *bo);
 
+int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name);
+int drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags,
+                      struct drm_tegra_bo **bop);
 
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 06/25] tegra: Add PRIME support helpers
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (4 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 05/25] tegra: Add flink helpers Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 07/25] tegra: Make API more consistent Thierry Reding
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

These helpers facilitate exporting and importing buffer objects to and
from PRIME file descriptors.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v3:
- add drm_public annotations
---
 tegra/tegra-symbols.txt |  2 ++
 tegra/tegra.c           | 61 +++++++++++++++++++++++++++++++++++++++++
 tegra/tegra.h           |  4 +++
 3 files changed, 67 insertions(+)

diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index 630e075fa5d7..f8811bcd26f4 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -1,5 +1,7 @@
+drm_tegra_bo_export
 drm_tegra_bo_get_handle
 drm_tegra_bo_get_name
+drm_tegra_bo_import
 drm_tegra_bo_map
 drm_tegra_bo_new
 drm_tegra_bo_open
diff --git a/tegra/tegra.c b/tegra/tegra.c
index 5eb8518104ef..240600c3c496 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -294,3 +294,64 @@ free:
     free(bo);
     return err;
 }
+
+drm_public int drm_tegra_bo_export(struct drm_tegra_bo *bo, uint32_t flags)
+{
+    int fd, err;
+
+    flags |= DRM_CLOEXEC;
+
+    err = drmPrimeHandleToFD(bo->drm->fd, bo->handle, flags, &fd);
+    if (err < 0)
+        return err;
+
+    return fd;
+}
+
+static ssize_t fd_get_size(int fd)
+{
+    ssize_t size, offset;
+    int err;
+
+    offset = lseek(fd, 0, SEEK_CUR);
+    if (offset < 0)
+        return -errno;
+
+    size = lseek(fd, 0, SEEK_END);
+    if (size < 0)
+        return -errno;
+
+    err = lseek(fd, offset, SEEK_SET);
+    if (err < 0)
+        return -errno;
+
+    return size;
+}
+
+drm_public int
+drm_tegra_bo_import(struct drm_tegra *drm, int fd, struct drm_tegra_bo **bop)
+{
+    struct drm_tegra_bo *bo;
+    ssize_t size;
+    int err;
+
+    size = fd_get_size(fd);
+    if (size < 0)
+        return size;
+
+    bo = drm_tegra_bo_alloc(drm, 0, 0, size);
+    if (!bo)
+        return -ENOMEM;
+
+    err = drmPrimeFDToHandle(drm->fd, fd, &bo->handle);
+    if (err < 0)
+        goto free;
+
+    *bop = bo;
+
+    return 0;
+
+free:
+    free(bo);
+    return err;
+}
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 333690f23118..aaaf455fbc8e 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -48,4 +48,8 @@ int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name);
 int drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags,
                       struct drm_tegra_bo **bop);
 
+int drm_tegra_bo_export(struct drm_tegra_bo *bo, uint32_t flags);
+int drm_tegra_bo_import(struct drm_tegra *drm, int fd,
+                        struct drm_tegra_bo **bop);
+
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 07/25] tegra: Make API more consistent
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (5 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 06/25] tegra: Add PRIME support helpers Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 08/25] tegra: Install tegra-openclose test Thierry Reding
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Most functions in libdrm_tegra take as first parameter the object that
they operate on. Make the device and buffer object creation functions
follow the same scheme.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/tegra.c           | 13 +++++++------
 tegra/tegra.h           | 10 +++++-----
 tests/tegra/openclose.c |  2 +-
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/tegra/tegra.c b/tegra/tegra.c
index 240600c3c496..0020e9301bf3 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -70,7 +70,7 @@ static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
     return 0;
 }
 
-drm_public int drm_tegra_new(struct drm_tegra **drmp, int fd)
+drm_public int drm_tegra_new(int fd, struct drm_tegra **drmp)
 {
     bool supported = false;
     drmVersionPtr version;
@@ -122,8 +122,8 @@ static struct drm_tegra_bo *drm_tegra_bo_alloc(struct drm_tegra *drm,
 }
 
 drm_public int
-drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-                 uint32_t flags, uint32_t size)
+drm_tegra_bo_new(struct drm_tegra *drm, uint32_t flags, uint32_t size,
+                 struct drm_tegra_bo **bop)
 {
     struct drm_tegra_gem_create args;
     struct drm_tegra_bo *bo;
@@ -156,8 +156,8 @@ drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
 }
 
 drm_public int
-drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-                  uint32_t handle, uint32_t flags, uint32_t size)
+drm_tegra_bo_wrap(struct drm_tegra *drm, uint32_t handle, uint32_t flags,
+                  uint32_t size, struct drm_tegra_bo **bop)
 {
     struct drm_tegra_bo *bo;
 
@@ -187,7 +187,8 @@ drm_public void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
         drm_tegra_bo_free(bo);
 }
 
-drm_public int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
+drm_public int
+drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
 {
     if (!bo || !handle)
         return -EINVAL;
diff --git a/tegra/tegra.h b/tegra/tegra.h
index aaaf455fbc8e..2bcd596e2d61 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -31,13 +31,13 @@
 struct drm_tegra_bo;
 struct drm_tegra;
 
-int drm_tegra_new(struct drm_tegra **drmp, int fd);
+int drm_tegra_new(int fd, struct drm_tegra **drmp);
 void drm_tegra_close(struct drm_tegra *drm);
 
-int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-                     uint32_t flags, uint32_t size);
-int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
-                      uint32_t handle, uint32_t flags, uint32_t size);
+int drm_tegra_bo_new(struct drm_tegra *drm, uint32_t flags, uint32_t size,
+                     struct drm_tegra_bo **bop);
+int drm_tegra_bo_wrap(struct drm_tegra *drm, uint32_t handle, uint32_t flags,
+                      uint32_t size, struct drm_tegra_bo **bop);
 struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo);
 void drm_tegra_bo_unref(struct drm_tegra_bo *bo);
 int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c
index 104e83806f3a..61dbc2ba4f5f 100644
--- a/tests/tegra/openclose.c
+++ b/tests/tegra/openclose.c
@@ -56,7 +56,7 @@ int main(int argc, char *argv[])
         drmFreeVersion(version);
     }
 
-    err = drm_tegra_new(&tegra, fd);
+    err = drm_tegra_new(fd, &tegra);
     if (err < 0)
         return 1;
 
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 08/25] tegra: Install tegra-openclose test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (6 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 07/25] tegra: Make API more consistent Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 09/25] tegra: Update for new UABI Thierry Reding
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Allow this simple test to be installed so that it can easily be run on a
target device.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/.gitignore  | 2 +-
 tests/tegra/meson.build | 7 +++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/tests/tegra/.gitignore b/tests/tegra/.gitignore
index 5c5216c5c5e6..56cfb62b785f 100644
--- a/tests/tegra/.gitignore
+++ b/tests/tegra/.gitignore
@@ -1 +1 @@
-openclose
+tegra-openclose
diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index 4f8c54f41553..fbf4e6d8d4a3 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -18,10 +18,13 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 
+inc_tegra = include_directories('../../tegra')
+
 openclose = executable(
-  'openclose',
+  'tegra-openclose',
   files('openclose.c'),
-  include_directories : [inc_root, inc_drm, include_directories('../../tegra')],
+  include_directories : [inc_root, inc_drm, inc_tegra],
   c_args : libdrm_c_args,
   link_with : [libdrm, libdrm_tegra],
+  install : with_install_tests,
 )
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 09/25] tegra: Update for new UABI
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (7 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 08/25] tegra: Install tegra-openclose test Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 10/25] tegra: Include private.h in list of source files Thierry Reding
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This new UABI is a more modern version that works better with both old
and recent chips.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/drm/tegra_drm.h | 429 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 404 insertions(+), 25 deletions(-)

diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
index 6c07919c04e9..94cfc306d50a 100644
--- a/include/drm/tegra_drm.h
+++ b/include/drm/tegra_drm.h
@@ -1,27 +1,8 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION.  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 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.
- */
+/* SPDX-License-Identifier: MIT */
+/* Copyright (c) 2012-2020 NVIDIA Corporation */
 
-#ifndef _TEGRA_DRM_H_
-#define _TEGRA_DRM_H_
+#ifndef _UAPI_TEGRA_DRM_H_
+#define _UAPI_TEGRA_DRM_H_
 
 #include "drm.h"
 
@@ -29,6 +10,8 @@
 extern "C" {
 #endif
 
+/* Tegra DRM legacy UAPI. Only enabled with STAGING */
+
 #define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
 #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
 
@@ -649,8 +632,8 @@ struct drm_tegra_gem_get_flags {
 #define DRM_TEGRA_SYNCPT_READ		0x02
 #define DRM_TEGRA_SYNCPT_INCR		0x03
 #define DRM_TEGRA_SYNCPT_WAIT		0x04
-#define DRM_TEGRA_OPEN_CHANNEL		0x05
-#define DRM_TEGRA_CLOSE_CHANNEL		0x06
+#define DRM_TEGRA_OPEN_CHANNEL	        0x05
+#define DRM_TEGRA_CLOSE_CHANNEL	        0x06
 #define DRM_TEGRA_GET_SYNCPT		0x07
 #define DRM_TEGRA_SUBMIT		0x08
 #define DRM_TEGRA_GET_SYNCPT_BASE	0x09
@@ -674,6 +657,402 @@ struct drm_tegra_gem_get_flags {
 #define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
 #define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
 
+/* New Tegra DRM UAPI */
+
+/*
+ * Reported by the driver in the `capabilities` field.
+ *
+ * DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT: If set, the engine is cache coherent
+ * with regard to the system memory.
+ */
+#define DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT (1 << 0)
+
+struct drm_tegra_channel_open {
+	/**
+	 * @host1x_class: [in]
+	 *
+	 * Host1x class of the engine that will be programmed using this
+	 * channel.
+	 */
+	__u32 host1x_class;
+
+	/**
+	 * @flags: [in]
+	 *
+	 * Flags.
+	 */
+	__u32 flags;
+
+	/**
+	 * @context: [out]
+	 *
+	 * Opaque identifier corresponding to the opened channel.
+	 */
+	__u32 context;
+
+	/**
+	 * @version: [out]
+	 *
+	 * Version of the engine hardware. This can be used by userspace
+	 * to determine how the engine needs to be programmed.
+	 */
+	__u32 version;
+
+	/**
+	 * @capabilities: [out]
+	 *
+	 * Flags describing the hardware capabilities.
+	 */
+	__u32 capabilities;
+	__u32 padding;
+};
+
+struct drm_tegra_channel_close {
+	/**
+	 * @context: [in]
+	 *
+	 * Identifier of the channel to close.
+	 */
+	__u32 context;
+	__u32 padding;
+};
+
+/*
+ * Mapping flags that can be used to influence how the mapping is created.
+ *
+ * DRM_TEGRA_CHANNEL_MAP_READ: create mapping that allows HW read access
+ * DRM_TEGRA_CHANNEL_MAP_WRITE: create mapping that allows HW write access
+ */
+#define DRM_TEGRA_CHANNEL_MAP_READ  (1 << 0)
+#define DRM_TEGRA_CHANNEL_MAP_WRITE (1 << 1)
+#define DRM_TEGRA_CHANNEL_MAP_READ_WRITE (DRM_TEGRA_CHANNEL_MAP_READ | \
+					  DRM_TEGRA_CHANNEL_MAP_WRITE)
+
+struct drm_tegra_channel_map {
+	/**
+	 * @context: [in]
+	 *
+	 * Identifier of the channel to which make memory available for.
+	 */
+	__u32 context;
+
+	/**
+	 * @handle: [in]
+	 *
+	 * GEM handle of the memory to map.
+	 */
+	__u32 handle;
+
+	/**
+	 * @flags: [in]
+	 *
+	 * Flags.
+	 */
+	__u32 flags;
+
+	/**
+	 * @mapping: [out]
+	 *
+	 * Identifier corresponding to the mapping, to be used for
+	 * relocations or unmapping later.
+	 */
+	__u32 mapping;
+};
+
+struct drm_tegra_channel_unmap {
+	/**
+	 * @context: [in]
+	 *
+	 * Channel identifier of the channel to unmap memory from.
+	 */
+	__u32 context;
+
+	/**
+	 * @mapping: [in]
+	 *
+	 * Mapping identifier of the memory mapping to unmap.
+	 */
+	__u32 mapping;
+};
+
+/* Submission */
+
+/**
+ * Specify that bit 39 of the patched-in address should be set to switch
+ * swizzling between Tegra and non-Tegra sector layout on systems that store
+ * surfaces in system memory in non-Tegra sector layout.
+ */
+#define DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT (1 << 0)
+
+struct drm_tegra_submit_buf {
+	/**
+	 * @mapping: [in]
+	 *
+	 * Identifier of the mapping to use in the submission.
+	 */
+	__u32 mapping;
+
+	/**
+	 * @flags: [in]
+	 *
+	 * Flags.
+	 */
+	__u32 flags;
+
+	/**
+	 * Information for relocation patching.
+	 */
+	struct {
+		/**
+		 * @target_offset: [in]
+		 *
+		 * Offset from the start of the mapping of the data whose
+		 * address is to be patched into the gather.
+		 */
+		__u64 target_offset;
+
+		/**
+		 * @gather_offset_words: [in]
+		 *
+		 * Offset in words from the start of the gather data to
+		 * where the address should be patched into.
+		 */
+		__u32 gather_offset_words;
+
+		/**
+		 * @shift: [in]
+		 *
+		 * Number of bits the address should be shifted right before
+		 * patching in.
+		 */
+		__u32 shift;
+	} reloc;
+};
+
+/**
+ * Execute `words` words of Host1x opcodes specified in the `gather_data_ptr`
+ * buffer. Each GATHER_UPTR command uses successive words from the buffer.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR		0
+/**
+ * Wait for a syncpoint to reach a value before continuing with further
+ * commands.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT		1
+/**
+ * Wait for a syncpoint to reach a value before continuing with further
+ * commands. The threshold is calculated relative to the start of the job.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT_RELATIVE	2
+
+struct drm_tegra_submit_cmd_gather_uptr {
+	__u32 words;
+	__u32 reserved[3];
+};
+
+struct drm_tegra_submit_cmd_wait_syncpt {
+	__u32 id;
+	__u32 value;
+	__u32 reserved[2];
+};
+
+struct drm_tegra_submit_cmd {
+	/**
+	 * @type: [in]
+	 *
+	 * Command type to execute. One of the DRM_TEGRA_SUBMIT_CMD*
+	 * defines.
+	 */
+	__u32 type;
+
+	/**
+	 * @flags: [in]
+	 *
+	 * Flags.
+	 */
+	__u32 flags;
+
+	union {
+		struct drm_tegra_submit_cmd_gather_uptr gather_uptr;
+		struct drm_tegra_submit_cmd_wait_syncpt wait_syncpt;
+		__u32 reserved[4];
+	};
+};
+
+struct drm_tegra_submit_syncpt {
+	/**
+	 * @id: [in]
+	 *
+	 * ID of the syncpoint that the job will increment.
+	 */
+	__u32 id;
+
+	/**
+	 * @flags: [in]
+	 *
+	 * Flags.
+	 */
+	__u32 flags;
+
+	/**
+	 * @increments: [in]
+	 *
+	 * Number of times the job will increment this syncpoint.
+	 */
+	__u32 increments;
+
+	/**
+	 * @value: [out]
+	 *
+	 * Value the syncpoint will have once the job has completed all
+	 * its specified syncpoint increments.
+	 *
+	 * Note that the kernel may increment the syncpoint before or after
+	 * the job. These increments are not reflected in this field.
+	 *
+	 * If the job hangs or times out, not all of the increments may
+	 * get executed.
+	 */
+	__u32 value;
+};
+
+struct drm_tegra_channel_submit {
+	/**
+	 * @context: [in]
+	 *
+	 * Identifier of the channel to submit this job to.
+	 */
+	__u32 context;
+
+	/**
+	 * @num_bufs: [in]
+	 *
+	 * Number of elements in the `bufs_ptr` array.
+	 */
+	__u32 num_bufs;
+
+	/**
+	 * @num_cmds: [in]
+	 *
+	 * Number of elements in the `cmds_ptr` array.
+	 */
+	__u32 num_cmds;
+
+	/**
+	 * @gather_data_words: [in]
+	 *
+	 * Number of 32-bit words in the `gather_data_ptr` array.
+	 */
+	__u32 gather_data_words;
+
+	/**
+	 * @bufs_ptr: [in]
+	 *
+	 * Pointer to an array of drm_tegra_submit_buf structures.
+	 */
+	__u64 bufs_ptr;
+
+	/**
+	 * @cmds_ptr: [in]
+	 *
+	 * Pointer to an array of drm_tegra_submit_cmd structures.
+	 */
+	__u64 cmds_ptr;
+
+	/**
+	 * @gather_data_ptr: [in]
+	 *
+	 * Pointer to an array of Host1x opcodes to be used by GATHER_UPTR
+	 * commands.
+	 */
+	__u64 gather_data_ptr;
+
+	/**
+	 * @syncobj_in: [in]
+	 *
+	 * Handle for DRM syncobj that will be waited before submission.
+	 * Ignored if zero.
+	 */
+	__u32 syncobj_in;
+
+	/**
+	 * @syncobj_out: [in]
+	 *
+	 * Handle for DRM syncobj that will have its fence replaced with
+	 * the job's completion fence. Ignored if zero.
+	 */
+	__u32 syncobj_out;
+
+	/**
+	 * @syncpt_incr: [in,out]
+	 *
+	 * Information about the syncpoint the job will increment.
+	 */
+	struct drm_tegra_submit_syncpt syncpt;
+};
+
+struct drm_tegra_syncpoint_allocate {
+	/**
+	 * @id: [out]
+	 *
+	 * ID of allocated syncpoint.
+	 */
+	__u32 id;
+	__u32 padding;
+};
+
+struct drm_tegra_syncpoint_free {
+	/**
+	 * @id: [in]
+	 *
+	 * ID of syncpoint to free.
+	 */
+	__u32 id;
+	__u32 padding;
+};
+
+struct drm_tegra_syncpoint_wait {
+	/**
+	 * @timeout: [in]
+	 *
+	 * Absolute timestamp at which the wait will time out.
+	 */
+	__s64 timeout_ns;
+
+	/**
+	 * @id: [in]
+	 *
+	 * ID of syncpoint to wait on.
+	 */
+	__u32 id;
+
+	/**
+	 * @threshold: [in]
+	 *
+	 * Threshold to wait for.
+	 */
+	__u32 threshold;
+
+	/**
+	 * @value: [out]
+	 *
+	 * Value of the syncpoint upon wait completion.
+	 */
+	__u32 value;
+
+	__u32 padding;
+};
+
+#define DRM_IOCTL_TEGRA_CHANNEL_OPEN DRM_IOWR(DRM_COMMAND_BASE + 0x10, struct drm_tegra_channel_open)
+#define DRM_IOCTL_TEGRA_CHANNEL_CLOSE DRM_IOWR(DRM_COMMAND_BASE + 0x11, struct drm_tegra_channel_close)
+#define DRM_IOCTL_TEGRA_CHANNEL_MAP DRM_IOWR(DRM_COMMAND_BASE + 0x12, struct drm_tegra_channel_map)
+#define DRM_IOCTL_TEGRA_CHANNEL_UNMAP DRM_IOWR(DRM_COMMAND_BASE + 0x13, struct drm_tegra_channel_unmap)
+#define DRM_IOCTL_TEGRA_CHANNEL_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + 0x14, struct drm_tegra_channel_submit)
+
+#define DRM_IOCTL_TEGRA_SYNCPOINT_ALLOCATE DRM_IOWR(DRM_COMMAND_BASE + 0x20, struct drm_tegra_syncpoint_allocate)
+#define DRM_IOCTL_TEGRA_SYNCPOINT_FREE DRM_IOWR(DRM_COMMAND_BASE + 0x21, struct drm_tegra_syncpoint_free)
+#define DRM_IOCTL_TEGRA_SYNCPOINT_WAIT DRM_IOWR(DRM_COMMAND_BASE + 0x22, struct drm_tegra_syncpoint_wait)
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 10/25] tegra: Include private.h in list of source files
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (8 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 09/25] tegra: Update for new UABI Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 11/25] tegra: Add channel APIs Thierry Reding
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This makes sure that the proper dependencies are created and that the
file is distributed.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/meson.build | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tegra/meson.build b/tegra/meson.build
index edddf72bc0e7..9813d9baddac 100644
--- a/tegra/meson.build
+++ b/tegra/meson.build
@@ -20,7 +20,12 @@
 
 libdrm_tegra = library(
   'drm_tegra',
-  [files('tegra.c'), config_file],
+  [
+    files(
+      'private.h', 'tegra.c'
+    ),
+    config_file
+  ],
   include_directories : [inc_root, inc_drm],
   link_with : libdrm,
   dependencies : [dep_pthread_stubs, dep_atomic_ops],
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 11/25] tegra: Add channel APIs
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (9 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 10/25] tegra: Include private.h in list of source files Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 12/25] tegra: Add job and push buffer APIs Thierry Reding
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

These new functions can be used to open a channel to a given engine, map
and unmap buffer objects to that channel, and close the channel.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/channel.c         | 195 ++++++++++++++++++++++++++++++++++++++++
 tegra/meson.build       |   2 +-
 tegra/private.h         |  24 +++++
 tegra/tegra-symbols.txt |   5 ++
 tegra/tegra.h           |  22 +++++
 5 files changed, 247 insertions(+), 1 deletion(-)
 create mode 100644 tegra/channel.c

diff --git a/tegra/channel.c b/tegra/channel.c
new file mode 100644
index 000000000000..391362023259
--- /dev/null
+++ b/tegra/channel.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2012, 2013 Thierry Reding
+ * Copyright © 2013 Erik Faye-Lund
+ * Copyright © 2014-2021 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 <string.h>
+
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+drm_public int
+drm_tegra_channel_open(struct drm_tegra *drm,
+                       enum drm_tegra_class client,
+                       struct drm_tegra_channel **channelp)
+{
+    struct drm_tegra_channel_open args;
+    struct drm_tegra_channel *channel;
+    enum host1x_class class;
+    int err;
+
+    switch (client) {
+    case DRM_TEGRA_HOST1X:
+        class = HOST1X_CLASS_HOST1X;
+        break;
+
+    case DRM_TEGRA_GR2D:
+        class = HOST1X_CLASS_GR2D;
+        break;
+
+    case DRM_TEGRA_GR3D:
+        class = HOST1X_CLASS_GR3D;
+        break;
+
+    case DRM_TEGRA_VIC:
+        class = HOST1X_CLASS_VIC;
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    channel = calloc(1, sizeof(*channel));
+    if (!channel)
+        return -ENOMEM;
+
+    channel->drm = drm;
+
+    memset(&args, 0, sizeof(args));
+    args.host1x_class = class;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_OPEN, &args);
+    if (err < 0) {
+        free(channel);
+        return -errno;
+    }
+
+    channel->context = args.context;
+    channel->version = args.version;
+    channel->capabilities = args.capabilities;
+    channel->class = class;
+
+    switch (channel->version) {
+    case 0x20:
+    case 0x30:
+    case 0x35:
+    case 0x40:
+    case 0x21:
+        channel->cond_shift = 8;
+        break;
+
+    case 0x18:
+    case 0x19:
+        channel->cond_shift = 10;
+        break;
+
+    default:
+        return -ENOTSUP;
+    }
+
+    *channelp = channel;
+
+    return 0;
+}
+
+drm_public int drm_tegra_channel_close(struct drm_tegra_channel *channel)
+{
+    struct drm_tegra_channel_close args;
+    struct drm_tegra *drm;
+    int err;
+
+    if (!channel)
+        return -EINVAL;
+
+    drm = channel->drm;
+
+    memset(&args, 0, sizeof(args));
+    args.context = channel->context;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_CLOSE, &args);
+    if (err < 0)
+        return -errno;
+
+    free(channel);
+
+    return 0;
+}
+
+drm_public unsigned int
+drm_tegra_channel_get_version(struct drm_tegra_channel *channel)
+{
+    return channel->version;
+}
+
+drm_public int
+drm_tegra_channel_map(struct drm_tegra_channel *channel,
+                      struct drm_tegra_bo *bo, uint32_t flags,
+                      struct drm_tegra_mapping **mapp)
+{
+    struct drm_tegra *drm = channel->drm;
+    struct drm_tegra_channel_map args;
+    struct drm_tegra_mapping *map;
+    int err;
+
+    if (!drm || !bo || !mapp)
+        return -EINVAL;
+
+    map = calloc(1, sizeof(*map));
+    if (!map)
+        return -ENOMEM;
+
+    memset(&args, 0, sizeof(args));
+    args.context = channel->context;
+    args.handle = bo->handle;
+    args.flags = flags;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_MAP, &args);
+    if (err < 0) {
+        free(map);
+        return -errno;
+    }
+
+    map->channel = channel;
+    map->id = args.mapping;
+    *mapp = map;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_channel_unmap(struct drm_tegra_mapping *map)
+{
+    struct drm_tegra_channel *channel = map->channel;
+    struct drm_tegra *drm = channel->drm;
+    struct drm_tegra_channel_unmap args;
+    int err;
+
+    if (!channel || !map)
+        return -EINVAL;
+
+    memset(&args, 0, sizeof(args));
+    args.context = channel->context;
+    args.mapping = map->id;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_UNMAP, &args);
+    if (err < 0)
+        return -errno;
+
+    free(map);
+    return 0;
+}
diff --git a/tegra/meson.build b/tegra/meson.build
index 9813d9baddac..e115966fc8ed 100644
--- a/tegra/meson.build
+++ b/tegra/meson.build
@@ -22,7 +22,7 @@ libdrm_tegra = library(
   'drm_tegra',
   [
     files(
-      'private.h', 'tegra.c'
+      'channel.c', 'private.h', 'tegra.c'
     ),
     config_file
   ],
diff --git a/tegra/private.h b/tegra/private.h
index d0f2944bfb3a..7c05276707bf 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -31,8 +31,17 @@
 #include <libdrm_macros.h>
 #include <xf86atomic.h>
 
+#include "tegra_drm.h"
 #include "tegra.h"
 
+enum host1x_class {
+    HOST1X_CLASS_HOST1X = 0x01,
+    HOST1X_CLASS_GR2D = 0x51,
+    HOST1X_CLASS_GR2D_SB = 0x52,
+    HOST1X_CLASS_VIC = 0x5d,
+    HOST1X_CLASS_GR3D = 0x60,
+};
+
 struct drm_tegra {
     bool close;
     int fd;
@@ -48,4 +57,19 @@ struct drm_tegra_bo {
     void *map;
 };
 
+struct drm_tegra_channel {
+    struct drm_tegra *drm;
+    enum host1x_class class;
+    uint32_t capabilities;
+    unsigned int version;
+    uint64_t context;
+
+    unsigned int cond_shift;
+};
+
+struct drm_tegra_mapping {
+    struct drm_tegra_channel *channel;
+    uint32_t id;
+};
+
 #endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index f8811bcd26f4..c16a351171f1 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -9,5 +9,10 @@ drm_tegra_bo_ref
 drm_tegra_bo_unmap
 drm_tegra_bo_unref
 drm_tegra_bo_wrap
+drm_tegra_channel_close
+drm_tegra_channel_get_version
+drm_tegra_channel_map
+drm_tegra_channel_open
+drm_tegra_channel_unmap
 drm_tegra_close
 drm_tegra_new
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 2bcd596e2d61..621fef6b7000 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -28,6 +28,15 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include <tegra_drm.h>
+
+enum drm_tegra_class {
+    DRM_TEGRA_HOST1X,
+    DRM_TEGRA_GR2D,
+    DRM_TEGRA_GR3D,
+    DRM_TEGRA_VIC,
+};
+
 struct drm_tegra_bo;
 struct drm_tegra;
 
@@ -52,4 +61,17 @@ int drm_tegra_bo_export(struct drm_tegra_bo *bo, uint32_t flags);
 int drm_tegra_bo_import(struct drm_tegra *drm, int fd,
                         struct drm_tegra_bo **bop);
 
+struct drm_tegra_channel;
+struct drm_tegra_mapping;
+
+int drm_tegra_channel_open(struct drm_tegra *drm,
+                           enum drm_tegra_class client,
+                           struct drm_tegra_channel **channelp);
+int drm_tegra_channel_close(struct drm_tegra_channel *channel);
+unsigned int drm_tegra_channel_get_version(struct drm_tegra_channel *channel);
+int drm_tegra_channel_map(struct drm_tegra_channel *channel,
+                          struct drm_tegra_bo *bo, uint32_t flags,
+                          struct drm_tegra_mapping **mapp);
+int drm_tegra_channel_unmap(struct drm_tegra_mapping *map);
+
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 12/25] tegra: Add job and push buffer APIs
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (10 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 11/25] tegra: Add channel APIs Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 13/25] tegra: Add syncpoint APIs Thierry Reding
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

These new functions can be used to create a job on a given channel, add
commands to the job using its push buffer and submit the job.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/job.c             | 164 ++++++++++++++++++++++++++++++++++++++++
 tegra/meson.build       |   2 +-
 tegra/private.h         |  32 ++++++++
 tegra/pushbuf.c         | 136 +++++++++++++++++++++++++++++++++
 tegra/tegra-symbols.txt |   7 ++
 tegra/tegra.h           |  34 +++++++++
 6 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 tegra/job.c
 create mode 100644 tegra/pushbuf.c

diff --git a/tegra/job.c b/tegra/job.c
new file mode 100644
index 000000000000..c8c94e131ef0
--- /dev/null
+++ b/tegra/job.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2012, 2013 Thierry Reding
+ * Copyright © 2013 Erik Faye-Lund
+ * 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 <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include "private.h"
+
+struct drm_tegra_submit_cmd *
+drm_tegra_job_add_command(struct drm_tegra_job *job, uint32_t type,
+                          uint32_t flags)
+{
+    struct drm_tegra_submit_cmd *commands, *command;
+    size_t size;
+
+    size = (job->num_commands + 1) * sizeof(*commands);
+
+    commands = realloc(job->commands, size);
+    if (!commands)
+        return NULL;
+
+    command = &commands[job->num_commands];
+    memset(command, 0, sizeof(*command));
+    command->type = type;
+    command->flags = flags;
+
+    job->commands = commands;
+    job->num_commands++;
+
+    return command;
+}
+
+drm_public int
+drm_tegra_job_new(struct drm_tegra_channel *channel,
+                  struct drm_tegra_job **jobp)
+{
+    struct drm_tegra_job *job;
+
+    job = calloc(1, sizeof(*job));
+    if (!job)
+        return -ENOMEM;
+
+    job->page_size = sysconf(_SC_PAGESIZE);
+    job->channel = channel;
+
+    *jobp = job;
+
+    return 0;
+}
+
+drm_public int drm_tegra_job_free(struct drm_tegra_job *job)
+{
+    if (!job)
+        return -EINVAL;
+
+    if (job->pushbuf)
+        drm_tegra_pushbuf_free(job->pushbuf);
+
+    if (job->commands)
+        free(job->commands);
+
+    if (job->buffers)
+        free(job->buffers);
+
+    free(job);
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_job_get_pushbuf(struct drm_tegra_job *job,
+                          struct drm_tegra_pushbuf **pushbufp)
+{
+    struct drm_tegra_pushbuf *pushbuf;
+
+    if (!job->pushbuf) {
+        pushbuf = calloc(1, sizeof(*pushbuf));
+        if (!pushbuf)
+            return -ENOMEM;
+
+        pushbuf->job = job;
+
+        pushbuf->start = calloc(1, job->page_size);
+        if (!pushbuf->start) {
+            free(pushbuf);
+            return -ENOMEM;
+        }
+
+        pushbuf->end = pushbuf->start + job->page_size / 4;
+        pushbuf->ptr = pushbuf->start;
+
+        job->pushbuf = pushbuf;
+    }
+
+    *pushbufp = job->pushbuf;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_job_submit(struct drm_tegra_job *job, struct drm_tegra_fence *fence)
+{
+    struct drm_tegra_channel *channel = job->channel;
+    struct drm_tegra *drm = channel->drm;
+    struct drm_tegra_channel_submit args;
+    int err;
+
+    memset(&args, 0, sizeof(args));
+    args.context = channel->context;
+    args.num_bufs = job->num_buffers;
+    args.num_cmds = job->num_commands;
+    args.gather_data_words = job->pushbuf->ptr - job->pushbuf->start;
+    args.syncpt.id = job->syncpt.id;
+    args.syncpt.increments = job->syncpt.increments;
+
+    args.bufs_ptr = (uintptr_t)job->buffers;
+    args.cmds_ptr = (uintptr_t)job->commands;
+    args.gather_data_ptr = (uintptr_t)job->pushbuf->start;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_SUBMIT, &args);
+    if (err < 0)
+        return -errno;
+
+    job->syncpt.fence = args.syncpt.value;
+
+    if (fence) {
+        fence->drm = drm;
+        fence->syncpt = job->syncpt.id;
+        fence->value = job->syncpt.fence;
+    }
+
+    return 0;
+}
diff --git a/tegra/meson.build b/tegra/meson.build
index e115966fc8ed..38e43039837c 100644
--- a/tegra/meson.build
+++ b/tegra/meson.build
@@ -22,7 +22,7 @@ libdrm_tegra = library(
   'drm_tegra',
   [
     files(
-      'channel.c', 'private.h', 'tegra.c'
+      'channel.c', 'job.c', 'private.h', 'pushbuf.c', 'tegra.c'
     ),
     config_file
   ],
diff --git a/tegra/private.h b/tegra/private.h
index 7c05276707bf..970ee8ad66d4 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -72,4 +72,36 @@ struct drm_tegra_mapping {
     uint32_t id;
 };
 
+struct drm_tegra_pushbuf {
+    struct drm_tegra_job *job;
+
+    uint32_t *start;
+    uint32_t *end;
+    uint32_t *ptr;
+};
+
+void drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf);
+
+struct drm_tegra_job {
+    struct drm_tegra_channel *channel;
+    struct drm_tegra_pushbuf *pushbuf;
+    size_t page_size;
+
+    struct drm_tegra_submit_cmd *commands;
+    unsigned int num_commands;
+
+    struct drm_tegra_submit_buf *buffers;
+    unsigned int num_buffers;
+
+    struct {
+        uint32_t id;
+        uint32_t increments;
+        uint32_t fence;
+    } syncpt;
+};
+
+struct drm_tegra_submit_cmd *
+drm_tegra_job_add_command(struct drm_tegra_job *job, uint32_t type,
+                          uint32_t flags);
+
 #endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/pushbuf.c b/tegra/pushbuf.c
new file mode 100644
index 000000000000..380a50abbbb0
--- /dev/null
+++ b/tegra/pushbuf.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2012, 2013 Thierry Reding
+ * Copyright © 2013 Erik Faye-Lund
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "util_math.h"
+#include "private.h"
+
+#define HOST1X_OPCODE_NONINCR(offset, count) \
+    ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff))
+
+static inline unsigned int
+drm_tegra_pushbuf_get_offset(struct drm_tegra_pushbuf *pushbuf, uint32_t *ptr)
+{
+    return ptr - pushbuf->start;
+}
+
+void drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf)
+{
+    if (pushbuf->start)
+        free(pushbuf->start);
+
+    free(pushbuf);
+}
+
+/**
+ * drm_tegra_pushbuf_begin() - prepare push buffer for a series of pushes
+ * @pushbuf: push buffer
+ * @words: maximum number of words in series of pushes to follow
+ */
+drm_public int
+drm_tegra_pushbuf_begin(struct drm_tegra_pushbuf *pushbuf,
+                        unsigned int words, uint32_t **ptrp)
+{
+    struct drm_tegra_job *job = pushbuf->job;
+    unsigned long offset;
+    size_t size;
+    void *ptr;
+
+    if (pushbuf->ptr + words >= pushbuf->end) {
+        words = pushbuf->end - pushbuf->start + words;
+        size = ALIGN(words * 4, job->page_size);
+        offset = pushbuf->ptr - pushbuf->start;
+
+        ptr = realloc(pushbuf->start, size);
+        if (!ptr)
+            return -ENOMEM;
+
+        pushbuf->start = ptr;
+        pushbuf->end = pushbuf->start + size / 4;
+        pushbuf->ptr = pushbuf->start + offset;
+    }
+
+    if (ptrp)
+        *ptrp = pushbuf->ptr;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_pushbuf_end(struct drm_tegra_pushbuf *pushbuf, uint32_t *ptr)
+{
+    struct drm_tegra_submit_cmd *command;
+
+    command = drm_tegra_job_add_command(pushbuf->job,
+                                        DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR,
+                                        0);
+    if (!command)
+        return -ENOMEM;
+
+    command->gather_uptr.words = ptr - pushbuf->start;
+    pushbuf->ptr = ptr;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, uint32_t **ptrp,
+                           struct drm_tegra_mapping *target,
+                           unsigned long offset, unsigned int shift,
+                           uint32_t flags)
+{
+    struct drm_tegra_submit_buf *buffers, *buffer;
+    struct drm_tegra_job *job = pushbuf->job;
+    size_t size;
+
+    size = (job->num_buffers + 1) * sizeof(*buffer);
+
+    buffers = realloc(job->buffers, size);
+    if (!buffers)
+        return -ENOMEM;
+
+    buffer = &buffers[job->num_buffers];
+
+    memset(buffer, 0, sizeof(*buffer));
+    buffer->mapping = target->id;
+    buffer->flags = flags;
+    buffer->reloc.target_offset = offset;
+    buffer->reloc.gather_offset_words = drm_tegra_pushbuf_get_offset(pushbuf,
+                                                                     *ptrp);
+    buffer->reloc.shift = shift;
+
+    *(*ptrp)++ = 0xdeadbeef;
+
+    job->buffers = buffers;
+    job->num_buffers++;
+
+    return 0;
+}
diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index c16a351171f1..da3972cb99e1 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -15,4 +15,11 @@ drm_tegra_channel_map
 drm_tegra_channel_open
 drm_tegra_channel_unmap
 drm_tegra_close
+drm_tegra_job_free
+drm_tegra_job_get_pushbuf
+drm_tegra_job_new
+drm_tegra_job_submit
 drm_tegra_new
+drm_tegra_pushbuf_begin
+drm_tegra_pushbuf_end
+drm_tegra_pushbuf_relocate
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 621fef6b7000..0213e3b11e04 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -63,6 +63,22 @@ int drm_tegra_bo_import(struct drm_tegra *drm, int fd,
 
 struct drm_tegra_channel;
 struct drm_tegra_mapping;
+struct drm_tegra_pushbuf;
+struct drm_tegra_job;
+
+enum drm_tegra_sync_cond {
+    DRM_TEGRA_SYNC_COND_IMMEDIATE,
+    DRM_TEGRA_SYNC_COND_OP_DONE,
+    DRM_TEGRA_SYNC_COND_RD_DONE,
+    DRM_TEGRA_SYNC_COND_WR_SAFE,
+    DRM_TEGRA_SYNC_COND_MAX,
+  };
+
+struct drm_tegra_fence {
+    struct drm_tegra *drm;
+    uint32_t syncpt;
+    uint32_t value;
+};
 
 int drm_tegra_channel_open(struct drm_tegra *drm,
                            enum drm_tegra_class client,
@@ -74,4 +90,22 @@ int drm_tegra_channel_map(struct drm_tegra_channel *channel,
                           struct drm_tegra_mapping **mapp);
 int drm_tegra_channel_unmap(struct drm_tegra_mapping *map);
 
+int drm_tegra_job_new(struct drm_tegra_channel *channel,
+                      struct drm_tegra_job **jobp);
+int drm_tegra_job_free(struct drm_tegra_job *job);
+int drm_tegra_job_get_pushbuf(struct drm_tegra_job *job,
+                              struct drm_tegra_pushbuf **pushbufp);
+int drm_tegra_job_submit(struct drm_tegra_job *job,
+                         struct drm_tegra_fence *fence);
+int drm_tegra_job_wait(struct drm_tegra_job *job, unsigned long timeout);
+
+int drm_tegra_pushbuf_begin(struct drm_tegra_pushbuf *pushbuf,
+                            unsigned int words, uint32_t **ptrp);
+int drm_tegra_pushbuf_end(struct drm_tegra_pushbuf *pushbuf, uint32_t *ptr);
+int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
+                               uint32_t **ptrp,
+                               struct drm_tegra_mapping *target,
+                               unsigned long offset, unsigned int shift,
+                               uint32_t flags);
+
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 13/25] tegra: Add syncpoint APIs
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (11 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 12/25] tegra: Add job and push buffer APIs Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 14/25] tests: tegra: Add helper library for tests Thierry Reding
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

These new functions can be used to allocate and free syncpoints, as well
as wait for a syncpoint threshold to be reached. Jobs can also be waited
on if a syncpoint was attached to them.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/job.c             |  23 +++++++++
 tegra/meson.build       |   2 +-
 tegra/private.h         |   5 ++
 tegra/pushbuf.c         |  48 +++++++++++++++++++
 tegra/syncpt.c          | 101 ++++++++++++++++++++++++++++++++++++++++
 tegra/tegra-symbols.txt |   7 +++
 tegra/tegra.h           |  16 +++++++
 7 files changed, 201 insertions(+), 1 deletion(-)
 create mode 100644 tegra/syncpt.c

diff --git a/tegra/job.c b/tegra/job.c
index c8c94e131ef0..75a344f1dcc5 100644
--- a/tegra/job.c
+++ b/tegra/job.c
@@ -162,3 +162,26 @@ drm_tegra_job_submit(struct drm_tegra_job *job, struct drm_tegra_fence *fence)
 
     return 0;
 }
+
+drm_public int
+drm_tegra_job_wait(struct drm_tegra_job *job, unsigned long timeout)
+{
+    struct drm_tegra_channel *channel = job->channel;
+    struct drm_tegra *drm = channel->drm;
+    struct drm_tegra_syncpoint_wait args;
+    struct timespec ts;
+    int err;
+
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    memset(&args, 0, sizeof(args));
+    args.timeout_ns = ts.tv_sec * 1000000000 + ts.tv_nsec + timeout;
+    args.id = job->syncpt.id;
+    args.threshold = job->syncpt.fence;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SYNCPOINT_WAIT, &args);
+    if (err < 0)
+        return -errno;
+
+    return 0;
+}
diff --git a/tegra/meson.build b/tegra/meson.build
index 38e43039837c..3059b2a57d56 100644
--- a/tegra/meson.build
+++ b/tegra/meson.build
@@ -22,7 +22,7 @@ libdrm_tegra = library(
   'drm_tegra',
   [
     files(
-      'channel.c', 'job.c', 'private.h', 'pushbuf.c', 'tegra.c'
+      'channel.c', 'job.c', 'private.h', 'pushbuf.c', 'syncpt.c', 'tegra.c'
     ),
     config_file
   ],
diff --git a/tegra/private.h b/tegra/private.h
index 970ee8ad66d4..f134f3ea2cea 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -104,4 +104,9 @@ struct drm_tegra_submit_cmd *
 drm_tegra_job_add_command(struct drm_tegra_job *job, uint32_t type,
                           uint32_t flags);
 
+struct drm_tegra_syncpoint {
+    struct drm_tegra *drm;
+    uint32_t id;
+};
+
 #endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/pushbuf.c b/tegra/pushbuf.c
index 380a50abbbb0..0c0212e127a7 100644
--- a/tegra/pushbuf.c
+++ b/tegra/pushbuf.c
@@ -101,6 +101,25 @@ drm_tegra_pushbuf_end(struct drm_tegra_pushbuf *pushbuf, uint32_t *ptr)
     return 0;
 }
 
+drm_public int
+drm_tegra_pushbuf_wait(struct drm_tegra_pushbuf *pushbuf,
+                       struct drm_tegra_syncpoint *syncpt,
+                       uint32_t value)
+{
+    struct drm_tegra_submit_cmd *command;
+
+    command = drm_tegra_job_add_command(pushbuf->job,
+                                        DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT,
+                                        0);
+    if (!command)
+        return -ENOMEM;
+
+    command->wait_syncpt.id = syncpt->id;
+    command->wait_syncpt.value = value;
+
+    return 0;
+}
+
 drm_public int
 drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, uint32_t **ptrp,
                            struct drm_tegra_mapping *target,
@@ -134,3 +153,32 @@ drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, uint32_t **ptrp,
 
     return 0;
 }
+
+drm_public int
+drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
+                       struct drm_tegra_syncpoint *syncpt,
+                       unsigned int count)
+{
+    struct drm_tegra_job *job = pushbuf->job;
+
+    job->syncpt.increments += count;
+    job->syncpt.id = syncpt->id;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_pushbuf_sync_cond(struct drm_tegra_pushbuf *pushbuf, uint32_t **ptrp,
+                            struct drm_tegra_syncpoint *syncpt,
+                            enum drm_tegra_sync_cond cond)
+{
+    struct drm_tegra_channel *channel = pushbuf->job->channel;
+
+    if (cond >= DRM_TEGRA_SYNC_COND_MAX)
+        return -EINVAL;
+
+    *(*ptrp)++ = HOST1X_OPCODE_NONINCR(0x0, 0x1);
+    *(*ptrp)++ = cond << channel->cond_shift | syncpt->id;
+
+    return drm_tegra_pushbuf_sync(pushbuf, syncpt, 1);
+}
diff --git a/tegra/syncpt.c b/tegra/syncpt.c
new file mode 100644
index 000000000000..16014186fa30
--- /dev/null
+++ b/tegra/syncpt.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2021 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 <string.h>
+
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+drm_public int
+drm_tegra_syncpoint_new(struct drm_tegra *drm,
+                        struct drm_tegra_syncpoint **syncptp)
+{
+    struct drm_tegra_syncpoint_allocate args;
+    struct drm_tegra_syncpoint *syncpt;
+    int err;
+
+    syncpt = calloc(1, sizeof(*syncpt));
+    if (!syncpt)
+        return -ENOMEM;
+
+    memset(&args, 0, sizeof(args));
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SYNCPOINT_ALLOCATE, &args);
+    if (err < 0) {
+        free(syncpt);
+        return -errno;
+    }
+
+    syncpt->drm = drm;
+    syncpt->id = args.id;
+
+    *syncptp = syncpt;
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_syncpoint_free(struct drm_tegra_syncpoint *syncpt)
+{
+    struct drm_tegra_syncpoint_free args;
+    struct drm_tegra *drm = syncpt->drm;
+    int err;
+
+    if (!syncpt)
+        return -EINVAL;
+
+    memset(&args, 0, sizeof(args));
+    args.id = syncpt->id;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SYNCPOINT_FREE, &args);
+    if (err < 0)
+        return -errno;
+
+    free(syncpt);
+
+    return 0;
+}
+
+drm_public int
+drm_tegra_fence_wait(struct drm_tegra_fence *fence, unsigned long timeout)
+{
+    struct drm_tegra_syncpoint_wait args;
+    struct drm_tegra *drm = fence->drm;
+    int err;
+
+    memset(&args, 0, sizeof(args));
+    args.timeout_ns = 0;
+    args.id = fence->syncpt;
+    args.threshold = fence->value;
+
+    err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SYNCPOINT_WAIT, &args);
+    if (err < 0)
+        return -errno;
+
+    return 0;
+}
diff --git a/tegra/tegra-symbols.txt b/tegra/tegra-symbols.txt
index da3972cb99e1..1a75c3d27c83 100644
--- a/tegra/tegra-symbols.txt
+++ b/tegra/tegra-symbols.txt
@@ -15,11 +15,18 @@ drm_tegra_channel_map
 drm_tegra_channel_open
 drm_tegra_channel_unmap
 drm_tegra_close
+drm_tegra_fence_wait
 drm_tegra_job_free
 drm_tegra_job_get_pushbuf
 drm_tegra_job_new
 drm_tegra_job_submit
+drm_tegra_job_wait
 drm_tegra_new
 drm_tegra_pushbuf_begin
 drm_tegra_pushbuf_end
 drm_tegra_pushbuf_relocate
+drm_tegra_pushbuf_sync
+drm_tegra_pushbuf_sync_cond
+drm_tegra_pushbuf_wait
+drm_tegra_syncpoint_free
+drm_tegra_syncpoint_new
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 0213e3b11e04..8f3c0554f29b 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -65,6 +65,7 @@ struct drm_tegra_channel;
 struct drm_tegra_mapping;
 struct drm_tegra_pushbuf;
 struct drm_tegra_job;
+struct drm_tegra_syncpoint;
 
 enum drm_tegra_sync_cond {
     DRM_TEGRA_SYNC_COND_IMMEDIATE,
@@ -102,10 +103,25 @@ int drm_tegra_job_wait(struct drm_tegra_job *job, unsigned long timeout);
 int drm_tegra_pushbuf_begin(struct drm_tegra_pushbuf *pushbuf,
                             unsigned int words, uint32_t **ptrp);
 int drm_tegra_pushbuf_end(struct drm_tegra_pushbuf *pushbuf, uint32_t *ptr);
+int drm_tegra_pushbuf_wait(struct drm_tegra_pushbuf *pushbuf,
+                           struct drm_tegra_syncpoint *syncpt,
+                           uint32_t value);
 int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
                                uint32_t **ptrp,
                                struct drm_tegra_mapping *target,
                                unsigned long offset, unsigned int shift,
                                uint32_t flags);
+int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
+                           struct drm_tegra_syncpoint *syncpt,
+                           unsigned int count);
+int drm_tegra_pushbuf_sync_cond(struct drm_tegra_pushbuf *pushbuf,
+                                uint32_t **ptrp,
+                                struct drm_tegra_syncpoint *syncpt,
+                                enum drm_tegra_sync_cond cond);
+
+int drm_tegra_syncpoint_new(struct drm_tegra *drm,
+                            struct drm_tegra_syncpoint **syncptp);
+int drm_tegra_syncpoint_free(struct drm_tegra_syncpoint *syncpt);
+int drm_tegra_fence_wait(struct drm_tegra_fence *fence, unsigned long timeout);
 
 #endif /* __DRM_TEGRA_H__ */
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 14/25] tests: tegra: Add helper library for tests
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (12 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 13/25] tegra: Add syncpoint APIs Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 15/25] tests: tegra: Add gr2d-fill test Thierry Reding
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This library provides helpers for common functionality needed by test
programs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/drm-test.c  | 248 ++++++++++++++++++++++++++++++++++++++++
 tests/tegra/drm-test.h  |  72 ++++++++++++
 tests/tegra/meson.build |   7 ++
 3 files changed, 327 insertions(+)
 create mode 100644 tests/tegra/drm-test.c
 create mode 100644 tests/tegra/drm-test.h

diff --git a/tests/tegra/drm-test.c b/tests/tegra/drm-test.c
new file mode 100644
index 000000000000..b1ded9cf5fac
--- /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 000000000000..f11aed42343e
--- /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/meson.build b/tests/tegra/meson.build
index fbf4e6d8d4a3..3ac9015fbed8 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -20,6 +20,13 @@
 
 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,
+)
+
 openclose = executable(
   'tegra-openclose',
   files('openclose.c'),
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 15/25] tests: tegra: Add gr2d-fill test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (13 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 14/25] tests: tegra: Add helper library for tests Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 16/25] tests: tegra: Add syncpt-wait test Thierry Reding
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This test uses the IOCTLs for job submission and fences to fill a sub-
region of the screen to a specific color using gr2d.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/.gitignore       |   1 +
 tests/tegra/drm-test-tegra.c | 147 +++++++++++++++++++++++++++++++++++
 tests/tegra/drm-test-tegra.h |  55 +++++++++++++
 tests/tegra/gr2d-fill.c      | 146 ++++++++++++++++++++++++++++++++++
 tests/tegra/meson.build      |  19 +++++
 5 files changed, 368 insertions(+)
 create mode 100644 tests/tegra/drm-test-tegra.c
 create mode 100644 tests/tegra/drm-test-tegra.h
 create mode 100644 tests/tegra/gr2d-fill.c

diff --git a/tests/tegra/.gitignore b/tests/tegra/.gitignore
index 56cfb62b785f..0db9e5401302 100644
--- a/tests/tegra/.gitignore
+++ b/tests/tegra/.gitignore
@@ -1 +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 000000000000..1a9fa8961de9
--- /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 000000000000..eefa954cd40b
--- /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/gr2d-fill.c b/tests/tegra/gr2d-fill.c
new file mode 100644
index 000000000000..d138cc4c6f85
--- /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/meson.build b/tests/tegra/meson.build
index 3ac9015fbed8..b4aea33f4298 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -27,6 +27,16 @@ libdrm_test = static_library(
   link_with : libdrm,
 )
 
+libdrm_test_tegra = static_library(
+  'drm-test-tegra',
+  [files(
+    'drm-test-tegra.c',
+    'drm-test-tegra.h',
+  ), config_file ],
+  include_directories : [inc_root, inc_drm, inc_tegra],
+  link_with : libdrm,
+)
+
 openclose = executable(
   'tegra-openclose',
   files('openclose.c'),
@@ -35,3 +45,12 @@ openclose = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 16/25] tests: tegra: Add syncpt-wait test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (14 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 15/25] tests: tegra: Add gr2d-fill test Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 17/25] tests: tegra: Add syncpoint timeout test Thierry Reding
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This is a very simple sanity test to check whether or not a syncpt can
be incremented by a host1x client. This uses gr2d on Tegra20 through
Tegra114 and VIC on Tegra124 and later.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build   |   9 +++
 tests/tegra/syncpt-wait.c | 151 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+)
 create mode 100644 tests/tegra/syncpt-wait.c

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index b4aea33f4298..8b1b8bf58dd1 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -54,3 +54,12 @@ gr2d_fill = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
diff --git a/tests/tegra/syncpt-wait.c b/tests/tegra/syncpt-wait.c
new file mode 100644
index 000000000000..f18117425f6d
--- /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;
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 17/25] tests: tegra: Add syncpoint timeout test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (15 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 16/25] tests: tegra: Add syncpt-wait test Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 18/25] tests: tegra: Add VIC support Thierry Reding
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This test can be used to purposefully trigger a job timeout.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build      |   9 ++
 tests/tegra/syncpt-timeout.c | 163 +++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+)
 create mode 100644 tests/tegra/syncpt-timeout.c

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index 8b1b8bf58dd1..4b05569e0971 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -63,3 +63,12 @@ syncpt_wait = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
diff --git a/tests/tegra/syncpt-timeout.c b/tests/tegra/syncpt-timeout.c
new file mode 100644
index 000000000000..fea3665cb126
--- /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;
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 18/25] tests: tegra: Add VIC support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (16 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 17/25] tests: tegra: Add syncpoint timeout test Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 13:22 ` [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support Thierry Reding
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

Implement a small abstraction interface to allow different versions of
VIC to be used transparently. An implementation will be chosen based on
the VIC version number reported by the DRM_TEGRA_IOCTL_OPEN_CHANNEL
IOCTL.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/host1x.h    |  34 ++++++++
 tests/tegra/meson.build |   2 +
 tests/tegra/vic.c       | 152 +++++++++++++++++++++++++++++++++
 tests/tegra/vic.h       | 181 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 369 insertions(+)
 create mode 100644 tests/tegra/host1x.h
 create mode 100644 tests/tegra/vic.c
 create mode 100644 tests/tegra/vic.h

diff --git a/tests/tegra/host1x.h b/tests/tegra/host1x.h
new file mode 100644
index 000000000000..902b0c12ee6d
--- /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
index 4b05569e0971..55c1c72808e3 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -32,6 +32,8 @@ libdrm_test_tegra = static_library(
   [files(
     'drm-test-tegra.c',
     'drm-test-tegra.h',
+    'vic.c',
+    'vic.h',
   ), config_file ],
   include_directories : [inc_root, inc_drm, inc_tegra],
   link_with : libdrm,
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
new file mode 100644
index 000000000000..02ba4a25ae47
--- /dev/null
+++ b/tests/tegra/vic.c
@@ -0,0 +1,152 @@
+/*
+ * 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);
+}
+
+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) {
+    default:
+        break;
+    }
+
+    return -ENOTSUP;
+}
+
+void vic_free(struct vic *vic)
+{
+    if (vic)
+        vic->ops->free(vic);
+}
diff --git a/tests/tegra/vic.h b/tests/tegra/vic.h
new file mode 100644
index 000000000000..64860c84f397
--- /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 (*clear)(struct vic *vic, struct vic_image *output,
+                 unsigned int alpha, unsigned int red,
+                 unsigned int green, unsigned int blue);
+    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);
+
+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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (17 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 18/25] tests: tegra: Add VIC support Thierry Reding
@ 2021-08-27 13:22 ` Thierry Reding
  2021-08-27 14:06   ` Michał Mirosław
  2021-08-27 13:23 ` [PATCH libdrm 20/25] tests: tegra: Add VIC 4.0 support Thierry Reding
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:22 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

The Video Image Composer (VIC) 3.0 can be found on NVIDIA Tegra124 SoCs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tegra/private.h         |   6 +
 tests/tegra/meson.build |   2 +
 tests/tegra/vic.c       |   8 +-
 tests/tegra/vic30.c     | 509 ++++++++++++++++++++++++++++++++++++++++
 tests/tegra/vic30.h     | 439 ++++++++++++++++++++++++++++++++++
 5 files changed, 962 insertions(+), 2 deletions(-)
 create mode 100644 tests/tegra/vic30.c
 create mode 100644 tests/tegra/vic30.h

diff --git a/tegra/private.h b/tegra/private.h
index f134f3ea2cea..821eb0e48fd0 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -26,6 +26,7 @@
 #define __DRM_TEGRA_PRIVATE_H__ 1
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 #include <libdrm_macros.h>
@@ -34,6 +35,11 @@
 #include "tegra_drm.h"
 #include "tegra.h"
 
+#define container_of(ptr, type, member) ({                  \
+        const typeof(((type *)0)->member) *__mptr = (ptr);  \
+        (type *)((char *)__mptr - offsetof(type, member));  \
+    })
+
 enum host1x_class {
     HOST1X_CLASS_HOST1X = 0x01,
     HOST1X_CLASS_GR2D = 0x51,
diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index 55c1c72808e3..934b728a48d9 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -34,6 +34,8 @@ libdrm_test_tegra = static_library(
     'drm-test-tegra.h',
     'vic.c',
     'vic.h',
+    'vic30.c',
+    'vic30.h',
   ), config_file ],
   include_directories : [inc_root, inc_drm, inc_tegra],
   link_with : libdrm,
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
index 02ba4a25ae47..6001a0cdb9d2 100644
--- a/tests/tegra/vic.c
+++ b/tests/tegra/vic.c
@@ -130,6 +130,10 @@ void vic_image_dump(struct vic_image *image, FILE *fp)
     drm_tegra_bo_unmap(image->bo);
 }
 
+/* from vic30.c */
+int vic30_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)
 {
@@ -138,8 +142,8 @@ int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
     version = drm_tegra_channel_get_version(channel);
 
     switch (version) {
-    default:
-        break;
+    case 0x40:
+        return vic30_new(drm, channel, vicp);
     }
 
     return -ENOTSUP;
diff --git a/tests/tegra/vic30.c b/tests/tegra/vic30.c
new file mode 100644
index 000000000000..5db83e08e003
--- /dev/null
+++ b/tests/tegra/vic30.c
@@ -0,0 +1,509 @@
+/*
+ * 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_clear(struct vic *v, struct vic_image *output,
+                       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 = 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 = 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.ChromaHeight = 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;
+
+    drm_tegra_bo_unmap(vic->config.bo);
+
+    return 0;
+}
+
+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 = {
+    .clear = vic30_clear,
+    .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 000000000000..d095c0d229f2
--- /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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 20/25] tests: tegra: Add VIC 4.0 support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (18 preceding siblings ...)
  2021-08-27 13:22 ` [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-08-27 13:23 ` [PATCH libdrm 21/25] tests: tegra: Add VIC 4.1 support Thierry Reding
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

The Video Image Composer (VIC) 4.0 can be found on NVIDIA Tegra210 SoCs.
It uses a different class (B0B6) that is slightly incompatible with the
class found on earlier generations.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   2 +
 tests/tegra/vic.c       |   7 +
 tests/tegra/vic40.c     | 412 ++++++++++++++++++++++++++++++++++++++++
 tests/tegra/vic40.h     | 285 +++++++++++++++++++++++++++
 4 files changed, 706 insertions(+)
 create mode 100644 tests/tegra/vic40.c
 create mode 100644 tests/tegra/vic40.h

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index 934b728a48d9..e0f94891a76f 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -36,6 +36,8 @@ libdrm_test_tegra = static_library(
     'vic.h',
     'vic30.c',
     'vic30.h',
+    'vic40.c',
+    'vic40.h',
   ), config_file ],
   include_directories : [inc_root, inc_drm, inc_tegra],
   link_with : libdrm,
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
index 6001a0cdb9d2..8acca30b6e6b 100644
--- a/tests/tegra/vic.c
+++ b/tests/tegra/vic.c
@@ -134,6 +134,10 @@ void vic_image_dump(struct vic_image *image, FILE *fp)
 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);
+
 int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
             struct vic **vicp)
 {
@@ -144,6 +148,9 @@ int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
     switch (version) {
     case 0x40:
         return vic30_new(drm, channel, vicp);
+
+    case 0x21:
+        return vic40_new(drm, channel, vicp);
     }
 
     return -ENOTSUP;
diff --git a/tests/tegra/vic40.c b/tests/tegra/vic40.c
new file mode 100644
index 000000000000..2809b9c7f5d0
--- /dev/null
+++ b/tests/tegra/vic40.c
@@ -0,0 +1,412 @@
+/*
+ * 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;
+
+    struct {
+        struct drm_tegra_mapping *map;
+        struct drm_tegra_bo *bo;
+    } hist;
+};
+
+static int vic40_clear(struct vic *v, struct vic_image *output,
+                       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 = 0;
+    c->outputConfig.TargetRectLeft = 0;
+    c->outputConfig.TargetRectRight = output->width - 1;
+    c->outputConfig.TargetRectBottom = output->height - 1;
+    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_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->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 vic40_ops = {
+    .clear = vic40_clear,
+    .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;
+    }
+
+    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/vic40.h b/tests/tegra/vic40.h
new file mode 100644
index 000000000000..a62301a8a94c
--- /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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 21/25] tests: tegra: Add VIC 4.1 support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (19 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 20/25] tests: tegra: Add VIC 4.0 support Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-08-27 13:23 ` [PATCH libdrm 22/25] tests: tegra: Add VIC 4.2 support Thierry Reding
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

The Video Image Composer (VIC) 4.1 can be found on NVIDIA Tegra186 SoCs.
It uses a different class (B1B6) that is slightly incompatible with the
class found on earlier generations.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   2 +
 tests/tegra/vic.c       |   7 +
 tests/tegra/vic41.c     | 416 ++++++++++++++++++++++++++++++++++++++++
 tests/tegra/vic41.h     | 372 +++++++++++++++++++++++++++++++++++
 4 files changed, 797 insertions(+)
 create mode 100644 tests/tegra/vic41.c
 create mode 100644 tests/tegra/vic41.h

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index e0f94891a76f..ad5d38bcd8dc 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -38,6 +38,8 @@ libdrm_test_tegra = static_library(
     'vic30.h',
     'vic40.c',
     'vic40.h',
+    'vic41.c',
+    'vic41.h',
   ), config_file ],
   include_directories : [inc_root, inc_drm, inc_tegra],
   link_with : libdrm,
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
index 8acca30b6e6b..9403a46a7050 100644
--- a/tests/tegra/vic.c
+++ b/tests/tegra/vic.c
@@ -138,6 +138,10 @@ int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
 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);
+
 int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
             struct vic **vicp)
 {
@@ -151,6 +155,9 @@ int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
 
     case 0x21:
         return vic40_new(drm, channel, vicp);
+
+    case 0x18:
+        return vic41_new(drm, channel, vicp);
     }
 
     return -ENOTSUP;
diff --git a/tests/tegra/vic41.c b/tests/tegra/vic41.c
new file mode 100644
index 000000000000..26cae1a895c3
--- /dev/null
+++ b/tests/tegra/vic41.c
@@ -0,0 +1,416 @@
+/*
+ * 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;
+
+    struct {
+        struct drm_tegra_mapping *map;
+        struct drm_tegra_bo *bo;
+    } hist;
+};
+
+static int vic41_clear(struct vic *v, struct vic_image *output,
+                       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 = 0;
+    c->outputConfig.TargetRectLeft = 0;
+    c->outputConfig.TargetRectRight = output->width - 1;
+    c->outputConfig.TargetRectBottom = output->height - 1;
+    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_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->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 vic41_ops = {
+    .clear = vic41_clear,
+    .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;
+    }
+
+    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/vic41.h b/tests/tegra/vic41.h
new file mode 100644
index 000000000000..07d7019a7a4e
--- /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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 22/25] tests: tegra: Add VIC 4.2 support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (20 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 21/25] tests: tegra: Add VIC 4.1 support Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-08-27 13:23 ` [PATCH libdrm 23/25] tests: tegra: Add VIC clear test Thierry Reding
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

The Video Image Composer (VIC) 4.2 can be found on NVIDIA Tegra194 SoCs.
It uses a different class (C5B6) that is slightly incompatible with the
class found on earlier generations, although it is backwards compatible
with the class implemented on Tegra186 (B1B6).

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   2 +
 tests/tegra/vic.c       |   7 +
 tests/tegra/vic42.c     | 423 ++++++++++++++++++++++++++++
 tests/tegra/vic42.h     | 597 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1029 insertions(+)
 create mode 100644 tests/tegra/vic42.c
 create mode 100644 tests/tegra/vic42.h

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index ad5d38bcd8dc..d71d3d564efe 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -40,6 +40,8 @@ libdrm_test_tegra = static_library(
     'vic40.h',
     'vic41.c',
     'vic41.h',
+    'vic42.c',
+    'vic42.h',
   ), config_file ],
   include_directories : [inc_root, inc_drm, inc_tegra],
   link_with : libdrm,
diff --git a/tests/tegra/vic.c b/tests/tegra/vic.c
index 9403a46a7050..8e65eb96c316 100644
--- a/tests/tegra/vic.c
+++ b/tests/tegra/vic.c
@@ -142,6 +142,10 @@ int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
 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)
 {
@@ -158,6 +162,9 @@ int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
 
     case 0x18:
         return vic41_new(drm, channel, vicp);
+
+    case 0x19:
+        return vic42_new(drm, channel, vicp);
     }
 
     return -ENOTSUP;
diff --git a/tests/tegra/vic42.c b/tests/tegra/vic42.c
new file mode 100644
index 000000000000..fec22ceb42a0
--- /dev/null
+++ b/tests/tegra/vic42.c
@@ -0,0 +1,423 @@
+/*
+ * 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;
+
+    struct {
+        struct drm_tegra_mapping *map;
+        struct drm_tegra_bo *bo;
+    } hist;
+};
+
+static int vic42_clear(struct vic *v, struct vic_image *output,
+                       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 = 0;
+    c->outputConfig.TargetRectLeft = 0;
+    c->outputConfig.TargetRectRight = output->width - 1;
+    c->outputConfig.TargetRectBottom = output->height - 1;
+    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;
+    printf("OutLumaWidth: %u\n", c->outputSurfaceConfig.OutLumaWidth);
+    c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
+    c->outputSurfaceConfig.OutChromaWidth = 16383;
+    c->outputSurfaceConfig.OutChromaHeight = 16383;
+
+    if (1) {
+        FILE *fp = fopen("/tmp/configstruct.bin", "wb");
+        fwrite(c, sizeof(*c), 1, fp);
+        fclose(fp);
+    }
+
+    drm_tegra_bo_unmap(vic->config.bo);
+
+    return 0;
+}
+
+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->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 vic42_ops = {
+    .clear = vic42_clear,
+    .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;
+    }
+
+    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/vic42.h b/tests/tegra/vic42.h
new file mode 100644
index 000000000000..3ed5cdbd3b6c
--- /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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 23/25] tests: tegra: Add VIC clear test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (21 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 22/25] tests: tegra: Add VIC 4.2 support Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-08-27 13:23 ` [PATCH libdrm 24/25] tests: tegra: Add VIC blit test Thierry Reding
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This test will attempt to use VIC to clear a surface.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   9 +++
 tests/tegra/vic-clear.c | 173 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 182 insertions(+)
 create mode 100644 tests/tegra/vic-clear.c

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index d71d3d564efe..e44bd3a4393d 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -82,3 +82,12 @@ syncpt_timeout = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
diff --git a/tests/tegra/vic-clear.c b/tests/tegra/vic-clear.c
new file mode 100644
index 000000000000..f65a644d398c
--- /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->ops->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;
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 24/25] tests: tegra: Add VIC blit test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (22 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 23/25] tests: tegra: Add VIC clear test Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-08-27 13:23 ` [PATCH libdrm 25/25] tests: tegra: Add VIC flip test Thierry Reding
  2021-09-20 16:43 ` [PATCH libdrm 00/25] Update Tegra support Dmitry Osipenko
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This test will attempt to use the VIC to blit from one surface to
another.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   9 ++
 tests/tegra/vic-blit.c  | 333 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 342 insertions(+)
 create mode 100644 tests/tegra/vic-blit.c

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index e44bd3a4393d..a9ca09e12f3e 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -91,3 +91,12 @@ vic_clear = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
diff --git a/tests/tegra/vic-blit.c b/tests/tegra/vic-blit.c
new file mode 100644
index 000000000000..1b4a3eff87d3
--- /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->ops->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;
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH libdrm 25/25] tests: tegra: Add VIC flip test
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (23 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 24/25] tests: tegra: Add VIC blit test Thierry Reding
@ 2021-08-27 13:23 ` Thierry Reding
  2021-09-20 16:43 ` [PATCH libdrm 00/25] Update Tegra support Dmitry Osipenko
  25 siblings, 0 replies; 28+ messages in thread
From: Thierry Reding @ 2021-08-27 13:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

From: Thierry Reding <treding@nvidia.com>

This test will attempt to use the VIC to blit one surface to another
and perform a vertical flip.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/tegra/meson.build |   9 ++
 tests/tegra/vic-flip.c  | 333 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 342 insertions(+)
 create mode 100644 tests/tegra/vic-flip.c

diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
index a9ca09e12f3e..d24053265c2f 100644
--- a/tests/tegra/meson.build
+++ b/tests/tegra/meson.build
@@ -100,3 +100,12 @@ vic_blit = executable(
   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 : warn_c_args,
+  link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra],
+  install : with_install_tests,
+)
diff --git a/tests/tegra/vic-flip.c b/tests/tegra/vic-flip.c
new file mode 100644
index 000000000000..2e32d6eb4324
--- /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->ops->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;
+}
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support
  2021-08-27 13:22 ` [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support Thierry Reding
@ 2021-08-27 14:06   ` Michał Mirosław
  0 siblings, 0 replies; 28+ messages in thread
From: Michał Mirosław @ 2021-08-27 14:06 UTC (permalink / raw)
  To: Thierry Reding; +Cc: dri-devel, linux-tegra

On Fri, Aug 27, 2021 at 03:22:59PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> The Video Image Composer (VIC) 3.0 can be found on NVIDIA Tegra124 SoCs.a
[...]
> +static int vic30_clear(struct vic *v, struct vic_image *output,
> +                       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 = 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 = 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.ChromaHeight = 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;
> +
> +    drm_tegra_bo_unmap(vic->config.bo);
> +
> +    return 0;
> +}
[...]

It does look exactly like:

return vic30_fill(v, output, 0, 0, output->width - 1,
	output->height - 1, alpha, red, green, blue);

Best Regards
Michał Mirosław

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH libdrm 00/25] Update Tegra support
  2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
                   ` (24 preceding siblings ...)
  2021-08-27 13:23 ` [PATCH libdrm 25/25] tests: tegra: Add VIC flip test Thierry Reding
@ 2021-09-20 16:43 ` Dmitry Osipenko
  25 siblings, 0 replies; 28+ messages in thread
From: Dmitry Osipenko @ 2021-09-20 16:43 UTC (permalink / raw)
  To: Thierry Reding, Mikko Perttunen; +Cc: dri-devel, linux-tegra

27.08.2021 16:22, Thierry Reding пишет:
> From: Thierry Reding <treding@nvidia.com>
> 
> Hi all,
> 
> this is the userspace part of the kernel patches that were recently
> merged into drm-next:
> 
>   https://patchwork.freedesktop.org/series/92378/
> 
> The goal is to provide a userspace implementation of the UAPI exposed by
> the kernel and show its usage in some test programs that can also be
> used for basic sanity testing. More complete userspace implementations
> are available here:
> 
>   * https://github.com/cyndis/vaapi-tegra-driver
>   * https://github.com/grate-driver/xf86-video-opentegra
>   * https://github.com/grate-driver/grate
> 
> Thierry
> 
> Thierry Reding (25):
>   tegra: Indent according to .editorconfig
>   tegra: Remove unused IOCTL implementations
>   tegra: Extract common buffer object allocation code
>   tegra: Fix mmap() of GEM buffer objects
>   tegra: Add flink helpers
>   tegra: Add PRIME support helpers
>   tegra: Make API more consistent
>   tegra: Install tegra-openclose test
>   tegra: Update for new UABI
>   tegra: Include private.h in list of source files
>   tegra: Add channel APIs
>   tegra: Add job and push buffer APIs
>   tegra: Add syncpoint APIs
>   tests: tegra: Add helper library for tests
>   tests: tegra: Add gr2d-fill test
>   tests: tegra: Add syncpt-wait test
>   tests: tegra: Add syncpoint timeout test
>   tests: tegra: Add VIC support
>   tests: tegra: Add VIC 3.0 support
>   tests: tegra: Add VIC 4.0 support
>   tests: tegra: Add VIC 4.1 support
>   tests: tegra: Add VIC 4.2 support
>   tests: tegra: Add VIC clear test
>   tests: tegra: Add VIC blit test
>   tests: tegra: Add VIC flip test

Have you thought about moving tests into IGT? Wouldn't it be a more
appropriate place for the tests?

Perhaps we can add/move Mikko's UAPI tests there too, for complicity.
Although, I'd prefer it all to be written in a plain C or C++.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2021-09-20 16:43 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-27 13:22 [PATCH libdrm 00/25] Update Tegra support Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 01/25] tegra: Indent according to .editorconfig Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 02/25] tegra: Remove unused IOCTL implementations Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 03/25] tegra: Extract common buffer object allocation code Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 04/25] tegra: Fix mmap() of GEM buffer objects Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 05/25] tegra: Add flink helpers Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 06/25] tegra: Add PRIME support helpers Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 07/25] tegra: Make API more consistent Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 08/25] tegra: Install tegra-openclose test Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 09/25] tegra: Update for new UABI Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 10/25] tegra: Include private.h in list of source files Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 11/25] tegra: Add channel APIs Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 12/25] tegra: Add job and push buffer APIs Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 13/25] tegra: Add syncpoint APIs Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 14/25] tests: tegra: Add helper library for tests Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 15/25] tests: tegra: Add gr2d-fill test Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 16/25] tests: tegra: Add syncpt-wait test Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 17/25] tests: tegra: Add syncpoint timeout test Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 18/25] tests: tegra: Add VIC support Thierry Reding
2021-08-27 13:22 ` [PATCH libdrm 19/25] tests: tegra: Add VIC 3.0 support Thierry Reding
2021-08-27 14:06   ` Michał Mirosław
2021-08-27 13:23 ` [PATCH libdrm 20/25] tests: tegra: Add VIC 4.0 support Thierry Reding
2021-08-27 13:23 ` [PATCH libdrm 21/25] tests: tegra: Add VIC 4.1 support Thierry Reding
2021-08-27 13:23 ` [PATCH libdrm 22/25] tests: tegra: Add VIC 4.2 support Thierry Reding
2021-08-27 13:23 ` [PATCH libdrm 23/25] tests: tegra: Add VIC clear test Thierry Reding
2021-08-27 13:23 ` [PATCH libdrm 24/25] tests: tegra: Add VIC blit test Thierry Reding
2021-08-27 13:23 ` [PATCH libdrm 25/25] tests: tegra: Add VIC flip test Thierry Reding
2021-09-20 16:43 ` [PATCH libdrm 00/25] Update Tegra support Dmitry Osipenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.