diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-06-06 12:14:08 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-06-06 12:14:08 +0000 |
commit | 2bd8150b39195449b9473a7afa51dc88f7650b60 (patch) | |
tree | 30fcb5c94c1562113321613766c363a54d607b79 | |
parent | 3c012d229d655ce7ec8da541464f38b441b1ae3d (diff) |
Import libdrm 2.4.111
59 files changed, 8254 insertions, 564 deletions
diff --git a/lib/libdrm/.gitlab-ci.yml b/lib/libdrm/.gitlab-ci.yml index c5aa7a2ba..3c79867ad 100644 --- a/lib/libdrm/.gitlab-ci.yml +++ b/lib/libdrm/.gitlab-ci.yml @@ -198,7 +198,6 @@ x86_64-freebsd-container_prep: -D freedreno=true -D freedreno-kgsl=true -D intel=true - -D libkms=true -D man-pages=true -D nouveau=true -D omap=true @@ -228,7 +227,7 @@ x86_64-freebsd-container_prep: # the workspace to see details about the failed tests. - | set +e - /app/vmctl exec "pkg info; cd $CI_PROJECT_NAME ; meson build -D amdgpu=true -D cairo-tests=true -D intel=true -D libkms=true -D man-pages=true -D nouveau=false -D radeon=true -D valgrind=auto && ninja -C build" + /app/vmctl exec "pkg info; cd $CI_PROJECT_NAME ; meson build -D amdgpu=true -D cairo-tests=true -D intel=true -D man-pages=true -D nouveau=false -D radeon=true -D valgrind=auto && ninja -C build" set -ex scp -r vm:$CI_PROJECT_NAME/build/meson-logs . /app/vmctl exec "ninja -C $CI_PROJECT_NAME/build install" diff --git a/lib/libdrm/data/amdgpu.ids b/lib/libdrm/data/amdgpu.ids index 0040a38ad..0d2b8847e 100644 --- a/lib/libdrm/data/amdgpu.ids +++ b/lib/libdrm/data/amdgpu.ids @@ -275,18 +275,35 @@ 7341, 00, AMD Radeon Pro W5500 7347, 00, AMD Radeon Pro W5500M 73A3, 00, AMD Radeon Pro W6800 +73A5, C0, AMD Radeon RX 6950 XT 73AF, C0, AMD Radeon RX 6900 XT 73BF, C0, AMD Radeon RX 6900 XT 73BF, C1, AMD Radeon RX 6800 XT 73BF, C3, AMD Radeon RX 6800 +73DF, C0, AMD Radeon RX 6750 XT 73DF, C1, AMD Radeon RX 6700 XT 73DF, C3, AMD Radeon RX 6800M 73DF, C5, AMD Radeon RX 6700 XT 73DF, CF, AMD Radeon RX 6700M 73E1, 00, AMD Radeon Pro W6600M 73E3, 00, AMD Radeon Pro W6600 +73EF, C0, AMD Radeon RX 6800S +73EF, C1, AMD Radeon RX 6650 XT +73EF, C2, AMD Radeon RX 6700S +73EF, C3, AMD Radeon RX 6650M +73EF, C4, AMD Radeon RX 6650M XT 73FF, C1, AMD Radeon RX 6600 XT 73FF, C3, AMD Radeon RX 6600M +73FF, C7, AMD Radeon RX 6600 +73FF, CB, AMD Radeon RX 6600S +7421, 00, AMD Radeon Pro W6500M +7422, 00, AMD Radeon PRO W6400 +7423, 00, AMD Radeon Pro W6300M +7424, 00, AMD Radeon RX 6300 +743F, C1, AMD Radeon RX 6500 XT +743F, C3, AMD Radeon RX 6500 +743F, C7, AMD Radeon RX 6400 +743F, CF, AMD Radeon RX 6300M 9874, C4, AMD Radeon R7 Graphics 9874, C5, AMD Radeon R6 Graphics 9874, C6, AMD Radeon R6 Graphics diff --git a/lib/libdrm/include/drm/tegra_drm.h b/lib/libdrm/include/drm/tegra_drm.h index 6c07919c0..94cfc306d 100644 --- a/lib/libdrm/include/drm/tegra_drm.h +++ b/lib/libdrm/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 diff --git a/lib/libdrm/intel/intel_chipset.c b/lib/libdrm/intel/intel_chipset.c index 99ad04ae0..ee8866c1b 100644 --- a/lib/libdrm/intel/intel_chipset.c +++ b/lib/libdrm/intel/intel_chipset.c @@ -35,9 +35,10 @@ static const struct pci_device { uint16_t gen; } pciids[] = { /* Keep ids sorted by gen; latest gen first */ - INTEL_RPLS_IDS(12), INTEL_ADLN_IDS(12), + INTEL_RPLP_IDS(12), INTEL_ADLP_IDS(12), + INTEL_RPLS_IDS(12), INTEL_ADLS_IDS(12), INTEL_RKL_IDS(12), INTEL_DG1_IDS(12), diff --git a/lib/libdrm/man/drm-kms.7.rst b/lib/libdrm/man/drm-kms.7.rst index e91fbe274..587d7eb79 100644 --- a/lib/libdrm/man/drm-kms.7.rst +++ b/lib/libdrm/man/drm-kms.7.rst @@ -102,13 +102,13 @@ for the selected connector. See the *Examples* section below for more information. All valid modes for a connector can be retrieved with a call to -drmModeGetConnector3 You need to select the mode you want to use and save it. +**drmModeGetConnector**\ (3) You need to select the mode you want to use and save it. The first mode in the list is the default mode with the highest resolution possible and often a suitable choice. After you have a working connector+CRTC+mode combination, you need to create a framebuffer that is used for scanout. Memory buffer allocation is -driver-depedent and described in **drm-memory**\ (7). You need to create a +driver-dependent and described in **drm-memory**\ (7). You need to create a buffer big enough for your selected mode. Now you can create a framebuffer object that uses your memory-buffer as scanout buffer. You can do this with **drmModeAddFB**\ (3) and **drmModeAddFB2**\ (3). diff --git a/lib/libdrm/man/drm.7.rst b/lib/libdrm/man/drm.7.rst index c9b5696ff..df2c1c740 100644 --- a/lib/libdrm/man/drm.7.rst +++ b/lib/libdrm/man/drm.7.rst @@ -73,7 +73,7 @@ driver dependent. However, two generic frameworks are available that are used by most DRM drivers. These are the *Translation Table Manager* (TTM) and the *Graphics Execution Manager* (GEM). They provide generic APIs to create, destroy and access buffers from user-space. However, -there are still many differences between the drivers so driver-depedent +there are still many differences between the drivers so driver-dependent code is still needed. Many helpers are provided in *libgbm* (Graphics Buffer Manager) from the *Mesa* project. For more information on DRM memory management, see **drm-memory**\ (7). diff --git a/lib/libdrm/meson.build b/lib/libdrm/meson.build index 210d29e08..06f48dd97 100644 --- a/lib/libdrm/meson.build +++ b/lib/libdrm/meson.build @@ -21,7 +21,7 @@ project( 'libdrm', ['c'], - version : '2.4.110', + version : '2.4.111', license : 'MIT', meson_version : '>= 0.53', default_options : ['buildtype=debugoptimized', 'c_std=c99'], @@ -182,15 +182,6 @@ if _vc4 != 'false' endif summary('VC4', with_vc4) -# XXX: Apparently only freebsd and dragonfly bsd actually need this (and -# gnu/kfreebsd), not openbsd and netbsd -with_libkms = false -_libkms = get_option('libkms') -if _libkms != 'false' - with_libkms = _libkms == 'true' or (['linux', 'freebsd', 'dragonfly'].contains(host_machine.system()) and not android) -endif -summary('libkms', with_libkms) - # Among others FreeBSD does not have a separate dl library. if not cc.has_function('dlsym') dep_dl = cc.find_library('dl', required : with_nouveau) @@ -366,9 +357,6 @@ pkg.generate( description : 'Userspace interface to kernel DRM services', ) -if with_libkms - subdir('libkms') -endif if with_intel subdir('intel') endif diff --git a/lib/libdrm/meson_options.txt b/lib/libdrm/meson_options.txt index 8af33f1c1..f5d066f08 100644 --- a/lib/libdrm/meson_options.txt +++ b/lib/libdrm/meson_options.txt @@ -19,13 +19,6 @@ # SOFTWARE. option( - 'libkms', - type : 'combo', - value : 'auto', - choices : ['true', 'false', 'auto'], - description : 'Build libkms mm abstraction library.', -) -option( 'intel', type : 'combo', value : 'auto', diff --git a/lib/libdrm/nouveau/nouveau-symbols.txt b/lib/libdrm/nouveau/nouveau-symbols.txt index ef8032f29..598465f18 100644 --- a/lib/libdrm/nouveau/nouveau-symbols.txt +++ b/lib/libdrm/nouveau/nouveau-symbols.txt @@ -12,6 +12,7 @@ nouveau_bufctx_mthd nouveau_bufctx_new nouveau_bufctx_refn nouveau_bufctx_reset +nouveau_check_dead_channel nouveau_client_del nouveau_client_new nouveau_device_del diff --git a/lib/libdrm/nouveau/nouveau.h b/lib/libdrm/nouveau/nouveau.h index 335ce77dc..0c632febd 100644 --- a/lib/libdrm/nouveau/nouveau.h +++ b/lib/libdrm/nouveau/nouveau.h @@ -273,4 +273,8 @@ struct nv04_notify { uint32_t offset; uint32_t length; }; + +bool +nouveau_check_dead_channel(struct nouveau_drm *, struct nouveau_object *chan); + #endif diff --git a/lib/libdrm/nouveau/pushbuf.c b/lib/libdrm/nouveau/pushbuf.c index 5fadd7a99..5d54f21df 100644 --- a/lib/libdrm/nouveau/pushbuf.c +++ b/lib/libdrm/nouveau/pushbuf.c @@ -782,3 +782,19 @@ nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan) pushbuf_flush(push); return pushbuf_validate(push, false); } + +drm_public bool +nouveau_check_dead_channel(struct nouveau_drm *drm, struct nouveau_object *chan) +{ + struct drm_nouveau_gem_pushbuf req = {}; + struct nouveau_fifo *fifo = chan->data; + int ret; + + req.channel = fifo->channel; + req.nr_push = 0; + + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF, + &req, sizeof(req)); + /* nouveau returns ENODEV once the channel was killed */ + return ret == -ENODEV; +} diff --git a/lib/libdrm/tegra/channel.c b/lib/libdrm/tegra/channel.c new file mode 100644 index 000000000..391362023 --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tegra/job.c b/lib/libdrm/tegra/job.c new file mode 100644 index 000000000..75a344f1d --- /dev/null +++ b/lib/libdrm/tegra/job.c @@ -0,0 +1,187 @@ +/* + * 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; +} + +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/lib/libdrm/tegra/meson.build b/lib/libdrm/tegra/meson.build index 7585c8b5b..0b63d7894 100644 --- a/lib/libdrm/tegra/meson.build +++ b/lib/libdrm/tegra/meson.build @@ -20,7 +20,12 @@ libdrm_tegra = library( 'drm_tegra', - [files('tegra.c'), config_file], + [ + files( + 'channel.c', 'job.c', 'private.h', 'pushbuf.c', 'syncpt.c', 'tegra.c' + ), + config_file + ], include_directories : [inc_root, inc_drm], link_with : libdrm, dependencies : [dep_pthread_stubs, dep_atomic_ops], diff --git a/lib/libdrm/tegra/private.h b/lib/libdrm/tegra/private.h index bb6c1a516..fc204e82e 100644 --- a/lib/libdrm/tegra/private.h +++ b/lib/libdrm/tegra/private.h @@ -26,26 +26,93 @@ #define __DRM_TEGRA_PRIVATE_H__ 1 #include <stdbool.h> +#include <stddef.h> #include <stdint.h> #include <libdrm_macros.h> #include <xf86atomic.h> +#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, + HOST1X_CLASS_GR2D_SB = 0x52, + HOST1X_CLASS_VIC = 0x5d, + HOST1X_CLASS_GR3D = 0x60, +}; + 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; + uint64_t offset; + uint32_t flags; + uint32_t size; + atomic_t ref; + 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; +}; + +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); + +struct drm_tegra_syncpoint { + struct drm_tegra *drm; + uint32_t id; }; #endif /* __DRM_TEGRA_PRIVATE_H__ */ diff --git a/lib/libdrm/tegra/pushbuf.c b/lib/libdrm/tegra/pushbuf.c new file mode 100644 index 000000000..0c0212e12 --- /dev/null +++ b/lib/libdrm/tegra/pushbuf.c @@ -0,0 +1,184 @@ +/* + * 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_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, + 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; +} + +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/lib/libdrm/tegra/syncpt.c b/lib/libdrm/tegra/syncpt.c new file mode 100644 index 000000000..16014186f --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tegra/tegra-symbols.txt b/lib/libdrm/tegra/tegra-symbols.txt index 5e3e955f2..1a75c3d27 100644 --- a/lib/libdrm/tegra/tegra-symbols.txt +++ b/lib/libdrm/tegra/tegra-symbols.txt @@ -1,13 +1,32 @@ -drm_tegra_bo_get_flags +drm_tegra_bo_export drm_tegra_bo_get_handle -drm_tegra_bo_get_tiling +drm_tegra_bo_get_name +drm_tegra_bo_import drm_tegra_bo_map drm_tegra_bo_new +drm_tegra_bo_open 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 +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_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/lib/libdrm/tegra/tegra.c b/lib/libdrm/tegra/tegra.c index 420b171c5..6a51c4311 100644 --- a/lib/libdrm/tegra/tegra.c +++ b/lib/libdrm/tegra/tegra.c @@ -37,288 +37,318 @@ static void drm_tegra_bo_free(struct drm_tegra_bo *bo) { - struct drm_tegra *drm = bo->drm; + struct drm_tegra *drm = bo->drm; - if (bo->map) - munmap(bo->map, bo->size); + if (bo->map) + munmap(bo->map, bo->size); - drmCloseBufferHandle(drm->fd, bo->handle); + drmCloseBufferHandle(drm->fd, bo->handle); - 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) +drm_public int drm_tegra_new(int fd, struct drm_tegra **drmp) { - 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) +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_gem_create args; - struct drm_tegra_bo *bo; - int err; + struct drm_tegra_bo *bo; - if (!drm || size == 0 || !bop) - return -EINVAL; + bo = calloc(1, sizeof(*bo)); + if (!bo) + return NULL; - 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->flags = flags; - bo->size = size; - bo->drm = drm; + return bo; +} + +drm_public int +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; + int err; + + if (!drm || size == 0 || !bop) + return -EINVAL; + + bo = drm_tegra_bo_alloc(drm, 0, flags, size); + if (!bo) + return -ENOMEM; - 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 *drm, uint32_t handle, uint32_t flags, + uint32_t size, struct drm_tegra_bo **bop) { - 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 = 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; - *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) +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 = 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; + } + } - 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) +drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name) { - struct drm_tegra_gem_get_flags args; - struct drm_tegra *drm = bo->drm; - int err; - - if (!bo) - return -EINVAL; + struct drm_tegra *drm = bo->drm; + struct drm_gem_flink 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_GET_FLAGS, &args, - sizeof(args)); - if (err < 0) - return -errno; + err = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &args); + if (err < 0) + return err; - if (flags) - *flags = args.flags; + if (name) + *name = args.name; - return 0; + return 0; } -drm_public int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) +drm_public int +drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags, + struct drm_tegra_bo **bop) { - struct drm_tegra_gem_get_flags args; - struct drm_tegra *drm = bo->drm; - int err; + 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; - if (!bo) - return -EINVAL; + err = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &args); + if (err < 0) + goto free; - memset(&args, 0, sizeof(args)); - args.handle = bo->handle; - args.flags = flags; + bo->handle = args.handle; + bo->size = args.size; - err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args, - sizeof(args)); - if (err < 0) - return -errno; + *bop = bo; - return 0; + return 0; + +free: + free(bo); + return err; } -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_export(struct drm_tegra_bo *bo, uint32_t flags) { - struct drm_tegra_gem_get_tiling args; - struct drm_tegra *drm = bo->drm; - int err; + int fd, err; + + flags |= DRM_CLOEXEC; + + err = drmPrimeHandleToFD(bo->drm->fd, bo->handle, flags, &fd); + if (err < 0) + return err; + + return fd; +} - if (!bo) - return -EINVAL; +static ssize_t fd_get_size(int fd) +{ + ssize_t size, offset; + int err; - memset(&args, 0, sizeof(args)); - args.handle = bo->handle; + offset = lseek(fd, 0, SEEK_CUR); + if (offset < 0) + return -errno; - err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args, - sizeof(args)); - if (err < 0) - return -errno; + size = lseek(fd, 0, SEEK_END); + if (size < 0) + return -errno; - if (tiling) { - tiling->mode = args.mode; - tiling->value = args.value; - } + err = lseek(fd, offset, SEEK_SET); + if (err < 0) + return -errno; - return 0; + return size; } -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_import(struct drm_tegra *drm, int fd, struct drm_tegra_bo **bop) { - struct drm_tegra_gem_set_tiling args; - struct drm_tegra *drm = bo->drm; - int err; + 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; - if (!bo) - return -EINVAL; + err = drmPrimeFDToHandle(drm->fd, fd, &bo->handle); + if (err < 0) + goto free; - memset(&args, 0, sizeof(args)); - args.handle = bo->handle; - args.mode = tiling->mode; - args.value = tiling->value; + *bop = bo; - err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args, - sizeof(args)); - if (err < 0) - return -errno; + return 0; - return 0; +free: + free(bo); + return err; } diff --git a/lib/libdrm/tegra/tegra.h b/lib/libdrm/tegra/tegra.h index 31b0995ad..8f3c0554f 100644 --- a/lib/libdrm/tegra/tegra.h +++ b/lib/libdrm/tegra/tegra.h @@ -28,33 +28,100 @@ #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; -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); 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); +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); + +struct drm_tegra_channel; +struct drm_tegra_mapping; +struct drm_tegra_pushbuf; +struct drm_tegra_job; +struct drm_tegra_syncpoint; -struct drm_tegra_bo_tiling { - uint32_t mode; - uint32_t value; +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_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); +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); + +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_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__ */ diff --git a/lib/libdrm/tests/amdgpu/amdgpu_test.c b/lib/libdrm/tests/amdgpu/amdgpu_test.c index 6a2ff8ba2..7f3aee40b 100644 --- a/lib/libdrm/tests/amdgpu/amdgpu_test.c +++ b/lib/libdrm/tests/amdgpu/amdgpu_test.c @@ -73,6 +73,7 @@ #define SYNCOBJ_TIMELINE_TESTS_STR "SYNCOBJ TIMELINE Tests" #define SECURITY_TESTS_STR "Security Tests" #define HOTUNPLUG_TESTS_STR "Hotunplug Tests" +#define CP_DMA_TESTS_STR "CP DMA Tests" /** * Open handles for amdgpu devices @@ -163,6 +164,12 @@ static CU_SuiteInfo suites[] = { .pCleanupFunc = suite_hotunplug_tests_clean, .pTests = hotunplug_tests, }, + { + .pName = CP_DMA_TESTS_STR, + .pInitFunc = suite_cp_dma_tests_init, + .pCleanupFunc = suite_cp_dma_tests_clean, + .pTests = cp_dma_tests, + }, CU_SUITE_INFO_NULL, }; @@ -232,6 +239,10 @@ static Suites_Active_Status suites_active_stat[] = { .pName = HOTUNPLUG_TESTS_STR, .pActive = suite_hotunplug_tests_enable, }, + { + .pName = CP_DMA_TESTS_STR, + .pActive = suite_cp_dma_tests_enable, + }, }; @@ -311,6 +322,10 @@ static int amdgpu_open_devices(int open_render_node) int fd; drmVersionPtr version; + for (i = 0; i < MAX_CARDS_SUPPORTED; i++) { + drm_amdgpu[i] = -1; + } + drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED); if (drm_count < 0) { diff --git a/lib/libdrm/tests/amdgpu/amdgpu_test.h b/lib/libdrm/tests/amdgpu/amdgpu_test.h index 2c43a2faf..9f4453db6 100644 --- a/lib/libdrm/tests/amdgpu/amdgpu_test.h +++ b/lib/libdrm/tests/amdgpu/amdgpu_test.h @@ -261,11 +261,32 @@ CU_BOOL suite_syncobj_timeline_tests_enable(void); */ extern CU_TestInfo syncobj_timeline_tests[]; + +/** + * Initialize cp dma test suite + */ +int suite_cp_dma_tests_init(); + +/** + * Deinitialize cp dma test suite + */ +int suite_cp_dma_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_cp_dma_tests_enable(void); + +/** + * Tests in cp dma test suite + */ +extern CU_TestInfo cp_dma_tests[]; + void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip_type); void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip_type); void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, - int hang); -void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring); + int version, int hang); +void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring, int version); /** * Initialize security test suite diff --git a/lib/libdrm/tests/amdgpu/basic_tests.c b/lib/libdrm/tests/amdgpu/basic_tests.c index 8afd05c19..688260d96 100644 --- a/lib/libdrm/tests/amdgpu/basic_tests.c +++ b/lib/libdrm/tests/amdgpu/basic_tests.c @@ -292,6 +292,8 @@ CU_TestInfo basic_tests[] = { #define PKT3_SET_SH_REG 0x76 #define PACKET3_SET_SH_REG_START 0x00002c00 +#define PKT3_SET_SH_REG_INDEX 0x9B + #define PACKET3_DISPATCH_DIRECT 0x15 #define PACKET3_EVENT_WRITE 0x46 #define PACKET3_ACQUIRE_MEM 0x58 @@ -351,6 +353,12 @@ static const uint32_t bufferclear_cs_shader_gfx9[] = { 0xbf810000 }; +static const uint32_t bufferclear_cs_shader_gfx10[] = { + 0xD7460004, 0x04010C08, 0x7E000204, 0x7E020205, + 0x7E040206, 0x7E060207, 0xE01C2000, 0x80000004, + 0xBF810000 +}; + static const uint32_t bufferclear_cs_shader_registers_gfx9[][2] = { {0x2e12, 0x000C0041}, //{ mmCOMPUTE_PGM_RSRC1, 0x000C0041 }, {0x2e13, 0x00000090}, //{ mmCOMPUTE_PGM_RSRC2, 0x00000090 }, @@ -367,6 +375,11 @@ static const uint32_t buffercopy_cs_shader_gfx9[] = { 0xe01c2000, 0x80010200, 0xbf810000 }; +static const uint32_t buffercopy_cs_shader_gfx10[] = { + 0xD7460001, 0x04010C08, 0xE00C2000, 0x80000201, + 0xBF8C3F70, 0xE01C2000, 0x80010201, 0xBF810000 +}; + static const uint32_t preamblecache_gfx9[] = { 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0, 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000, @@ -390,6 +403,32 @@ static const uint32_t preamblecache_gfx9[] = { 0xc0017900, 0x24b, 0x0 }; +static const uint32_t preamblecache_gfx10[] = { + 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0, + 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000, + 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0, + 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0, + 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0, + 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0, + 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0, + 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, + 0xc0046900, 0x310, 0, 0x3, 0, 0x100000, 0xc0026900, 0x316, 0xe, 0x20, + 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0, + 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x6, 0x0, + 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0, + 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff, + 0xc0016900, 0x314, 0x0, 0xc0016900, 0x10a, 0, 0xc0016900, 0x2a6, 0, 0xc0016900, 0x210, 0, + 0xc0016900, 0x2db, 0, 0xc0016900, 0x1d4, 0, 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1, 0xc0016900, 0xe, 0x2, + 0xc0016900, 0x206, 0x300, 0xc0016900, 0x212, 0x200, 0xc0017900, 0x7b, 0x20, 0xc0017a00, 0x20000243, 0x0, + 0xc0017900, 0x249, 0, 0xc0017900, 0x24a, 0, 0xc0017900, 0x24b, 0, 0xc0017900, 0x259, 0xffffffff, + 0xc0017900, 0x25f, 0, 0xc0017900, 0x260, 0, 0xc0017900, 0x262, 0, + 0xc0017600, 0x45, 0x0, 0xc0017600, 0x6, 0x0, + 0xc0067600, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc0067600, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 +}; + enum ps_type { PS_CONST, PS_TEX, @@ -442,6 +481,39 @@ static const uint32_t ps_const_context_reg_gfx9[][2] = { {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 } }; +static const uint32_t ps_const_shader_gfx10[] = { + 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203, + 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, + 0xF8001C0F, 0x00000100, 0xBF810000 +}; + +static const uint32_t ps_const_shader_patchinfo_code_size_gfx10 = 6; + +static const uint32_t ps_const_shader_patchinfo_code_gfx10[][10][6] = { + {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000300 }, + { 0x5E000300, 0x5E020702, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 }, + { 0xD7690000, 0x00020300, 0xD7690001, 0x00020702, 0xF8001C0F, 0x00000100 }, + { 0xD7680000, 0x00020300, 0xD7680001, 0x00020702, 0xF8001C0F, 0x00000100 }, + { 0xD76A0000, 0x00020300, 0xD76A0001, 0x00020702, 0xF8001C0F, 0x00000100 }, + { 0xD76B0000, 0x00020300, 0xD76B0001, 0x00020702, 0xF8001C0F, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x03020100 } + } +}; + +static const uint32_t ps_const_shader_patchinfo_offset_gfx10[] = { + 0x00000004 +}; + +static const uint32_t ps_num_sh_registers_gfx10 = 2; + +static const uint32_t ps_const_sh_registers_gfx10[][2] = { + {0x2C0A, 0x000C0000},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0000 }, + {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 } +}; + static const uint32_t ps_tex_shader_gfx9[] = { 0xBEFC000C, 0xBE8E017E, 0xBEFE077E, 0xD4180000, 0xD4190001, 0xD41C0100, 0xD41D0101, 0xF0800F00, @@ -485,6 +557,34 @@ static const uint32_t ps_tex_context_reg_gfx9[][2] = { {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 } }; +static const uint32_t ps_tex_shader_gfx10[] = { + 0xBEFC030C, 0xBE8E047E, 0xBEFE0A7E, 0xC8080000, + 0xC80C0100, 0xC8090001, 0xC80D0101, 0xF0800F0A, + 0x00400402, 0x00000003, 0xBEFE040E, 0xBF8C0F70, + 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000, + 0xF8001C0F, 0x00000100, 0xBF810000 +}; + +static const uint32_t ps_tex_shader_patchinfo_offset_gfx10[] = { + 0x0000000C +}; + +static const uint32_t ps_tex_shader_patchinfo_code_size_gfx10 = 6; + +static const uint32_t ps_tex_shader_patchinfo_code_gfx10[][10][6] = { + {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001890, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001801, 0x00000004 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000504 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF8001803, 0x00000704 }, + { 0x5E000B04, 0x5E020F06, 0xBF800000, 0xBF800000, 0xF8001C0F, 0x00000100 }, + { 0xD7690000, 0x00020B04, 0xD7690001, 0x00020F06, 0xF8001C0F, 0x00000100 }, + { 0xD7680000, 0x00020B04, 0xD7680001, 0x00020F06, 0xF8001C0F, 0x00000100 }, + { 0xD76A0000, 0x00020B04, 0xD76A0001, 0x00020F06, 0xF8001C0F, 0x00000100 }, + { 0xD76B0000, 0x00020B04, 0xD76B0001, 0x00020F06, 0xF8001C0F, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xF800180F, 0x07060504 } + } +}; + static const uint32_t vs_RectPosTexFast_shader_gfx9[] = { 0x7E000B00, 0x020000F3, 0xD042000A, 0x00010100, 0x7E020202, 0x7E040200, 0x020000F3, 0x7E060206, @@ -496,6 +596,17 @@ static const uint32_t vs_RectPosTexFast_shader_gfx9[] = { 0xC400020F, 0x05060403, 0xBF810000 }; +static const uint32_t vs_RectPosTexFast_shader_gfx10[] = { + 0x7E000B00, 0x060000F3, 0x7E020202, 0x7E040206, + 0x7C040080, 0x060000F3, 0xD5010001, 0x01AA0200, + 0x7E060203, 0xD5010002, 0x01AA0404, 0x7E080207, + 0x7C040080, 0xD5010000, 0x01A80101, 0xD5010001, + 0x01AA0601, 0x7E060208, 0x7E0A02F2, 0xD5010002, + 0x01A80902, 0xD5010004, 0x01AA0805, 0x7E0C0209, + 0xF80008CF, 0x05030100, 0xF800020F, 0x05060402, + 0xBF810000 +}; + static const uint32_t cached_cmd_gfx9[] = { 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0, 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020, @@ -507,6 +618,17 @@ static const uint32_t cached_cmd_gfx9[] = { 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0 }; +static const uint32_t cached_cmd_gfx10[] = { + 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0, + 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020, + 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf, + 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x18, + 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0, + 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011, + 0xc0026900, 0x292, 0x20, 0x6020000, + 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0 +}; + unsigned int memcpy_ps_hang[] = { 0xFFFFFFFF, 0xBEFE0A7E, 0xBEFC0304, 0xC0C20100, 0xC0800300, 0xC8080000, 0xC80C0100, 0xC8090001, @@ -546,6 +668,18 @@ struct amdgpu_test_shader memcpy_cs_hang_slow_rv = { 1 }; +unsigned int memcpy_cs_hang_slow_nv_codes[] = { + 0xd7460000, 0x04010c08, 0xe00c2000, 0x80000100, + 0xbf8c0f70, 0xe01ca000, 0x80010100, 0xbf810000 +}; + +struct amdgpu_test_shader memcpy_cs_hang_slow_nv = { + memcpy_cs_hang_slow_nv_codes, + 4, + 3, + 1 +}; + unsigned int memcpy_ps_hang_slow_ai_codes[] = { 0xbefc000c, 0xbe8e017e, 0xbefe077e, 0xd4080000, 0xd4090001, 0xd40c0100, 0xd40d0101, 0xf0800f00, @@ -2335,6 +2469,9 @@ static int amdgpu_dispatch_load_cs_shader_hang_slow(uint32_t *ptr, int family) case AMDGPU_FAMILY_RV: shader = &memcpy_cs_hang_slow_rv; break; + case AMDGPU_FAMILY_NV: + shader = &memcpy_cs_hang_slow_nv; + break; default: return -1; break; @@ -2355,19 +2492,30 @@ static int amdgpu_dispatch_load_cs_shader_hang_slow(uint32_t *ptr, int family) } static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, - int cs_type) + int cs_type, + uint32_t version) { uint32_t shader_size; const uint32_t *shader; switch (cs_type) { case CS_BUFFERCLEAR: - shader = bufferclear_cs_shader_gfx9; - shader_size = sizeof(bufferclear_cs_shader_gfx9); + if (version == 9) { + shader = bufferclear_cs_shader_gfx9; + shader_size = sizeof(bufferclear_cs_shader_gfx9); + } else if (version == 10) { + shader = bufferclear_cs_shader_gfx10; + shader_size = sizeof(bufferclear_cs_shader_gfx10); + } break; case CS_BUFFERCOPY: - shader = buffercopy_cs_shader_gfx9; - shader_size = sizeof(buffercopy_cs_shader_gfx9); + if (version == 9) { + shader = buffercopy_cs_shader_gfx9; + shader_size = sizeof(buffercopy_cs_shader_gfx9); + } else if (version == 10) { + shader = buffercopy_cs_shader_gfx10; + shader_size = sizeof(buffercopy_cs_shader_gfx10); + } break; case CS_HANG: shader = memcpy_ps_hang; @@ -2382,7 +2530,7 @@ static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, return 0; } -static int amdgpu_dispatch_init(uint32_t *ptr, uint32_t ip_type) +static int amdgpu_dispatch_init(uint32_t *ptr, uint32_t ip_type, uint32_t version) { int i = 0; @@ -2404,29 +2552,57 @@ static int amdgpu_dispatch_init(uint32_t *ptr, uint32_t ip_type) ptr[i++] = 0x218; ptr[i++] = 0; + /* Set new sh registers in GFX10 to 0 */ + if (version == 10) { + /* mmCOMPUTE_SHADER_CHKSUM */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x22a; + ptr[i++] = 0; + /* mmCOMPUTE_REQ_CTRL */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 6); + ptr[i++] = 0x222; + i += 6; + /* mmCP_COHER_START_DELAY */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x7b; + ptr[i++] = 0x20; + } return i; } -static int amdgpu_dispatch_write_cumask(uint32_t *ptr) +static int amdgpu_dispatch_write_cumask(uint32_t *ptr, uint32_t version) { int i = 0; /* Issue commands to set cu mask used in current dispatch */ - /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */ - ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); - ptr[i++] = 0x216; - ptr[i++] = 0xffffffff; - ptr[i++] = 0xffffffff; - /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */ - ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); - ptr[i++] = 0x219; - ptr[i++] = 0xffffffff; - ptr[i++] = 0xffffffff; + if (version == 9) { + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x216; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x219; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + } else if (version == 10) { + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG_INDEX, 2); + ptr[i++] = 0x30000216; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG_INDEX, 2); + ptr[i++] = 0x30000219; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + } return i; } -static int amdgpu_dispatch_write2hw(uint32_t *ptr, uint64_t shader_addr) +static int amdgpu_dispatch_write2hw(uint32_t *ptr, uint64_t shader_addr, uint32_t version) { int i, j; @@ -2446,12 +2622,20 @@ static int amdgpu_dispatch_write2hw(uint32_t *ptr, uint64_t shader_addr) ptr[i++] = bufferclear_cs_shader_registers_gfx9[j][1]; } + if (version == 10) { + /* mmCOMPUTE_PGM_RSRC3 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x228; + ptr[i++] = 0; + } + return i; } static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, uint32_t ip_type, - uint32_t ring) + uint32_t ring, + uint32_t version) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_dst, bo_shader, bo_cmd, resources[3]; @@ -2487,7 +2671,7 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); memset(ptr_shader, 0, bo_shader_size); - r = amdgpu_dispatch_load_cs_shader(ptr_shader, CS_BUFFERCLEAR); + r = amdgpu_dispatch_load_cs_shader(ptr_shader, CS_BUFFERCLEAR, version); CU_ASSERT_EQUAL(r, 0); r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, @@ -2497,13 +2681,13 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); i = 0; - i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type, version); /* Issue commands to set cu mask used in current dispatch */ - i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + i += amdgpu_dispatch_write_cumask(ptr_cmd + i, version); /* Writes shader state to HW */ - i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader, version); /* Write constant data */ /* Writes the UAV constant data to the SGPRs. */ @@ -2512,7 +2696,10 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, ptr_cmd[i++] = mc_address_dst; ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; ptr_cmd[i++] = 0x400; - ptr_cmd[i++] = 0x74fac; + if (version == 9) + ptr_cmd[i++] = 0x74fac; + else if (version == 10) + ptr_cmd[i++] = 0x1104bfac; /* Sets a range of pixel shader constants */ ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); @@ -2594,6 +2781,7 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, uint32_t ip_type, uint32_t ring, + uint32_t version, int hang) { amdgpu_context_handle context_handle; @@ -2633,7 +2821,7 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, memset(ptr_shader, 0, bo_shader_size); cs_type = hang ? CS_HANG : CS_BUFFERCOPY; - r = amdgpu_dispatch_load_cs_shader(ptr_shader, cs_type); + r = amdgpu_dispatch_load_cs_shader(ptr_shader, cs_type, version); CU_ASSERT_EQUAL(r, 0); r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, @@ -2651,13 +2839,13 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, memset(ptr_src, 0x55, bo_dst_size); i = 0; - i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type, version); /* Issue commands to set cu mask used in current dispatch */ - i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + i += amdgpu_dispatch_write_cumask(ptr_cmd + i, version); /* Writes shader state to HW */ - i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader, version); /* Write constant data */ /* Writes the texture resource constants data to the SGPRs */ @@ -2666,7 +2854,10 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, ptr_cmd[i++] = mc_address_src; ptr_cmd[i++] = (mc_address_src >> 32) | 0x100000; ptr_cmd[i++] = 0x400; - ptr_cmd[i++] = 0x74fac; + if (version == 9) + ptr_cmd[i++] = 0x74fac; + else if (version == 10) + ptr_cmd[i++] = 0x1104bfac; /* Writes the UAV constant data to the SGPRs. */ ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); @@ -2674,7 +2865,10 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, ptr_cmd[i++] = mc_address_dst; ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; ptr_cmd[i++] = 0x400; - ptr_cmd[i++] = 0x74fac; + if (version == 9) + ptr_cmd[i++] = 0x74fac; + else if (version == 10) + ptr_cmd[i++] = 0x1104bfac; /* clear mmCOMPUTE_RESOURCE_LIMITS */ ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); @@ -2758,16 +2952,22 @@ static void amdgpu_compute_dispatch_test(void) { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no compute ring\n"); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); - amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id, 0); + amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id, version); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id, version, 0); } } @@ -2775,16 +2975,22 @@ static void amdgpu_gfx_dispatch_test(void) { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no graphics ring\n"); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); - amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id, 0); + amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id, version); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id, version, 0); } } @@ -2792,22 +2998,28 @@ void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no ring for ip %d\n", ip_type); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); - amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 1); - amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, version, 0); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, version, 1); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, version, 0); } } static void amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_handle, - uint32_t ip_type, uint32_t ring) + uint32_t ip_type, uint32_t ring, int version) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_src, bo_dst, bo_shader, bo_cmd, resources[4]; @@ -2866,13 +3078,13 @@ static void amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_ha memset(ptr_src, 0x55, bo_dst_size); i = 0; - i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type, version); /* Issue commands to set cu mask used in current dispatch */ - i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + i += amdgpu_dispatch_write_cumask(ptr_cmd + i, version); /* Writes shader state to HW */ - i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader, version); /* Write constant data */ /* Writes the texture resource constants data to the SGPRs */ @@ -2881,7 +3093,10 @@ static void amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_ha ptr_cmd[i++] = mc_address_src; ptr_cmd[i++] = (mc_address_src >> 32) | 0x100000; ptr_cmd[i++] = 0x400000; - ptr_cmd[i++] = 0x74fac; + if (version == 9) + ptr_cmd[i++] = 0x74fac; + else if (version == 10) + ptr_cmd[i++] = 0x1104bfac; /* Writes the UAV constant data to the SGPRs. */ ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); @@ -2889,7 +3104,10 @@ static void amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_ha ptr_cmd[i++] = mc_address_dst; ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; ptr_cmd[i++] = 0x400000; - ptr_cmd[i++] = 0x74fac; + if (version == 9) + ptr_cmd[i++] = 0x74fac; + else if (version == 10) + ptr_cmd[i++] = 0x1104bfac; /* clear mmCOMPUTE_RESOURCE_LIMITS */ ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); @@ -2961,17 +3179,23 @@ void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32 { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no ring for ip %d\n", ip_type); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); - amdgpu_memcpy_dispatch_hang_slow_test(device_handle, ip_type, ring_id); - amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, version, 0); + amdgpu_memcpy_dispatch_hang_slow_test(device_handle, ip_type, ring_id, version); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, version, 0); } } @@ -3004,7 +3228,7 @@ static int amdgpu_draw_load_ps_shader_hang_slow(uint32_t *ptr, int family) return 0; } -static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) +static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type, uint32_t version) { int i; uint32_t shader_offset= 256; @@ -3016,18 +3240,34 @@ static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) switch (ps_type) { case PS_CONST: - shader = ps_const_shader_gfx9; - shader_size = sizeof(ps_const_shader_gfx9); - patchinfo_code = (const uint32_t *)ps_const_shader_patchinfo_code_gfx9; - patchinfo_code_size = ps_const_shader_patchinfo_code_size_gfx9; - patchcode_offset = ps_const_shader_patchinfo_offset_gfx9; + if (version == 9) { + shader = ps_const_shader_gfx9; + shader_size = sizeof(ps_const_shader_gfx9); + patchinfo_code = (const uint32_t *)ps_const_shader_patchinfo_code_gfx9; + patchinfo_code_size = ps_const_shader_patchinfo_code_size_gfx9; + patchcode_offset = ps_const_shader_patchinfo_offset_gfx9; + } else if (version == 10){ + shader = ps_const_shader_gfx10; + shader_size = sizeof(ps_const_shader_gfx10); + patchinfo_code = (const uint32_t *)ps_const_shader_patchinfo_code_gfx10; + patchinfo_code_size = ps_const_shader_patchinfo_code_size_gfx10; + patchcode_offset = ps_const_shader_patchinfo_offset_gfx10; + } break; case PS_TEX: - shader = ps_tex_shader_gfx9; - shader_size = sizeof(ps_tex_shader_gfx9); - patchinfo_code = (const uint32_t *)ps_tex_shader_patchinfo_code_gfx9; - patchinfo_code_size = ps_tex_shader_patchinfo_code_size_gfx9; - patchcode_offset = ps_tex_shader_patchinfo_offset_gfx9; + if (version == 9) { + shader = ps_tex_shader_gfx9; + shader_size = sizeof(ps_tex_shader_gfx9); + patchinfo_code = (const uint32_t *)ps_tex_shader_patchinfo_code_gfx9; + patchinfo_code_size = ps_tex_shader_patchinfo_code_size_gfx9; + patchcode_offset = ps_tex_shader_patchinfo_offset_gfx9; + } else if (version == 10) { + shader = ps_tex_shader_gfx10; + shader_size = sizeof(ps_tex_shader_gfx10); + patchinfo_code = (const uint32_t *)ps_tex_shader_patchinfo_code_gfx10; + patchinfo_code_size = ps_tex_shader_patchinfo_code_size_gfx10; + patchcode_offset = ps_tex_shader_patchinfo_offset_gfx10; + } break; case PS_HANG: shader = memcpy_ps_hang; @@ -3059,20 +3299,25 @@ static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) } /* load RectPosTexFast_VS */ -static int amdgpu_draw_load_vs_shader(uint8_t *ptr) +static int amdgpu_draw_load_vs_shader(uint8_t *ptr, uint32_t version) { const uint32_t *shader; uint32_t shader_size; - shader = vs_RectPosTexFast_shader_gfx9; - shader_size = sizeof(vs_RectPosTexFast_shader_gfx9); + if (version == 9) { + shader = vs_RectPosTexFast_shader_gfx9; + shader_size = sizeof(vs_RectPosTexFast_shader_gfx9); + } else if (version == 10) { + shader = vs_RectPosTexFast_shader_gfx10; + shader_size = sizeof(vs_RectPosTexFast_shader_gfx10); + } memcpy(ptr, shader, shader_size); return 0; } -static int amdgpu_draw_init(uint32_t *ptr) +static int amdgpu_draw_init(uint32_t *ptr, uint32_t version) { int i = 0; const uint32_t *preamblecache_ptr; @@ -3083,8 +3328,13 @@ static int amdgpu_draw_init(uint32_t *ptr) ptr[i++] = 0x80000000; ptr[i++] = 0x80000000; - preamblecache_ptr = preamblecache_gfx9; - preamblecache_size = sizeof(preamblecache_gfx9); + if (version == 9) { + preamblecache_ptr = preamblecache_gfx9; + preamblecache_size = sizeof(preamblecache_gfx9); + } else if (version == 10) { + preamblecache_ptr = preamblecache_gfx10; + preamblecache_size = sizeof(preamblecache_gfx10); + } memcpy(ptr + i, preamblecache_ptr, preamblecache_size); return i + preamblecache_size/sizeof(uint32_t); @@ -3092,41 +3342,95 @@ static int amdgpu_draw_init(uint32_t *ptr) static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, uint64_t dst_addr, + uint32_t version, int hang_slow) { int i = 0; /* setup color buffer */ - /* offset reg - 0xA318 CB_COLOR0_BASE - 0xA319 CB_COLOR0_BASE_EXT - 0xA31A CB_COLOR0_ATTRIB2 - 0xA31B CB_COLOR0_VIEW - 0xA31C CB_COLOR0_INFO - 0xA31D CB_COLOR0_ATTRIB - 0xA31E CB_COLOR0_DCC_CONTROL - 0xA31F CB_COLOR0_CMASK - 0xA320 CB_COLOR0_CMASK_BASE_EXT - 0xA321 CB_COLOR0_FMASK - 0xA322 CB_COLOR0_FMASK_BASE_EXT - 0xA323 CB_COLOR0_CLEAR_WORD0 - 0xA324 CB_COLOR0_CLEAR_WORD1 - 0xA325 CB_COLOR0_DCC_BASE - 0xA326 CB_COLOR0_DCC_BASE_EXT */ - ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 15); - ptr[i++] = 0x318; - ptr[i++] = dst_addr >> 8; - ptr[i++] = dst_addr >> 40; - ptr[i++] = hang_slow ? 0x1ffc7ff : 0x7c01f; - ptr[i++] = 0; - ptr[i++] = 0x50438; - ptr[i++] = 0x10140000; - i += 9; + if (version == 9) { + /* offset reg + 0xA318 CB_COLOR0_BASE + 0xA319 CB_COLOR0_BASE_EXT + 0xA31A CB_COLOR0_ATTRIB2 + 0xA31B CB_COLOR0_VIEW + 0xA31C CB_COLOR0_INFO + 0xA31D CB_COLOR0_ATTRIB + 0xA31E CB_COLOR0_DCC_CONTROL + 0xA31F CB_COLOR0_CMASK + 0xA320 CB_COLOR0_CMASK_BASE_EXT + 0xA321 CB_COLOR0_FMASK + 0xA322 CB_COLOR0_FMASK_BASE_EXT + 0xA323 CB_COLOR0_CLEAR_WORD0 + 0xA324 CB_COLOR0_CLEAR_WORD1 + 0xA325 CB_COLOR0_DCC_BASE + 0xA326 CB_COLOR0_DCC_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 15); + ptr[i++] = 0x318; + ptr[i++] = dst_addr >> 8; + ptr[i++] = dst_addr >> 40; + ptr[i++] = hang_slow ? 0x3ffc7ff : 0x7c01f; + ptr[i++] = 0; + ptr[i++] = 0x50438; + ptr[i++] = 0x10140000; + i += 9; + + /* mmCB_MRT0_EPITCH */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1e8; + ptr[i++] = hang_slow ? 0xfff : 0x1f; + } else if (version == 10) { + /* 0xA318 CB_COLOR0_BASE + 0xA319 CB_COLOR0_PITCH + 0xA31A CB_COLOR0_SLICE + 0xA31B CB_COLOR0_VIEW + 0xA31C CB_COLOR0_INFO + 0xA31D CB_COLOR0_ATTRIB + 0xA31E CB_COLOR0_DCC_CONTROL + 0xA31F CB_COLOR0_CMASK + 0xA320 CB_COLOR0_CMASK_SLICE + 0xA321 CB_COLOR0_FMASK + 0xA322 CB_COLOR0_FMASK_SLICE + 0xA323 CB_COLOR0_CLEAR_WORD0 + 0xA324 CB_COLOR0_CLEAR_WORD1 + 0xA325 CB_COLOR0_DCC_BASE */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 14); + ptr[i++] = 0x318; + ptr[i++] = dst_addr >> 8; + i += 3; + ptr[i++] = 0x50438; + i += 9; + + /* 0xA390 CB_COLOR0_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x390; + ptr[i++] = dst_addr >> 40; + + /* 0xA398 CB_COLOR0_CMASK_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x398; + ptr[i++] = 0; - /* mmCB_MRT0_EPITCH */ - ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); - ptr[i++] = 0x1e8; - ptr[i++] = hang_slow ? 0x7ff : 0x1f; + /* 0xA3A0 CB_COLOR0_FMASK_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x3a0; + ptr[i++] = 0; + + /* 0xA3A8 CB_COLOR0_DCC_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x3a8; + ptr[i++] = 0; + + /* 0xA3B0 CB_COLOR0_ATTRIB2 */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x3b0; + ptr[i++] = hang_slow ? 0x3ffc7ff : 0x7c01f; + + /* 0xA3B8 CB_COLOR0_ATTRIB3 */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x3b8; + ptr[i++] = 0x9014000; + } /* 0xA32B CB_COLOR1_BASE */ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); @@ -3144,15 +3448,24 @@ static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, ptr[i++] = 9; /* Setup depth buffer */ - /* mmDB_Z_INFO */ - ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2); - ptr[i++] = 0xe; - i += 2; + if (version == 9) { + /* mmDB_Z_INFO */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2); + ptr[i++] = 0xe; + i += 2; + } else if (version == 10) { + /* mmDB_Z_INFO */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2); + ptr[i++] = 0x10; + i += 2; + } return i; } -static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr, int hang_slow) +static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr, + uint32_t version, + int hang_slow) { int i = 0; const uint32_t *cached_cmd_ptr; @@ -3168,7 +3481,10 @@ static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr, int hang_slo ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); ptr[i++] = 0xd7; - ptr[i++] = 1; + if (version == 9) + ptr[i++] = 1; + else if (version == 10) + ptr[i++] = 0; /* mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 16); @@ -3180,20 +3496,37 @@ static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr, int hang_slo ptr[i++] = 0x2f5; i += 2; - cached_cmd_ptr = cached_cmd_gfx9; - cached_cmd_size = sizeof(cached_cmd_gfx9); + if (version == 9) { + cached_cmd_ptr = cached_cmd_gfx9; + cached_cmd_size = sizeof(cached_cmd_gfx9); + } else if (version == 10) { + cached_cmd_ptr = cached_cmd_gfx10; + cached_cmd_size = sizeof(cached_cmd_gfx10); + } memcpy(ptr + i, cached_cmd_ptr, cached_cmd_size); if (hang_slow) *(ptr + i + 12) = 0x8000800; i += cached_cmd_size/sizeof(uint32_t); + if (version == 10) { + /* mmCB_RMI_GL2_CACHE_CONTROL */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x104; + ptr[i++] = 0x40aa0055; + /* mmDB_RMI_L2_CACHE_CONTROL */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1f; + ptr[i++] = 0x2a0055; + } + return i; } static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, int ps_type, uint64_t shader_addr, + uint32_t version, int hang_slow) { int i = 0; @@ -3203,10 +3536,21 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, ptr[i++] = 0x207; ptr[i++] = 0; - /* mmSPI_SHADER_PGM_RSRC3_VS */ - ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); - ptr[i++] = 0x46; - ptr[i++] = 0xffff; + if (version == 9) { + /* mmSPI_SHADER_PGM_RSRC3_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x46; + ptr[i++] = 0xffff; + } else if (version == 10) { + /* mmSPI_SHADER_PGM_RSRC3_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG_INDEX, 1); + ptr[i++] = 0x30000046; + ptr[i++] = 0xffff; + /* mmSPI_SHADER_PGM_RSRC4_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG_INDEX, 1); + ptr[i++] = 0x30000041; + ptr[i++] = 0xffff; + } /* mmSPI_SHADER_PGM_LO_VS...mmSPI_SHADER_PGM_HI_VS */ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); @@ -3217,7 +3561,10 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, /* mmSPI_SHADER_PGM_RSRC1_VS */ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); ptr[i++] = 0x4a; - ptr[i++] = 0xc0081; + if (version == 9) + ptr[i++] = 0xc0081; + else if (version == 10) + ptr[i++] = 0xc0041; /* mmSPI_SHADER_PGM_RSRC2_VS */ ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); ptr[i++] = 0x4b; @@ -3258,7 +3605,8 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, static int amdgpu_draw_ps_write2hw(uint32_t *ptr, int ps_type, - uint64_t shader_addr) + uint64_t shader_addr, + uint32_t version) { int i, j; const uint32_t *sh_registers; @@ -3266,9 +3614,14 @@ static int amdgpu_draw_ps_write2hw(uint32_t *ptr, uint32_t num_sh_reg, num_context_reg; if (ps_type == PS_CONST) { - sh_registers = (const uint32_t *)ps_const_sh_registers_gfx9; + if (version == 9) { + sh_registers = (const uint32_t *)ps_const_sh_registers_gfx9; + num_sh_reg = ps_num_sh_registers_gfx9; + } else if (version == 10) { + sh_registers = (const uint32_t *)ps_const_sh_registers_gfx10; + num_sh_reg = ps_num_sh_registers_gfx10; + } context_registers = (const uint32_t *)ps_const_context_reg_gfx9; - num_sh_reg = ps_num_sh_registers_gfx9; num_context_reg = ps_num_context_registers_gfx9; } else if (ps_type == PS_TEX) { sh_registers = (const uint32_t *)ps_tex_sh_registers_gfx9; @@ -3279,15 +3632,35 @@ static int amdgpu_draw_ps_write2hw(uint32_t *ptr, i = 0; - /* 0x2c07 SPI_SHADER_PGM_RSRC3_PS - 0x2c08 SPI_SHADER_PGM_LO_PS - 0x2c09 SPI_SHADER_PGM_HI_PS */ - shader_addr += 256 * 9; - ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3); - ptr[i++] = 0x7; - ptr[i++] = 0xffff; - ptr[i++] = shader_addr >> 8; - ptr[i++] = shader_addr >> 40; + if (version == 9) { + /* 0x2c07 SPI_SHADER_PGM_RSRC3_PS + 0x2c08 SPI_SHADER_PGM_LO_PS + 0x2c09 SPI_SHADER_PGM_HI_PS */ + /* multiplicator 9 is from SPI_SHADER_COL_FORMAT */ + shader_addr += 256 * 9; + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3); + ptr[i++] = 0x7; + ptr[i++] = 0xffff; + ptr[i++] = shader_addr >> 8; + ptr[i++] = shader_addr >> 40; + } else if (version == 10) { + shader_addr += 256 * 9; + /* 0x2c08 SPI_SHADER_PGM_LO_PS + 0x2c09 SPI_SHADER_PGM_HI_PS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x8; + ptr[i++] = shader_addr >> 8; + ptr[i++] = shader_addr >> 40; + + /* mmSPI_SHADER_PGM_RSRC3_PS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG_INDEX, 1); + ptr[i++] = 0x30000007; + ptr[i++] = 0xffff; + /* mmSPI_SHADER_PGM_RSRC4_PS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG_INDEX, 1); + ptr[i++] = 0x30000001; + ptr[i++] = 0xffff; + } for (j = 0; j < num_sh_reg; j++) { ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); @@ -3312,19 +3685,29 @@ static int amdgpu_draw_ps_write2hw(uint32_t *ptr, return i; } -static int amdgpu_draw_draw(uint32_t *ptr) +static int amdgpu_draw_draw(uint32_t *ptr, uint32_t version) { int i = 0; - /* mmIA_MULTI_VGT_PARAM */ - ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); - ptr[i++] = 0x40000258; - ptr[i++] = 0xd00ff; - - /* mmVGT_PRIMITIVE_TYPE */ - ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); - ptr[i++] = 0x10000242; - ptr[i++] = 0x11; + if (version == 9) { + /* mmIA_MULTI_VGT_PARAM */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x40000258; + ptr[i++] = 0xd00ff; + /* mmVGT_PRIMITIVE_TYPE */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x10000242; + ptr[i++] = 0x11; + } else if (version == 10) { + /* mmGE_CNTL */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x25b; + ptr[i++] = 0xff; + /* mmVGT_PRIMITIVE_TYPE */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x242; + ptr[i++] = 0x11; + } ptr[i++] = PACKET3(PACKET3_DRAW_INDEX_AUTO, 1); ptr[i++] = 3; @@ -3338,7 +3721,7 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, amdgpu_bo_handle bo_shader_vs, uint64_t mc_address_shader_ps, uint64_t mc_address_shader_vs, - uint32_t ring_id) + uint32_t ring_id, uint32_t version) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_dst, bo_cmd, resources[4]; @@ -3372,15 +3755,16 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); i = 0; - i += amdgpu_draw_init(ptr_cmd + i); + i += amdgpu_draw_init(ptr_cmd + i, version); - i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 0); + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, version, 0); - i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 0); + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, version, 0); - i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_vs, 0); + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_vs, + version, 0); - i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_ps); + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_ps, version); ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr_cmd[i++] = 0xc; @@ -3389,7 +3773,7 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, ptr_cmd[i++] = 0x33333333; ptr_cmd[i++] = 0x33333333; - i += amdgpu_draw_draw(ptr_cmd + i); + i += amdgpu_draw_draw(ptr_cmd + i, version); while (i & 7) ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ @@ -3447,7 +3831,7 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, } static void amdgpu_memset_draw_test(amdgpu_device_handle device_handle, - uint32_t ring) + uint32_t ring, int version) { amdgpu_bo_handle bo_shader_ps, bo_shader_vs; void *ptr_shader_ps; @@ -3471,14 +3855,15 @@ static void amdgpu_memset_draw_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); memset(ptr_shader_vs, 0, bo_shader_size); - r = amdgpu_draw_load_ps_shader(ptr_shader_ps, PS_CONST); + r = amdgpu_draw_load_ps_shader(ptr_shader_ps, PS_CONST, version); CU_ASSERT_EQUAL(r, 0); - r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + r = amdgpu_draw_load_vs_shader(ptr_shader_vs, version); CU_ASSERT_EQUAL(r, 0); amdgpu_memset_draw(device_handle, bo_shader_ps, bo_shader_vs, - mc_address_shader_ps, mc_address_shader_vs, ring); + mc_address_shader_ps, mc_address_shader_vs, + ring, version); r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_size); CU_ASSERT_EQUAL(r, 0); @@ -3492,7 +3877,7 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, amdgpu_bo_handle bo_shader_vs, uint64_t mc_address_shader_ps, uint64_t mc_address_shader_vs, - uint32_t ring, int hang) + uint32_t ring, int version, int hang) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_dst, bo_src, bo_cmd, resources[5]; @@ -3536,24 +3921,36 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, memset(ptr_src, 0x55, bo_size); i = 0; - i += amdgpu_draw_init(ptr_cmd + i); + i += amdgpu_draw_init(ptr_cmd + i, version); - i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 0); + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, version, 0); - i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 0); + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, version, 0); - i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_vs, 0); + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_vs, + version, 0); - i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps); + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps, version); ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 8); - ptr_cmd[i++] = 0xc; - ptr_cmd[i++] = mc_address_src >> 8; - ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; - ptr_cmd[i++] = 0x7c01f; - ptr_cmd[i++] = 0x90500fac; - ptr_cmd[i++] = 0x3e000; - i += 3; + if (version == 9) { + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; + ptr_cmd[i++] = 0x7c01f; + ptr_cmd[i++] = 0x90500fac; + ptr_cmd[i++] = 0x3e000; + i += 3; + } else if (version == 10) { + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0xc4b00000; + ptr_cmd[i++] = 0x8007c007; + ptr_cmd[i++] = 0x90500fac; + i += 2; + ptr_cmd[i++] = 0x400; + i++; + } ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr_cmd[i++] = 0x14; @@ -3564,7 +3961,7 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, ptr_cmd[i++] = 0x191; ptr_cmd[i++] = 0; - i += amdgpu_draw_draw(ptr_cmd + i); + i += amdgpu_draw_draw(ptr_cmd + i, version); while (i & 7) ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ @@ -3630,7 +4027,7 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, } void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, - int hang) + int version, int hang) { amdgpu_bo_handle bo_shader_ps, bo_shader_vs; void *ptr_shader_ps; @@ -3655,14 +4052,15 @@ void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, CU_ASSERT_EQUAL(r, 0); memset(ptr_shader_vs, 0, bo_shader_size); - r = amdgpu_draw_load_ps_shader(ptr_shader_ps, ps_type); + r = amdgpu_draw_load_ps_shader(ptr_shader_ps, ps_type, version); CU_ASSERT_EQUAL(r, 0); - r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + r = amdgpu_draw_load_vs_shader(ptr_shader_vs, version); CU_ASSERT_EQUAL(r, 0); amdgpu_memcpy_draw(device_handle, bo_shader_ps, bo_shader_vs, - mc_address_shader_ps, mc_address_shader_vs, ring, hang); + mc_address_shader_ps, mc_address_shader_vs, + ring, version, hang); r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_size); CU_ASSERT_EQUAL(r, 0); @@ -3675,20 +4073,26 @@ static void amdgpu_draw_test(void) { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no graphics ring\n"); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memset_draw_test(device_handle, ring_id); - amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + amdgpu_memset_draw_test(device_handle, ring_id, version); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 0); } } -void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring) +void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring, int version) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_shader_ps, bo_shader_vs; @@ -3744,7 +4148,7 @@ void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint3 r = amdgpu_draw_load_ps_shader_hang_slow(ptr_shader_ps, gpu_info.family_id); CU_ASSERT_EQUAL(r, 0); - r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + r = amdgpu_draw_load_vs_shader(ptr_shader_vs, version); CU_ASSERT_EQUAL(r, 0); r = amdgpu_bo_alloc_and_map(device_handle, bo_size, 4096, @@ -3762,25 +4166,35 @@ void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint3 memset(ptr_src, 0x55, bo_size); i = 0; - i += amdgpu_draw_init(ptr_cmd + i); + i += amdgpu_draw_init(ptr_cmd + i, version); - i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 1); + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, version, 1); - i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 1); + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, version, 1); i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, - mc_address_shader_vs, 1); + mc_address_shader_vs, version, 1); - i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps); + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps, version); ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 8); - ptr_cmd[i++] = 0xc; - ptr_cmd[i++] = mc_address_src >> 8; - ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; - ptr_cmd[i++] = 0x1ffc7ff; - ptr_cmd[i++] = 0x90500fac; - ptr_cmd[i++] = 0xffe000; - i += 3; + + if (version == 9) { + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; + ptr_cmd[i++] = 0x1ffcfff; + ptr_cmd[i++] = 0x90500fac; + ptr_cmd[i++] = 0x1ffe000; + i += 3; + } else if (version == 10) { + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0xc4b00000; + ptr_cmd[i++] = 0x81ffc1ff; + ptr_cmd[i++] = 0x90500fac; + i += 4; + } ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr_cmd[i++] = 0x14; @@ -3791,7 +4205,7 @@ void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint3 ptr_cmd[i++] = 0x191; ptr_cmd[i++] = 0; - i += amdgpu_draw_draw(ptr_cmd + i); + i += amdgpu_draw_draw(ptr_cmd + i, version); while (i & 7) ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ diff --git a/lib/libdrm/tests/amdgpu/cp_dma_tests.c b/lib/libdrm/tests/amdgpu/cp_dma_tests.c new file mode 100644 index 000000000..e82214fed --- /dev/null +++ b/lib/libdrm/tests/amdgpu/cp_dma_tests.c @@ -0,0 +1,533 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "CUnit/Basic.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" + +#define IB_SIZE 4096 +#define MAX_RESOURCES 8 + +#define DMA_SIZE 4097 +#define DMA_DATA_BYTE 0xea + +static bool do_p2p; + +static amdgpu_device_handle executing_device_handle; +static uint32_t executing_device_major_version; +static uint32_t executing_device_minor_version; + +static amdgpu_device_handle peer_exporting_device_handle; +static uint32_t peer_exporting_device_major_version; +static uint32_t peer_exporting_device_minor_version; + +static amdgpu_context_handle context_handle; +static amdgpu_bo_handle ib_handle; +static uint32_t *ib_cpu; +static uint64_t ib_mc_address; +static amdgpu_va_handle ib_va_handle; +static uint32_t num_dword; + +static amdgpu_bo_handle resources[MAX_RESOURCES]; +static unsigned num_resources; + +static uint8_t* reference_data; + +static void amdgpu_cp_dma_host_to_vram(void); +static void amdgpu_cp_dma_vram_to_host(void); +static void amdgpu_cp_dma_p2p_vram_to_vram(void); +static void amdgpu_cp_dma_p2p_host_to_vram(void); +static void amdgpu_cp_dma_p2p_vram_to_host(void); + +/** + * Tests in cp dma test suite + */ +CU_TestInfo cp_dma_tests[] = { + { "CP DMA write Host to VRAM", amdgpu_cp_dma_host_to_vram }, + { "CP DMA write VRAM to Host", amdgpu_cp_dma_vram_to_host }, + + { "Peer to Peer CP DMA write VRAM to VRAM", amdgpu_cp_dma_p2p_vram_to_vram }, + { "Peer to Peer CP DMA write Host to VRAM", amdgpu_cp_dma_p2p_host_to_vram }, + { "Peer to Peer CP DMA write VRAM to Host", amdgpu_cp_dma_p2p_vram_to_host }, + CU_TEST_INFO_NULL, +}; + +struct amdgpu_cp_dma_bo{ + amdgpu_bo_handle buf_handle; + amdgpu_va_handle va_handle; + uint64_t gpu_va; + uint64_t size; +}; + +static int allocate_bo_and_va(amdgpu_device_handle dev, + uint64_t size, uint64_t alignment, + uint32_t heap, uint64_t alloc_flags, + struct amdgpu_cp_dma_bo *bo) { + struct amdgpu_bo_alloc_request request = {}; + amdgpu_bo_handle buf_handle; + amdgpu_va_handle va_handle; + uint64_t vmc_addr; + int r; + + request.alloc_size = size; + request.phys_alignment = alignment; + request.preferred_heap = heap; + request.flags = alloc_flags; + + r = amdgpu_bo_alloc(dev, &request, &buf_handle); + if (r) + goto error_bo_alloc; + + r = amdgpu_va_range_alloc(dev, amdgpu_gpu_va_range_general, + size, alignment, 0, + &vmc_addr, &va_handle, 0); + if (r) + goto error_va_alloc; + + r = amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, + AMDGPU_VM_PAGE_READABLE | + AMDGPU_VM_PAGE_WRITEABLE | + AMDGPU_VM_PAGE_EXECUTABLE, + AMDGPU_VA_OP_MAP); + if (r) + goto error_va_map; + + bo->buf_handle = buf_handle; + bo->va_handle = va_handle; + bo->gpu_va = vmc_addr; + bo->size = size; + + return 0; + +error_va_map: + amdgpu_bo_va_op(buf_handle, 0, + size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP); + +error_va_alloc: + amdgpu_va_range_free(va_handle); + +error_bo_alloc: + amdgpu_bo_free(buf_handle); + + return r; +} + +static int import_dma_buf_to_bo(amdgpu_device_handle dev, + int dmabuf_fd, struct amdgpu_cp_dma_bo *bo) { + amdgpu_va_handle va_handle; + uint64_t vmc_addr; + int r; + struct amdgpu_bo_import_result bo_import_result = {}; + + r = amdgpu_bo_import(dev, amdgpu_bo_handle_type_dma_buf_fd, + dmabuf_fd, &bo_import_result); + if (r) + goto error_bo_import; + + r = amdgpu_va_range_alloc(dev, amdgpu_gpu_va_range_general, + bo_import_result.alloc_size, 0, 0, + &vmc_addr, &va_handle, 0); + if (r) + goto error_va_alloc; + + r = amdgpu_bo_va_op(bo_import_result.buf_handle, 0, + bo_import_result.alloc_size, vmc_addr, + AMDGPU_VM_PAGE_READABLE | + AMDGPU_VM_PAGE_WRITEABLE | + AMDGPU_VM_PAGE_EXECUTABLE, + AMDGPU_VA_OP_MAP); + if (r) + goto error_va_map; + + bo->buf_handle = bo_import_result.buf_handle; + bo->va_handle = va_handle; + bo->gpu_va = vmc_addr; + bo->size = bo_import_result.alloc_size; + + return 0; + +error_va_map: + amdgpu_bo_va_op(bo_import_result.buf_handle, 0, + bo_import_result.alloc_size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP); + +error_va_alloc: + amdgpu_va_range_free(va_handle); + +error_bo_import: + amdgpu_bo_free(bo_import_result.buf_handle); + + return r; +} + +static int free_bo(struct amdgpu_cp_dma_bo bo) { + int r; + r = amdgpu_bo_va_op(bo.buf_handle, 0, + bo.size, bo.gpu_va, 0, AMDGPU_VA_OP_UNMAP); + if(r) + return r; + + r = amdgpu_va_range_free(bo.va_handle); + if(r) + return r; + + r = amdgpu_bo_free(bo.buf_handle); + if(r) + return r; + + return 0; +} + +static int submit_and_sync() { + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t expired; + uint32_t family_id, chip_id, chip_rev; + unsigned gc_ip_type; + int r; + + r = amdgpu_bo_list_create(executing_device_handle, + num_resources, resources, + NULL, &ibs_request.resources); + if (r) + return r; + + family_id = executing_device_handle->info.family_id; + chip_id = executing_device_handle->info.chip_external_rev; + chip_rev = executing_device_handle->info.chip_rev; + + gc_ip_type = (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) ? + AMDGPU_HW_IP_COMPUTE : AMDGPU_HW_IP_GFX; + + ib_info.ib_mc_address = ib_mc_address; + ib_info.size = num_dword; + + ibs_request.ip_type = gc_ip_type; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + if (r) + return r; + + r = amdgpu_bo_list_destroy(ibs_request.resources); + if (r) + return r; + + fence_status.context = context_handle; + fence_status.ip_type = gc_ip_type; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + if (r) + return r; + + return 0; +} + +static void cp_dma_cmd(struct amdgpu_cp_dma_bo src_bo, + struct amdgpu_cp_dma_bo dst_bo) { + _Static_assert(DMA_SIZE < (1 << 26), "DMA size exceeds CP DMA maximium!"); + + ib_cpu[0] = 0xc0055000; + ib_cpu[1] = 0x80000000; + ib_cpu[2] = src_bo.gpu_va & 0x00000000ffffffff; + ib_cpu[3] = (src_bo.gpu_va & 0xffffffff00000000) >> 32; + ib_cpu[4] = dst_bo.gpu_va & 0x00000000ffffffff; + ib_cpu[5] = (dst_bo.gpu_va & 0xffffffff00000000) >> 32; + // size is read from the lower 26bits. + ib_cpu[6] = ((1 << 26) - 1) & DMA_SIZE; + ib_cpu[7] = 0xffff1000; + + num_dword = 8; + + resources[0] = src_bo.buf_handle; + resources[1] = dst_bo.buf_handle; + resources[2] = ib_handle; + num_resources = 3; +} + +static void amdgpu_cp_dma(uint32_t src_heap, uint32_t dst_heap) { + int r; + struct amdgpu_cp_dma_bo src_bo = {0}; + struct amdgpu_cp_dma_bo dst_bo = {0}; + void *src_bo_cpu; + void *dst_bo_cpu; + + /* allocate the src bo, set its data to DMA_DATA_BYTE */ + r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096, + src_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &src_bo); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_cpu_map(src_bo.buf_handle, (void **)&src_bo_cpu); + CU_ASSERT_EQUAL(r, 0); + memset(src_bo_cpu, DMA_DATA_BYTE, DMA_SIZE); + + r = amdgpu_bo_cpu_unmap(src_bo.buf_handle); + CU_ASSERT_EQUAL(r, 0); + + /* allocate the dst bo and clear its content to all 0 */ + r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096, + dst_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &dst_bo); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_cpu_map(dst_bo.buf_handle, (void **)&dst_bo_cpu); + CU_ASSERT_EQUAL(r, 0); + + _Static_assert(DMA_DATA_BYTE != 0, "Initialization data should be different from DMA data!"); + memset(dst_bo_cpu, 0, DMA_SIZE); + + /* record CP DMA command and dispatch the command */ + cp_dma_cmd(src_bo, dst_bo); + + r = submit_and_sync(); + CU_ASSERT_EQUAL(r, 0); + + /* verify the dst bo is filled with DMA_DATA_BYTE */ + CU_ASSERT_EQUAL(memcmp(dst_bo_cpu, reference_data, DMA_SIZE) == 0, true); + + r = amdgpu_bo_cpu_unmap(dst_bo.buf_handle); + CU_ASSERT_EQUAL(r, 0); + + r = free_bo(src_bo); + CU_ASSERT_EQUAL(r, 0); + + r = free_bo(dst_bo); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_cp_dma_p2p(uint32_t src_heap, uint32_t dst_heap) { + int r; + struct amdgpu_cp_dma_bo exported_bo = {0}; + int dma_buf_fd; + int dma_buf_fd_dup; + struct amdgpu_cp_dma_bo src_bo = {0}; + struct amdgpu_cp_dma_bo imported_dst_bo = {0}; + void *exported_bo_cpu; + void *src_bo_cpu; + + /* allocate a bo on the peer device and export it to dma-buf */ + r = allocate_bo_and_va(peer_exporting_device_handle, DMA_SIZE, 4096, + src_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &exported_bo); + CU_ASSERT_EQUAL(r, 0); + + /* map the exported bo and clear its content to 0 */ + _Static_assert(DMA_DATA_BYTE != 0, "Initialization data should be different from DMA data!"); + r = amdgpu_bo_cpu_map(exported_bo.buf_handle, (void **)&exported_bo_cpu); + CU_ASSERT_EQUAL(r, 0); + memset(exported_bo_cpu, 0, DMA_SIZE); + + r = amdgpu_bo_export(exported_bo.buf_handle, + amdgpu_bo_handle_type_dma_buf_fd, (uint32_t*)&dma_buf_fd); + CU_ASSERT_EQUAL(r, 0); + + // According to amdgpu_drm: + // "Buffer must be "imported" only using new "fd" + // (different from one used by "exporter")" + dma_buf_fd_dup = dup(dma_buf_fd); + r = close(dma_buf_fd); + CU_ASSERT_EQUAL(r, 0); + + /* import the dma-buf to the executing device, imported bo is the DMA destination */ + r = import_dma_buf_to_bo( + executing_device_handle, dma_buf_fd_dup, &imported_dst_bo); + CU_ASSERT_EQUAL(r, 0); + + r = close(dma_buf_fd_dup); + CU_ASSERT_EQUAL(r, 0); + + /* allocate the src bo and set its content to DMA_DATA_BYTE */ + r = allocate_bo_and_va(executing_device_handle, DMA_SIZE, 4096, + dst_heap, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &src_bo); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_cpu_map(src_bo.buf_handle, (void **)&src_bo_cpu); + CU_ASSERT_EQUAL(r, 0); + + memset(src_bo_cpu, DMA_DATA_BYTE, DMA_SIZE); + + r = amdgpu_bo_cpu_unmap(src_bo.buf_handle); + CU_ASSERT_EQUAL(r, 0); + + /* record CP DMA command and dispatch the command */ + cp_dma_cmd(src_bo, imported_dst_bo); + + r = submit_and_sync(); + CU_ASSERT_EQUAL(r, 0); + + /* verify the bo from the peer device is filled with DMA_DATA_BYTE */ + CU_ASSERT_EQUAL(memcmp(exported_bo_cpu, reference_data, DMA_SIZE) == 0, true); + + r = amdgpu_bo_cpu_unmap(exported_bo.buf_handle); + CU_ASSERT_EQUAL(r, 0); + + r = free_bo(exported_bo); + CU_ASSERT_EQUAL(r, 0); + + r = free_bo(imported_dst_bo); + CU_ASSERT_EQUAL(r, 0); + + r = free_bo(src_bo); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_cp_dma_host_to_vram(void) { + amdgpu_cp_dma(AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_DOMAIN_VRAM); +} + +static void amdgpu_cp_dma_vram_to_host(void) { + amdgpu_cp_dma(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_GTT); +} + +static void amdgpu_cp_dma_p2p_vram_to_vram(void) { + amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_VRAM); +} + +static void amdgpu_cp_dma_p2p_host_to_vram(void) { + amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_DOMAIN_VRAM); +} + +static void amdgpu_cp_dma_p2p_vram_to_host(void) { + amdgpu_cp_dma_p2p(AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_GTT); +} + +int suite_cp_dma_tests_init() { + int r; + + r = amdgpu_device_initialize(drm_amdgpu[0], + &executing_device_major_version, + &executing_device_minor_version, + &executing_device_handle); + if (r) + return CUE_SINIT_FAILED; + + r = amdgpu_cs_ctx_create(executing_device_handle, &context_handle); + if (r) + return CUE_SINIT_FAILED; + + r = amdgpu_bo_alloc_and_map(executing_device_handle, IB_SIZE, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_handle, (void**)&ib_cpu, + &ib_mc_address, &ib_va_handle); + if (r) + return CUE_SINIT_FAILED; + + if (do_p2p) { + r = amdgpu_device_initialize(drm_amdgpu[1], + &peer_exporting_device_major_version, + &peer_exporting_device_minor_version, + &peer_exporting_device_handle); + + if (r) + return CUE_SINIT_FAILED; + } + + reference_data = (uint8_t*)malloc(DMA_SIZE); + if (!reference_data) + return CUE_SINIT_FAILED; + memset(reference_data, DMA_DATA_BYTE, DMA_SIZE); + + return CUE_SUCCESS; +} + +int suite_cp_dma_tests_clean() { + int r; + + free(reference_data); + + r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, + ib_mc_address, IB_SIZE); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_cs_ctx_free(context_handle); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_device_deinitialize(executing_device_handle); + if (r) + return CUE_SCLEAN_FAILED; + + if (do_p2p) { + r = amdgpu_device_deinitialize(peer_exporting_device_handle); + if (r) + return CUE_SCLEAN_FAILED; + } + + return CUE_SUCCESS; +} + +CU_BOOL suite_cp_dma_tests_enable(void) { + int r = 0; + + if (amdgpu_device_initialize(drm_amdgpu[0], + &executing_device_major_version, + &executing_device_minor_version, + &executing_device_handle)) + return CU_FALSE; + + if (!(executing_device_handle->info.family_id >= AMDGPU_FAMILY_AI && + executing_device_handle->info.family_id <= AMDGPU_FAMILY_NV)) { + printf("Testing device has ASIC that is not supported by CP-DMA test suite!\n"); + return CU_FALSE; + } + + if (amdgpu_device_deinitialize(executing_device_handle)) + return CU_FALSE; + + if (drm_amdgpu[1] >= 0) { + r = amdgpu_device_initialize(drm_amdgpu[1], + &peer_exporting_device_major_version, + &peer_exporting_device_minor_version, + &peer_exporting_device_handle); + + if (r == 0 && (peer_exporting_device_handle->info.family_id >= AMDGPU_FAMILY_AI && + peer_exporting_device_handle->info.family_id <= AMDGPU_FAMILY_NV)) { + do_p2p = true; + } + + if (r == 0 && amdgpu_device_deinitialize(peer_exporting_device_handle) != 0) { + printf("Deinitialize peer_exporting_device_handle failed!\n"); + return CU_FALSE; + } + } + + if (!do_p2p) { + amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write VRAM to VRAM", CU_FALSE); + amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write Host to VRAM", CU_FALSE); + amdgpu_set_test_active("CP DMA Tests", "Peer to Peer CP DMA write VRAM to Host", CU_FALSE); + printf("Peer device is not opened or has ASIC not supported by the suite, skip all Peer to Peer tests.\n"); + } + + return CU_TRUE; +} diff --git a/lib/libdrm/tests/amdgpu/deadlock_tests.c b/lib/libdrm/tests/amdgpu/deadlock_tests.c index 07a39446b..f29a83ab5 100644 --- a/lib/libdrm/tests/amdgpu/deadlock_tests.c +++ b/lib/libdrm/tests/amdgpu/deadlock_tests.c @@ -139,11 +139,13 @@ CU_BOOL suite_deadlock_tests_enable(void) /* * Only enable for ASICs supporting GPU reset and for which it's enabled - * by default (currently GFX8/9 dGPUS) + * by default (currently GFX8+ dGPUS and gfx9+ APUs). Note that Raven1 + * did not support GPU reset, but newer variants do. */ - if (family_id != AMDGPU_FAMILY_VI && - family_id != AMDGPU_FAMILY_AI && - family_id != AMDGPU_FAMILY_CI) { + if (family_id == AMDGPU_FAMILY_SI || + family_id == AMDGPU_FAMILY_KV || + family_id == AMDGPU_FAMILY_CZ || + family_id == AMDGPU_FAMILY_RV) { printf("\n\nGPU reset is not enabled for the ASIC, deadlock suite disabled\n"); enable = CU_FALSE; } @@ -531,32 +533,44 @@ static void amdgpu_draw_hang_gfx(void) { int r; struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); if (!info.available_rings) printf("SKIP ... as there's no graphic ring\n"); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memcpy_draw_test(device_handle, ring_id, 0); - amdgpu_memcpy_draw_test(device_handle, ring_id, 1); - amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 0); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 1); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 0); } } static void amdgpu_draw_hang_slow_gfx(void) { struct drm_amdgpu_info_hw_ip info; - uint32_t ring_id; + uint32_t ring_id, version; int r; r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); + version = info.hw_ip_version_major; + if (version != 9 && version != 10) { + printf("SKIP ... unsupported gfx version %d\n", version); + return; + } + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { - amdgpu_memcpy_draw_test(device_handle, ring_id, 0); - amdgpu_memcpy_draw_hang_slow_test(device_handle, ring_id); - amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 0); + amdgpu_memcpy_draw_hang_slow_test(device_handle, ring_id, version); + amdgpu_memcpy_draw_test(device_handle, ring_id, version, 0); } } diff --git a/lib/libdrm/tests/amdgpu/hotunplug_tests.c b/lib/libdrm/tests/amdgpu/hotunplug_tests.c index 23ea1407e..2b265673e 100644 --- a/lib/libdrm/tests/amdgpu/hotunplug_tests.c +++ b/lib/libdrm/tests/amdgpu/hotunplug_tests.c @@ -62,15 +62,13 @@ CU_BOOL suite_hotunplug_tests_enable(void) return CU_FALSE; } - /* Disable until the hot-unplug support in kernel gets into drm-next */ - if (major_version < 0xff) - enable = false; - if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, &minor_version, &device_handle)) return CU_FALSE; - - /* TODO Once DRM version for unplug feature ready compare here agains it*/ + + /* Latest tested amdgpu version to work with all the tests */ + if (minor_version < 46) + enable = false; if (amdgpu_device_deinitialize(device_handle)) return CU_FALSE; diff --git a/lib/libdrm/tests/amdgpu/jpeg_tests.c b/lib/libdrm/tests/amdgpu/jpeg_tests.c index 5e50bef62..772a4fecd 100644 --- a/lib/libdrm/tests/amdgpu/jpeg_tests.c +++ b/lib/libdrm/tests/amdgpu/jpeg_tests.c @@ -179,12 +179,9 @@ CU_BOOL suite_jpeg_tests_enable(void) return CU_FALSE; } - if (family_id == AMDGPU_FAMILY_RV) { - if (chip_id >= (chip_rev + 0x91)) - jpeg_direct_reg = true; - else - jpeg_direct_reg = false; - } else if (family_id == AMDGPU_FAMILY_NV) + if (info.hw_ip_version_major == 1) + jpeg_direct_reg = false; + else if (info.hw_ip_version_major > 1 && info.hw_ip_version_major <= 3) jpeg_direct_reg = true; else return CU_FALSE; diff --git a/lib/libdrm/tests/amdgpu/meson.build b/lib/libdrm/tests/amdgpu/meson.build index e027bccc1..53f2010bf 100644 --- a/lib/libdrm/tests/amdgpu/meson.build +++ b/lib/libdrm/tests/amdgpu/meson.build @@ -25,7 +25,7 @@ if dep_cunit.found() 'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c', 'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c', 'vm_tests.c', 'ras_tests.c', 'syncobj_tests.c', 'security_tests.c', - 'hotunplug_tests.c', 'jpeg_tests.c' + 'hotunplug_tests.c', 'jpeg_tests.c', 'cp_dma_tests.c' ), dependencies : [dep_cunit, dep_threads, dep_atomic_ops], include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')], diff --git a/lib/libdrm/tests/amdgpu/vcn_tests.c b/lib/libdrm/tests/amdgpu/vcn_tests.c index 15d573d3c..ff97f3445 100644 --- a/lib/libdrm/tests/amdgpu/vcn_tests.c +++ b/lib/libdrm/tests/amdgpu/vcn_tests.c @@ -70,7 +70,13 @@ static uint32_t *ib_cpu; static amdgpu_bo_handle resources[MAX_RESOURCES]; static unsigned num_resources; -static struct amdgpu_vcn_reg reg; + +static uint8_t vcn_reg_index; +static struct amdgpu_vcn_reg reg[] = { + {0x81c4, 0x81c5, 0x81c3, 0x81ff, 0x81c6}, + {0x504, 0x505, 0x503, 0x53f, 0x506}, + {0x10, 0x11, 0xf, 0x29, 0x26d}, +}; static void amdgpu_cs_vcn_dec_create(void); static void amdgpu_cs_vcn_dec_decode(void); @@ -125,45 +131,14 @@ CU_BOOL suite_vcn_tests_enable(void) amdgpu_set_test_active("VCN Tests", "VCN ENC destroy", CU_FALSE); } - if (family_id == AMDGPU_FAMILY_RV) { - if (chip_id >= (chip_rev + 0x91)) { - reg.data0 = 0x504; - reg.data1 = 0x505; - reg.cmd = 0x503; - reg.nop = 0x53f; - reg.cntl = 0x506; - } else { - reg.data0 = 0x81c4; - reg.data1 = 0x81c5; - reg.cmd = 0x81c3; - reg.nop = 0x81ff; - reg.cntl = 0x81c6; - } - } else if (family_id == AMDGPU_FAMILY_NV) { - if (chip_id == (chip_rev + 0x28) || - chip_id == (chip_rev + 0x32) || - chip_id == (chip_rev + 0x3c) || - chip_id == (chip_rev + 0x46)) { - reg.data0 = 0x10; - reg.data1 = 0x11; - reg.cmd = 0xf; - reg.nop = 0x29; - reg.cntl = 0x26d; - } - else { - reg.data0 = 0x504; - reg.data1 = 0x505; - reg.cmd = 0x503; - reg.nop = 0x53f; - reg.cntl = 0x506; - } - } else if (family_id == AMDGPU_FAMILY_AI) { - reg.data0 = 0x10; - reg.data1 = 0x11; - reg.cmd = 0xf; - reg.nop = 0x29; - reg.cntl = 0x26d; - } else + if (info.hw_ip_version_major == 1) + vcn_reg_index = 0; + else if (info.hw_ip_version_major == 2) + vcn_reg_index = 1; + else if ((info.hw_ip_version_major == 2 && info.hw_ip_version_minor >= 5) || + info.hw_ip_version_major == 3) + vcn_reg_index = 2; + else return CU_FALSE; return CU_TRUE; @@ -307,11 +282,11 @@ static void free_resource(struct amdgpu_vcn_bo *vcn_bo) static void vcn_dec_cmd(uint64_t addr, unsigned cmd, int *idx) { - ib_cpu[(*idx)++] = reg.data0; + ib_cpu[(*idx)++] = reg[vcn_reg_index].data0; ib_cpu[(*idx)++] = addr; - ib_cpu[(*idx)++] = reg.data1; + ib_cpu[(*idx)++] = reg[vcn_reg_index].data1; ib_cpu[(*idx)++] = addr >> 32; - ib_cpu[(*idx)++] = reg.cmd; + ib_cpu[(*idx)++] = reg[vcn_reg_index].cmd; ib_cpu[(*idx)++] = cmd << 1; } @@ -332,14 +307,14 @@ static void amdgpu_cs_vcn_dec_create(void) memcpy(msg_buf.ptr, vcn_dec_create_msg, sizeof(vcn_dec_create_msg)); len = 0; - ib_cpu[len++] = reg.data0; + ib_cpu[len++] = reg[vcn_reg_index].data0; ib_cpu[len++] = msg_buf.addr; - ib_cpu[len++] = reg.data1; + ib_cpu[len++] = reg[vcn_reg_index].data1; ib_cpu[len++] = msg_buf.addr >> 32; - ib_cpu[len++] = reg.cmd; + ib_cpu[len++] = reg[vcn_reg_index].cmd; ib_cpu[len++] = 0; for (; len % 16; ) { - ib_cpu[len++] = reg.nop; + ib_cpu[len++] = reg[vcn_reg_index].nop; ib_cpu[len++] = 0; } @@ -407,10 +382,10 @@ static void amdgpu_cs_vcn_dec_decode(void) vcn_dec_cmd(it_addr, 0x204, &len); vcn_dec_cmd(ctx_addr, 0x206, &len); - ib_cpu[len++] = reg.cntl; + ib_cpu[len++] = reg[vcn_reg_index].cntl; ib_cpu[len++] = 0x1; for (; len % 16; ) { - ib_cpu[len++] = reg.nop; + ib_cpu[len++] = reg[vcn_reg_index].nop; ib_cpu[len++] = 0; } @@ -442,14 +417,14 @@ static void amdgpu_cs_vcn_dec_destroy(void) memcpy(msg_buf.ptr, vcn_dec_destroy_msg, sizeof(vcn_dec_destroy_msg)); len = 0; - ib_cpu[len++] = reg.data0; + ib_cpu[len++] = reg[vcn_reg_index].data0; ib_cpu[len++] = msg_buf.addr; - ib_cpu[len++] = reg.data1; + ib_cpu[len++] = reg[vcn_reg_index].data1; ib_cpu[len++] = msg_buf.addr >> 32; - ib_cpu[len++] = reg.cmd; + ib_cpu[len++] = reg[vcn_reg_index].cmd; ib_cpu[len++] = 0; for (; len % 16; ) { - ib_cpu[len++] = reg.nop; + ib_cpu[len++] = reg[vcn_reg_index].nop; ib_cpu[len++] = 0; } diff --git a/lib/libdrm/tests/exynos/exynos_fimg2d_test.c b/lib/libdrm/tests/exynos/exynos_fimg2d_test.c index 99bb9233a..d85e2f6b6 100644 --- a/lib/libdrm/tests/exynos/exynos_fimg2d_test.c +++ b/lib/libdrm/tests/exynos/exynos_fimg2d_test.c @@ -35,7 +35,6 @@ #include <xf86drm.h> #include <xf86drmMode.h> -#include <libkms.h> #include <drm_fourcc.h> #include "exynos_drm.h" diff --git a/lib/libdrm/tests/exynos/meson.build b/lib/libdrm/tests/exynos/meson.build index 3a048e8ae..12259c3c1 100644 --- a/lib/libdrm/tests/exynos/meson.build +++ b/lib/libdrm/tests/exynos/meson.build @@ -20,18 +20,15 @@ inc_exynos = include_directories('../../exynos') -if with_libkms - exynos_fimg2d_test = executable( - 'exynos_fimg2d_test', - files('exynos_fimg2d_test.c'), - c_args : libdrm_c_args, - include_directories : [inc_root, inc_drm, inc_exynos, - include_directories('../../libkms')], - link_with : [libdrm, libkms, libdrm_exynos], - dependencies : dep_threads, - install : with_install_tests, - ) -endif +exynos_fimg2d_test = executable( + 'exynos_fimg2d_test', + files('exynos_fimg2d_test.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm, inc_exynos], + link_with : [libdrm, libdrm_exynos], + dependencies : dep_threads, + install : with_install_tests, +) exynos_fimg2d_perf = executable( 'exynos_fimg2d_perf', diff --git a/lib/libdrm/tests/meson.build b/lib/libdrm/tests/meson.build index 196edbfa9..ac9e66b01 100644 --- a/lib/libdrm/tests/meson.build +++ b/lib/libdrm/tests/meson.build @@ -21,14 +21,10 @@ inc_tests = include_directories('.') subdir('util') -subdir('kms') subdir('modeprint') subdir('proptest') subdir('modetest') subdir('vbltest') -if with_libkms - subdir('kmstest') -endif if with_radeon subdir('radeon') endif diff --git a/lib/libdrm/tests/modeprint/modeprint.c b/lib/libdrm/tests/modeprint/modeprint.c index f424f19d4..9372ad92d 100644 --- a/lib/libdrm/tests/modeprint/modeprint.c +++ b/lib/libdrm/tests/modeprint/modeprint.c @@ -113,7 +113,7 @@ static int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, ui } else { for (j = 0; j < props->count_enums; j++) { - printf("\t\t%" PRId64 " = %s\n", props->enums[j].value, props->enums[j].name); + printf("\t\t%" PRIu64" = %s\n", (uint64_t)props->enums[j].value, props->enums[j].name); if (props->enums[j].value == value) name = props->enums[j].name; } diff --git a/lib/libdrm/tests/modetest/modetest.c b/lib/libdrm/tests/modetest/modetest.c index 5fd22f79d..d6ab9dc8f 100644 --- a/lib/libdrm/tests/modetest/modetest.c +++ b/lib/libdrm/tests/modetest/modetest.c @@ -376,7 +376,7 @@ static void dump_prop(struct device *dev, drmModePropertyPtr prop, printf("\t\tenums:"); for (i = 0; i < prop->count_enums; i++) printf(" %s=%"PRIu64, prop->enums[i].name, - prop->enums[i].value); + (uint64_t)prop->enums[i].value); printf("\n"); } else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) { printf("\t\tvalues:"); diff --git a/lib/libdrm/tests/proptest/proptest.c b/lib/libdrm/tests/proptest/proptest.c index 0ab0907dd..88bed10b2 100644 --- a/lib/libdrm/tests/proptest/proptest.c +++ b/lib/libdrm/tests/proptest/proptest.c @@ -127,7 +127,7 @@ dump_prop(uint32_t prop_id, uint64_t value) printf("\t\tenums:"); for (i = 0; i < prop->count_enums; i++) printf(" %s=%"PRIu64, prop->enums[i].name, - prop->enums[i].value); + (uint64_t)prop->enums[i].value); printf("\n"); } else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) { printf("\t\tvalues:"); diff --git a/lib/libdrm/tests/tegra/.gitignore b/lib/libdrm/tests/tegra/.gitignore index 5c5216c5c..0db9e5401 100644 --- a/lib/libdrm/tests/tegra/.gitignore +++ b/lib/libdrm/tests/tegra/.gitignore @@ -1 +1,2 @@ -openclose +tegra-gr2d-fill +tegra-openclose diff --git a/lib/libdrm/tests/tegra/drm-test-tegra.c b/lib/libdrm/tests/tegra/drm-test-tegra.c new file mode 100644 index 000000000..1a9fa8961 --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/drm-test-tegra.h b/lib/libdrm/tests/tegra/drm-test-tegra.h new file mode 100644 index 000000000..eefa954cd --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/drm-test.c b/lib/libdrm/tests/tegra/drm-test.c new file mode 100644 index 000000000..b1ded9cf5 --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/drm-test.h b/lib/libdrm/tests/tegra/drm-test.h new file mode 100644 index 000000000..f11aed423 --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/gr2d-fill.c b/lib/libdrm/tests/tegra/gr2d-fill.c new file mode 100644 index 000000000..d138cc4c6 --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/host1x.h b/lib/libdrm/tests/tegra/host1x.h new file mode 100644 index 000000000..902b0c12e --- /dev/null +++ b/lib/libdrm/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/lib/libdrm/tests/tegra/meson.build b/lib/libdrm/tests/tegra/meson.build index 4f8c54f41..26a32e868 100644 --- a/lib/libdrm/tests/tegra/meson.build +++ b/lib/libdrm/tests/tegra/meson.build @@ -18,10 +18,94 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +inc_tegra = include_directories('../../tegra') + +libdrm_test = static_library( + 'drm-test', + [files('drm-test.c', 'drm-test.h'), config_file ], + include_directories : [inc_root, inc_drm, inc_tegra], + link_with : libdrm, +) + +libdrm_test_tegra = static_library( + 'drm-test-tegra', + [files( + 'drm-test-tegra.c', + 'drm-test-tegra.h', + 'vic.c', + 'vic.h', + 'vic30.c', + 'vic30.h', + 'vic40.c', + 'vic40.h', + 'vic41.c', + 'vic41.h', + 'vic42.c', + 'vic42.h', + ), config_file ], + include_directories : [inc_root, inc_drm, inc_tegra], + link_with : libdrm, +) + openclose = executable( - '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, +) + +gr2d_fill = executable( + 'tegra-gr2d-fill', + files('gr2d-fill.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) + +syncpt_wait = executable( + 'tegra-syncpt-wait', + files('syncpt-wait.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) + +syncpt_timeout = executable( + 'tegra-syncpt-timeout', + files('syncpt-timeout.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) + +vic_clear = executable( + 'tegra-vic-clear', + files('vic-clear.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) + +vic_blit = executable( + 'tegra-vic-blit', + files('vic-blit.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) + +vic_flip = executable( + 'tegra-vic-flip', + files('vic-flip.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, ) diff --git a/lib/libdrm/tests/tegra/openclose.c b/lib/libdrm/tests/tegra/openclose.c index f80f52d47..61dbc2ba4 100644 --- a/lib/libdrm/tests/tegra/openclose.c +++ b/lib/libdrm/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(fd, &tegra); + if (err < 0) + return 1; - drm_tegra_close(tegra); - close(fd); + drm_tegra_close(tegra); + close(fd); - return 0; + return 0; } diff --git a/lib/libdrm/tests/tegra/syncpt-timeout.c b/lib/libdrm/tests/tegra/syncpt-timeout.c new file mode 100644 index 000000000..fea3665cb --- /dev/null +++ b/lib/libdrm/tests/tegra/syncpt-timeout.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "tegra.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static int channel_open(struct drm_tegra *drm, + struct drm_tegra_channel **channel) +{ + static const struct { + enum drm_tegra_class class; + const char *name; + } classes[] = { + { DRM_TEGRA_VIC, "VIC" }, + { DRM_TEGRA_GR2D, "GR2D" }, + }; + unsigned int i; + int err; + + for (i = 0; i < ARRAY_SIZE(classes); i++) { + err = drm_tegra_channel_open(drm, classes[i].class, channel); + if (err < 0) { + fprintf(stderr, "failed to open channel to %s: %s\n", + classes[i].name, strerror(-err)); + continue; + } + + break; + } + + return err; +} + +int main(int argc, char *argv[]) +{ + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_syncpoint *syncpt; + struct drm_tegra_channel *channel; + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + struct drm_tegra *drm; + uint32_t *ptr; + int fd, err; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(fd, &drm); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = drm_tegra_syncpoint_new(drm, &syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + drm_tegra_close(drm); + close(fd); + return 1; + } + + err = channel_open(drm, &channel); + if (err < 0) { + fprintf(stderr, "failed to open channel: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 8, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return 1; + } + + /* + * Empty command streams will be rejected, so we use this as an easy way + * to add something to the command stream. But this could be any other, + * valid command stream. + */ + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, syncpt, + DRM_TEGRA_SYNC_COND_IMMEDIATE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return 1; + } + + /* pretend that the syncpoint was incremented a second time */ + err = drm_tegra_pushbuf_sync(pushbuf, syncpt, 1); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_wait(job, 250000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return 1; + } + + drm_tegra_job_free(job); + drm_tegra_channel_close(channel); + drm_tegra_syncpoint_free(syncpt); + drm_tegra_close(drm); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/tegra/syncpt-wait.c b/lib/libdrm/tests/tegra/syncpt-wait.c new file mode 100644 index 000000000..f18117425 --- /dev/null +++ b/lib/libdrm/tests/tegra/syncpt-wait.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "tegra.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static int channel_open(struct drm_tegra *drm, + struct drm_tegra_channel **channel) +{ + static const struct { + enum drm_tegra_class class; + const char *name; + } classes[] = { + { DRM_TEGRA_VIC, "VIC" }, + { DRM_TEGRA_GR2D, "GR2D" }, + }; + unsigned int i; + int err; + + for (i = 0; i < ARRAY_SIZE(classes); i++) { + err = drm_tegra_channel_open(drm, classes[i].class, channel); + if (err < 0) { + fprintf(stderr, "failed to open channel to %s: %s\n", + classes[i].name, strerror(-err)); + continue; + } + + break; + } + + return err; +} + +int main(int argc, char *argv[]) +{ + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_syncpoint *syncpt; + struct drm_tegra_channel *channel; + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + struct drm_tegra *drm; + uint32_t *ptr; + int fd, err; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(fd, &drm); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = drm_tegra_syncpoint_new(drm, &syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + drm_tegra_close(drm); + close(fd); + return 1; + } + + err = channel_open(drm, &channel); + if (err < 0) { + fprintf(stderr, "failed to open channel: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 4, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, syncpt, + DRM_TEGRA_SYNC_COND_IMMEDIATE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_wait(job, 250000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return 1; + } + + drm_tegra_job_free(job); + drm_tegra_channel_close(channel); + drm_tegra_syncpoint_free(syncpt); + drm_tegra_close(drm); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic-blit.c b/lib/libdrm/tests/tegra/vic-blit.c new file mode 100644 index 000000000..7baf9e7a0 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic-blit.c @@ -0,0 +1,333 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "tegra.h" + +#include "host1x.h" +#include "vic.h" + +/* clear output image to red */ +static int clear(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = vic_clear(vic, output, 1023, 1023, 0, 0); + if (err < 0) { + fprintf(stderr, "failed to clear surface: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +/* fill bottom half of image to blue */ +static int fill(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->fill(vic, output, 0, output->height / 2, output->width - 1, + output->height -1, 1023, 0, 0, 1023); + if (err < 0) { + fprintf(stderr, "failed to fill surface: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +/* blit image */ +static int blit(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output, struct vic_image *input) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->blit(vic, output, input); + if (err < 0) { + fprintf(stderr, "failed to blit surface: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, &input, 1); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +int main(int argc, char *argv[]) +{ + const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8; + const unsigned int kind = VIC_BLK_KIND_PITCH; + const unsigned int width = 16, height = 16; + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_channel *channel; + struct vic_image *input, *output; + struct drm_tegra *drm; + unsigned int version; + struct vic *vic; + int fd, err; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(fd, &drm); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel); + if (err < 0) { + fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err)); + return 1; + } + + version = drm_tegra_channel_get_version(channel); + printf("version: %08x\n", version); + + err = vic_new(drm, channel, &vic); + if (err < 0) { + fprintf(stderr, "failed to create VIC: %s\n", strerror(-err)); + return 1; + } + + err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &input); + if (err < 0) { + fprintf(stderr, "failed to create input image: %d\n", err); + return 1; + } + + err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &output); + if (err < 0) { + fprintf(stderr, "failed to create output image: %d\n", err); + return 1; + } + + err = clear(vic, channel, input); + if (err < 0) { + fprintf(stderr, "failed to clear image: %s\n", strerror(-err)); + return 1; + } + + err = fill(vic, channel, input); + if (err < 0) { + fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err)); + return 1; + } + + err = blit(vic, channel, output, input); + if (err < 0) { + fprintf(stderr, "failed to blit image: %s\n", strerror(-err)); + return 1; + } + + printf("input: %ux%u\n", input->width, input->height); + vic_image_dump(input, stdout); + + printf("output: %ux%u\n", output->width, output->height); + vic_image_dump(output, stdout); + + vic_image_free(output); + vic_image_free(input); + + vic_free(vic); + drm_tegra_channel_close(channel); + drm_tegra_close(drm); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic-clear.c b/lib/libdrm/tests/tegra/vic-clear.c new file mode 100644 index 000000000..da72782ed --- /dev/null +++ b/lib/libdrm/tests/tegra/vic-clear.c @@ -0,0 +1,173 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "util_math.h" + +#include "tegra.h" + +#include "host1x.h" +#include "vic.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +int main(int argc, char *argv[]) +{ + const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8; + const unsigned int kind = VIC_BLK_KIND_PITCH; + const unsigned int width = 16, height = 16; + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_channel *channel; + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + struct vic_image *output; + struct drm_tegra *drm; + unsigned int version; + struct vic *vic; + uint32_t *pb; + int fd, err; + void *ptr; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(fd, &drm); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel); + if (err < 0) { + fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err)); + return 1; + } + + version = drm_tegra_channel_get_version(channel); + printf("version: %08x\n", version); + + err = vic_new(drm, channel, &vic); + if (err < 0) { + fprintf(stderr, "failed to create VIC: %s\n", strerror(-err)); + return 1; + } + + err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &output); + if (err < 0) { + fprintf(stderr, "failed to create output image: %d\n", err); + return 1; + } + + printf("image: %zu bytes\n", output->size); + + err = drm_tegra_bo_map(output->bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map output image: %d\n", err); + return 1; + } + + memset(ptr, 0xff, output->size); + drm_tegra_bo_unmap(output->bo); + + printf("output: %ux%u\n", output->width, output->height); + vic_image_dump(output, stdout); + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &pb); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return 1; + } + + err = vic_clear(vic, output, 1023, 0, 0, 1023); + if (err < 0) { + fprintf(stderr, "failed to clear surface: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &pb, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &pb, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_end(pushbuf, pb); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return 1; + } + + printf("output: %ux%u\n", output->width, output->height); + vic_image_dump(output, stdout); + + drm_tegra_job_free(job); + vic_image_free(output); + vic_free(vic); + drm_tegra_channel_close(channel); + drm_tegra_close(drm); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic-flip.c b/lib/libdrm/tests/tegra/vic-flip.c new file mode 100644 index 000000000..e94336be1 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic-flip.c @@ -0,0 +1,333 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "tegra.h" + +#include "host1x.h" +#include "vic.h" + +/* clear output image to red */ +static int clear(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic_clear(vic, output, 1023, 0, 0, 1023); + if (err < 0) { + fprintf(stderr, "failed to clear surface: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +/* fill bottom half of image to blue */ +static int fill(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->fill(vic, output, 0, output->height / 2, output->width - 1, + output->height - 1, 0, 0, 1023, 1023); + if (err < 0) { + fprintf(stderr, "failed ot fill surface: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +/* flip image vertically */ +static int flip(struct vic *vic, struct drm_tegra_channel *channel, + struct vic_image *output, struct vic_image *input) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + uint32_t *ptr; + int err; + + err = drm_tegra_job_new(channel, &job); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_job_get_pushbuf(job, &pushbuf); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->flip(vic, output, input); + if (err < 0) { + fprintf(stderr, "failed to flip: %s\n", strerror(-err)); + return err; + } + + err = vic->ops->execute(vic, pushbuf, &ptr, output, &input, 1); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync_cond(pushbuf, &ptr, vic->syncpt, + DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_end(pushbuf, ptr); + if (err < 0) { + fprintf(stderr, "failed to update push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, NULL); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job, 1000000000); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_job_free(job); + + return 0; +} + +int main(int argc, char *argv[]) +{ + const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8; + const unsigned int kind = VIC_BLK_KIND_PITCH; + const unsigned int width = 16, height = 16; + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_channel *channel; + struct vic_image *input, *output; + struct drm_tegra *drm; + unsigned int version; + struct vic *vic; + int fd, err; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(fd, &drm); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = drm_tegra_channel_open(drm, DRM_TEGRA_VIC, &channel); + if (err < 0) { + fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err)); + return 1; + } + + version = drm_tegra_channel_get_version(channel); + printf("version: %08x\n", version); + + err = vic_new(drm, channel, &vic); + if (err < 0) { + fprintf(stderr, "failed to create VIC: %s\n", strerror(-err)); + return 1; + } + + err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &input); + if (err < 0) { + fprintf(stderr, "failed to create input image: %d\n", err); + return 1; + } + + err = vic_image_new(vic, width, height, format, kind, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &output); + if (err < 0) { + fprintf(stderr, "failed to create output image: %d\n", err); + return 1; + } + + err = clear(vic, channel, input); + if (err < 0) { + fprintf(stderr, "failed to clear image: %s\n", strerror(-err)); + return 1; + } + + err = fill(vic, channel, input); + if (err < 0) { + fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err)); + return 1; + } + + err = flip(vic, channel, output, input); + if (err < 0) { + fprintf(stderr, "failed to flip image: %s\n", strerror(-err)); + return 1; + } + + printf("input: %ux%u\n", input->width, input->height); + vic_image_dump(input, stdout); + + printf("output: %ux%u\n", output->width, output->height); + vic_image_dump(output, stdout); + + vic_image_free(output); + vic_image_free(input); + + vic_free(vic); + drm_tegra_channel_close(channel); + drm_tegra_close(drm); + close(fd); + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic.c b/lib/libdrm/tests/tegra/vic.c new file mode 100644 index 000000000..4163e1846 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <stdio.h> /* XXX remove */ +#include <stdlib.h> + +#include "util_math.h" + +#include "tegra.h" +#include "host1x.h" +#include "vic.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +const struct vic_format_info *vic_format_get_info(unsigned int format) +{ + static const struct vic_format_info formats[] = { + { .format = VIC_PIXEL_FORMAT_A8R8G8B8, .cpp = 4 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].format == format) + return &formats[i]; + } + + return 0; +} + +int vic_image_new(struct vic *vic, unsigned int width, unsigned int height, + unsigned int format, unsigned int kind, uint32_t flags, + struct vic_image **imagep) +{ + const struct vic_format_info *info = vic_format_get_info(format); + struct vic_image *image; + int err; + + if (!info) + return -EINVAL; + + image = calloc(1, sizeof(*image)); + if (!image) + return -ENOMEM; + + if (kind == VIC_BLK_KIND_PITCH) + image->align = 256; + else + image->align = 256; /* XXX */ + + image->width = width; + image->stride = ALIGN(width, image->align); + image->pitch = image->stride * info->cpp; + image->height = height; + image->format = format; + image->kind = kind; + + image->size = image->pitch * image->height; + + printf("image: %ux%u align: %zu stride: %u pitch: %u size: %zu\n", + image->width, image->height, image->align, image->stride, + image->pitch, image->size); + + err = drm_tegra_bo_new(vic->drm, 0, image->size, &image->bo); + if (err < 0) { + free(image); + return err; + } + + err = drm_tegra_channel_map(vic->channel, image->bo, flags, &image->map); + if (err < 0) { + drm_tegra_bo_unref(image->bo); + free(image); + return err; + } + + *imagep = image; + return 0; +} + +void vic_image_free(struct vic_image *image) +{ + if (image) { + drm_tegra_channel_unmap(image->map); + drm_tegra_bo_unref(image->bo); + free(image); + } +} + +void vic_image_dump(struct vic_image *image, FILE *fp) +{ + unsigned int i, j; + void *ptr; + int err; + + err = drm_tegra_bo_map(image->bo, &ptr); + if (err < 0) + return; + + for (j = 0; j < image->height; j++) { + uint32_t *pixels = (uint32_t *)((unsigned long)ptr + j * image->pitch); + + printf(" "); + + for (i = 0; i < image->width; i++) + printf(" %08x", pixels[i]); + + printf("\n"); + } + + drm_tegra_bo_unmap(image->bo); +} + +/* from vic30.c */ +int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp); + +/* from vic40.c */ +int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp); + +/* from vic41.c */ +int vic41_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp); + +/* from vic42.c */ +int vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp); + +int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp) +{ + unsigned int version; + + version = drm_tegra_channel_get_version(channel); + + switch (version) { + case 0x40: + return vic30_new(drm, channel, vicp); + + case 0x21: + return vic40_new(drm, channel, vicp); + + case 0x18: + return vic41_new(drm, channel, vicp); + + case 0x19: + return vic42_new(drm, channel, vicp); + } + + return -ENOTSUP; +} + +void vic_free(struct vic *vic) +{ + if (vic) + vic->ops->free(vic); +} + +int vic_clear(struct vic *vic, struct vic_image *output, unsigned int alpha, + unsigned int red, unsigned int green, unsigned int blue) +{ + return vic->ops->fill(vic, output, 0, 0, output->width - 1, + output->height - 1, alpha, red, green, blue); +} diff --git a/lib/libdrm/tests/tegra/vic.h b/lib/libdrm/tests/tegra/vic.h new file mode 100644 index 000000000..c20566694 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic.h @@ -0,0 +1,181 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIC_H +#define VIC_H + +#include <stdio.h> + +#include "host1x.h" + +#define DXVAHD_FRAME_FORMAT_PROGRESSIVE 0 +#define DXVAHD_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST 1 +#define DXVAHD_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST 2 +#define DXVAHD_FRAME_FORMAT_TOP_FIELD 3 +#define DXVAHD_FRAME_FORMAT_BOTTOM_FIELD 4 +#define DXVAHD_FRAME_FORMAT_SUBPIC_PROGRESSIVE 5 +#define DXVAHD_FRAME_FORMAT_SUBPIC_INTERLACED_TOP_FIELD_FIRST 6 +#define DXVAHD_FRAME_FORMAT_SUBPIC_INTERLACED_BOTTOM_FIELD_FIRST 7 +#define DXVAHD_FRAME_FORMAT_SUBPIC_TOP_FIELD 8 +#define DXVAHD_FRAME_FORMAT_SUBPIC_BOTTOM_FIELD 9 +#define DXVAHD_FRAME_FORMAT_TOP_FIELD_CHROMA_BOTTOM 10 +#define DXVAHD_FRAME_FORMAT_BOTTOM_FIELD_CHROMA_TOP 11 +#define DXVAHD_FRAME_FORMAT_SUBPIC_TOP_FIELD_CHROMA_BOTTOM 12 +#define DXVAHD_FRAME_FORMAT_SUBPIC_BOTTOM_FIELD_CHROMA_TOP 13 + +#define DXVAHD_ALPHA_FILL_MODE_OPAQUE 0 +#define DXVAHD_ALPHA_FILL_MODE_BACKGROUND 1 +#define DXVAHD_ALPHA_FILL_MODE_DESTINATION 2 +#define DXVAHD_ALPHA_FILL_MODE_SOURCE_STREAM 3 +#define DXVAHD_ALPHA_FILL_MODE_COMPOSITED 4 +#define DXVAHD_ALPHA_FILL_MODE_SOURCE_ALPHA 5 + +#define VIC_BLEND_SRCFACTC_K1 0 +#define VIC_BLEND_SRCFACTC_K1_TIMES_DST 1 +#define VIC_BLEND_SRCFACTC_NEG_K1_TIMES_DST 2 +#define VIC_BLEND_SRCFACTC_K1_TIMES_SRC 3 +#define VIC_BLEND_SRCFACTC_ZERO 4 + +#define VIC_BLEND_DSTFACTC_K1 0 +#define VIC_BLEND_DSTFACTC_K2 1 +#define VIC_BLEND_DSTFACTC_K1_TIMES_DST 2 +#define VIC_BLEND_DSTFACTC_NEG_K1_TIMES_DST 3 +#define VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC 4 +#define VIC_BLEND_DSTFACTC_ZERO 5 +#define VIC_BLEND_DSTFACTC_ONE 6 + +#define VIC_BLEND_SRCFACTA_K1 0 +#define VIC_BLEND_SRCFACTA_K2 1 +#define VIC_BLEND_SRCFACTA_NEG_K1_TIMES_DST 2 +#define VIC_BLEND_SRCFACTA_ZERO 3 + +#define VIC_BLEND_DSTFACTA_K2 0 +#define VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC 1 +#define VIC_BLEND_DSTFACTA_ZERO 2 +#define VIC_BLEND_DSTFACTA_ONE 3 + +#define VIC_BLK_KIND_PITCH 0 +#define VIC_BLK_KIND_GENERIC_16Bx2 1 + +#define VIC_PIXEL_FORMAT_L8 1 +#define VIC_PIXEL_FORMAT_R8 4 +#define VIC_PIXEL_FORMAT_A8R8G8B8 32 +#define VIC_PIXEL_FORMAT_R8G8B8A8 34 +#define VIC_PIXEL_FORMAT_Y8_U8V8_N420 67 +#define VIC_PIXEL_FORMAT_Y8_V8U8_N420 68 + +#define VIC_CACHE_WIDTH_16Bx16 0 /* BL16Bx2 */ +#define VIC_CACHE_WIDTH_32Bx8 1 /* BL16Bx2 */ +#define VIC_CACHE_WIDTH_64Bx4 2 /* BL16Bx2, PL */ +#define VIC_CACHE_WIDTH_128Bx2 3 /* BL16Bx2, PL */ +#define VIC_CACHE_WIDTH_256Bx1 4 /* PL */ + +struct vic_format_info { + unsigned int format; + unsigned int cpp; +}; + + +#define VIC_UCLASS_INCR_SYNCPT 0x00 +#define VIC_UCLASS_METHOD_OFFSET 0x10 +#define VIC_UCLASS_METHOD_DATA 0x11 + +static inline void VIC_PUSH_METHOD(struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, uint32_t method, + uint32_t value) +{ + *(*ptrp)++ = HOST1X_OPCODE_INCR(VIC_UCLASS_METHOD_OFFSET, 2); + *(*ptrp)++ = method >> 2; + *(*ptrp)++ = value; +} + +static inline void VIC_PUSH_BUFFER(struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, uint32_t method, + struct drm_tegra_mapping *map, + unsigned long offset, unsigned long flags) +{ + *(*ptrp)++ = HOST1X_OPCODE_INCR(VIC_UCLASS_METHOD_OFFSET, 2); + *(*ptrp)++ = method >> 2; + + drm_tegra_pushbuf_relocate(pushbuf, ptrp, map, offset, 8, flags); +} + +struct vic_image; +struct vic; + +struct vic_ops { + int (*fill)(struct vic *vic, struct vic_image *output, + unsigned int left, unsigned int top, + unsigned int right, unsigned int bottom, + unsigned int alpha, unsigned red, + unsigned int green, unsigned int blue); + int (*blit)(struct vic *vic, struct vic_image *output, + struct vic_image *input); + int (*flip)(struct vic *vic, struct vic_image *output, + struct vic_image *input); + int (*execute)(struct vic *vic, + struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, + struct vic_image *output, + struct vic_image **inputs, + unsigned int num_inputs); + void (*free)(struct vic *vic); +}; + +struct vic { + struct drm_tegra *drm; + struct drm_tegra_channel *channel; + struct drm_tegra_syncpoint *syncpt; + const struct vic_ops *ops; + unsigned int version; +}; + +int vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp); +void vic_free(struct vic *vic); + +int vic_clear(struct vic *vic, struct vic_image *output, unsigned int alpha, + unsigned int red, unsigned int green, unsigned int blue); + +struct vic_image { + struct drm_tegra_bo *bo; + struct drm_tegra_mapping *map; + unsigned int width; + unsigned int stride; + unsigned int pitch; + unsigned int height; + unsigned int format; + unsigned int kind; + + size_t align; + size_t size; +}; + +const struct vic_format_info *vic_format_get_info(unsigned int format); + +int vic_image_new(struct vic *vic, unsigned int width, unsigned int height, + unsigned int format, unsigned int kind, uint32_t flags, + struct vic_image **imagep); +void vic_image_free(struct vic_image *image); +void vic_image_dump(struct vic_image *image, FILE *fp); + +#endif diff --git a/lib/libdrm/tests/tegra/vic30.c b/lib/libdrm/tests/tegra/vic30.c new file mode 100644 index 000000000..1bea6e703 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic30.c @@ -0,0 +1,458 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <string.h> + +#include "private.h" +#include "tegra.h" +#include "vic.h" +#include "vic30.h" + +struct vic30 { + struct vic base; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } config; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } filter; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } hist; +}; + +static int vic30_fill(struct vic *v, struct vic_image *output, + unsigned int left, unsigned int top, + unsigned int right, unsigned int bottom, + unsigned int alpha, unsigned int red, + unsigned int green, unsigned int blue) +{ + struct vic30 *vic = container_of(v, struct vic30, base); + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->surfaceList0Struct.TargetRectLeft = left; + c->surfaceList0Struct.TargetRectTop = top; + c->surfaceList0Struct.TargetRectRight = right; + c->surfaceList0Struct.TargetRectBottom = bottom; + + c->blending0Struct.PixelFormat = output->format; + c->blending0Struct.BackgroundAlpha = alpha; + c->blending0Struct.BackgroundR = red; + c->blending0Struct.BackgroundG = green; + c->blending0Struct.BackgroundB = blue; + c->blending0Struct.LumaWidth = output->stride - 1; + c->blending0Struct.LumaHeight = output->height - 1; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.TargetRectLeft = left; + c->blending0Struct.TargetRectTop = top; + c->blending0Struct.TargetRectRight = right; + c->blending0Struct.TargetRectBottom = bottom; + c->blending0Struct.SurfaceWidth = output->width - 1; + c->blending0Struct.SurfaceHeight = output->height - 1; + c->blending0Struct.BlkKind = output->kind; + c->blending0Struct.BlkHeight = 0; + + c->fetchControl0Struct.TargetRectLeft = left; + c->fetchControl0Struct.TargetRectTop = top; + c->fetchControl0Struct.TargetRectRight = right; + c->fetchControl0Struct.TargetRectBottom = bottom; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic30_blit(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic30 *vic = container_of(v, struct vic30, base); + ColorConversionLumaAlphaStruct *ccla; + ColorConversionMatrixStruct *ccm; + ColorConversionClampStruct *ccc; + SurfaceListSurfaceStruct *s; + BlendingSurfaceStruct *b; + SurfaceCache0Struct *sc; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->surfaceList0Struct.TargetRectLeft = 0; + c->surfaceList0Struct.TargetRectTop = 0; + c->surfaceList0Struct.TargetRectRight = output->width - 1; + c->surfaceList0Struct.TargetRectBottom = output->height - 1; + + c->blending0Struct.PixelFormat = output->format; + c->blending0Struct.BackgroundAlpha = 0; + c->blending0Struct.BackgroundR = 0; + c->blending0Struct.BackgroundG = 0; + c->blending0Struct.BackgroundB = 0; + c->blending0Struct.LumaWidth = output->stride - 1; + c->blending0Struct.LumaHeight = output->height - 1; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.TargetRectLeft = 0; + c->blending0Struct.TargetRectTop = 0; + c->blending0Struct.TargetRectRight = output->width - 1; + c->blending0Struct.TargetRectBottom = output->height - 1; + c->blending0Struct.SurfaceWidth = output->width - 1; + c->blending0Struct.SurfaceHeight = output->height - 1; + c->blending0Struct.BlkKind = output->kind; + c->blending0Struct.BlkHeight = 0; + + c->fetchControl0Struct.TargetRectLeft = 0; + c->fetchControl0Struct.TargetRectTop = 0; + c->fetchControl0Struct.TargetRectRight = output->width - 1; + c->fetchControl0Struct.TargetRectBottom = output->height - 1; + + /* setup fetch parameters for slot 0 */ + c->fetchControl0Struct.Enable0 = 0x1; + c->fetchControl0Struct.Iir0 = 0x300; + + /* setup cache parameters for slot 0 */ + sc = &c->surfaceCache0Struct; + sc->PixelFormat0 = input->format; + + /* setup surface configuration for slot 0 */ + s = &c->surfaceListSurfaceStruct[0]; + s->Enable = 1; + s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE; + s->PixelFormat = input->format; + s->SurfaceWidth = input->width - 1; + s->SurfaceHeight = input->height - 1; + s->LumaWidth = input->stride - 1; + s->LumaHeight = input->height - 1; + s->ChromaWidth = 16383; + s->ChromaHeight = 16383; + s->CacheWidth = VIC_CACHE_WIDTH_256Bx1; //VIC_CACHE_WIDTH_16Bx16; + s->BlkKind = input->kind; + s->BlkHeight = 0; + s->DestRectLeft = 0; + s->DestRectTop = 0; + s->DestRectRight = output->width - 1; + s->DestRectBottom = output->height - 1; + s->SourceRectLeft = 0 << 16; + s->SourceRectTop = 0 << 16; + s->SourceRectRight = (input->width - 1) << 16; + s->SourceRectBottom = (input->height - 1) << 16; + + /* setup color conversion for slot 0 */ + ccla = &c->colorConversionLumaAlphaStruct[0]; + ccla->PlanarAlpha = 1023; + ccla->ConstantAlpha = 0; + + ccm = &c->colorConversionMatrixStruct[0]; + ccm->c00 = 1023; + ccm->c11 = 1023; + ccm->c22 = 1023; + + ccc = &c->colorConversionClampStruct[0]; + ccc->low = 0; + ccc->high = 1023; + + /* setup blending for slot 0 */ + b = &c->blendingSurfaceStruct[0]; + b->AlphaK1 = 1023; + b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1; + b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1; + b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC; + b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic30_flip(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic30 *vic = container_of(v, struct vic30, base); + ColorConversionLumaAlphaStruct *ccla; + ColorConversionMatrixStruct *ccm; + ColorConversionClampStruct *ccc; + SurfaceListSurfaceStruct *s; + BlendingSurfaceStruct *b; + SurfaceCache0Struct *sc; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->surfaceList0Struct.TargetRectLeft = 0; + c->surfaceList0Struct.TargetRectTop = 0; + c->surfaceList0Struct.TargetRectRight = output->width - 1; + c->surfaceList0Struct.TargetRectBottom = output->height - 1; + + c->blending0Struct.PixelFormat = output->format; + c->blending0Struct.BackgroundAlpha = 0; + c->blending0Struct.BackgroundR = 0; + c->blending0Struct.BackgroundG = 0; + c->blending0Struct.BackgroundB = 0; + c->blending0Struct.LumaWidth = output->stride - 1; + c->blending0Struct.LumaHeight = output->height - 1; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.ChromaWidth = 16383; + c->blending0Struct.TargetRectLeft = 0; + c->blending0Struct.TargetRectTop = 0; + c->blending0Struct.TargetRectRight = output->width - 1; + c->blending0Struct.TargetRectBottom = output->height - 1; + c->blending0Struct.SurfaceWidth = output->width - 1; + c->blending0Struct.SurfaceHeight = output->height - 1; + c->blending0Struct.BlkKind = output->kind; + c->blending0Struct.BlkHeight = 0; + c->blending0Struct.OutputFlipY = 1; + + c->fetchControl0Struct.TargetRectLeft = 0; + c->fetchControl0Struct.TargetRectTop = 0; + c->fetchControl0Struct.TargetRectRight = output->width - 1; + c->fetchControl0Struct.TargetRectBottom = output->height - 1; + + /* setup fetch parameters for slot 0 */ + c->fetchControl0Struct.Enable0 = 0x1; + c->fetchControl0Struct.Iir0 = 0x300; + + /* setup cache parameters for slot 0 */ + sc = &c->surfaceCache0Struct; + sc->PixelFormat0 = input->format; + + /* setup surface configuration for slot 0 */ + s = &c->surfaceListSurfaceStruct[0]; + s->Enable = 1; + s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE; + s->PixelFormat = input->format; + s->SurfaceWidth = input->width - 1; + s->SurfaceHeight = input->height - 1; + s->LumaWidth = input->stride - 1; + s->LumaHeight = input->height - 1; + s->ChromaWidth = 16383; + s->ChromaHeight = 16383; + s->CacheWidth = VIC_CACHE_WIDTH_256Bx1; + s->BlkKind = input->kind; + s->BlkHeight = 0; + s->DestRectLeft = 0; + s->DestRectTop = 0; + s->DestRectRight = output->width - 1; + s->DestRectBottom = output->height - 1; + s->SourceRectLeft = 0 << 16; + s->SourceRectTop = 0 << 16; + s->SourceRectRight = (input->width - 1) << 16; + s->SourceRectBottom = (input->height - 1) << 16; + + /* setup color conversion for slot 0 */ + ccla = &c->colorConversionLumaAlphaStruct[0]; + ccla->PlanarAlpha = 1023; + ccla->ConstantAlpha = 0; + + ccm = &c->colorConversionMatrixStruct[0]; + ccm->c00 = 1023; + ccm->c11 = 1023; + ccm->c22 = 1023; + + ccc = &c->colorConversionClampStruct[0]; + ccc->low = 0; + ccc->high = 1023; + + /* setup blending for slot 0 */ + b = &c->blendingSurfaceStruct[0]; + b->AlphaK1 = 1023; + b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1; + b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1; + b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC; + b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic30_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, struct vic_image *output, + struct vic_image **inputs, unsigned int num_inputs) +{ + struct vic30 *vic = container_of(v, struct vic30, base); + unsigned int i; + + if (num_inputs > 1) + return -EINVAL; + + VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1); + VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET, vic->hist.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0); + + for (i = 0; i < num_inputs; i++) + VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0); + + VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8); + + return 0; +} + +static void vic30_free(struct vic *v) +{ + struct vic30 *vic = container_of(v, struct vic30, base); + + drm_tegra_channel_unmap(vic->hist.map); + drm_tegra_bo_unref(vic->hist.bo); + + drm_tegra_channel_unmap(vic->filter.map); + drm_tegra_bo_unref(vic->filter.bo); + + drm_tegra_channel_unmap(vic->config.map); + drm_tegra_bo_unref(vic->config.bo); + + drm_tegra_syncpoint_free(v->syncpt); + + free(vic); +} + +static const struct vic_ops vic30_ops = { + .fill = vic30_fill, + .blit = vic30_blit, + .flip = vic30_flip, + .execute = vic30_execute, + .free = vic30_free, +}; + +int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp) +{ + struct vic30 *vic; + void *ptr; + int err; + + vic = calloc(1, sizeof(*vic)); + if (!vic) + return -ENOMEM; + + vic->base.drm = drm; + vic->base.channel = channel; + vic->base.ops = &vic30_ops; + vic->base.version = 0x40; + + err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate configuration structure: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->config.map); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate filter buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(vic->filter.bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 16384); + drm_tegra_bo_unmap(vic->filter.bo); + + err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->filter.map); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 4096, &vic->hist.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate history buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(vic->hist.bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map history buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 4096); + drm_tegra_bo_unmap(vic->hist.bo); + + err = drm_tegra_channel_map(channel, vic->hist.bo, DRM_TEGRA_CHANNEL_MAP_READ_WRITE, + &vic->hist.map); + if (err < 0) { + fprintf(stderr, "failed to map histogram buffer: %s\n", + strerror(-err)); + return err; + } + + if (vicp) + *vicp = &vic->base; + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic30.h b/lib/libdrm/tests/tegra/vic30.h new file mode 100644 index 000000000..d095c0d22 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic30.h @@ -0,0 +1,439 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIC30_H +#define VIC30_H + +#include <stdint.h> + +#define NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x200 +#define NVA0B6_VIDEO_COMPOSITOR_EXECUTE 0x300 +#define NVA0B6_VIDEO_COMPOSITOR_EXECUTE_AWAKEN (1 << 8) +#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET 0x400 +#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_U_OFFSET 0x404 +#define NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_V_OFFSET 0x408 +#define NVA0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x700 +#define NVA0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x720 +#define NVA0B6_VIDEO_COMPOSITOR_SET_PALETTE_OFFSET 0x724 +#define NVA0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x728 +#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x730 +#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_CHROMA_U_OFFSET 0x734 +#define NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_CHROMA_V_OFFSET 0x738 + +#define VIC_PIXEL_FORMAT_L8 1 +#define VIC_PIXEL_FORMAT_R8 4 +#define VIC_PIXEL_FORMAT_A8R8G8B8 32 +#define VIC_PIXEL_FORMAT_R8G8B8A8 34 +#define VIC_PIXEL_FORMAT_Y8_U8V8_N420 67 +#define VIC_PIXEL_FORMAT_Y8_V8U8_N420 68 + +#define VIC_BLK_KIND_PITCH 0 +#define VIC_BLK_KIND_GENERIC_16Bx2 1 + +typedef struct { + uint64_t DeNoise0 : 1; /* 0 */ + uint64_t CadenceDetect0 : 1; /* 1 */ + uint64_t MotionMap0 : 1; /* 2 */ + uint64_t MedianFilter0 : 1; /* 3 */ + uint64_t DeNoise1 : 1; /* 4 */ + uint64_t CadenceDetect1 : 1; /* 5 */ + uint64_t MotionMap1 : 1; /* 6 */ + uint64_t MedianFilter1 : 1; /* 7 */ + uint64_t DeNoise2 : 1; /* 8 */ + uint64_t CadenceDetect2 : 1; /* 9 */ + uint64_t MotionMap2 : 1; /* 10 */ + uint64_t MedianFilter2 : 1; /* 11 */ + uint64_t DeNoise3 : 1; /* 12 */ + uint64_t CadenceDetect3 : 1; /* 13 */ + uint64_t MotionMap3 : 1; /* 14 */ + uint64_t MedianFilter3 : 1; /* 15 */ + uint64_t DeNoise4 : 1; /* 16 */ + uint64_t CadenceDetect4 : 1; /* 17 */ + uint64_t MotionMap4 : 1; /* 18 */ + uint64_t MedianFilter4 : 1; /* 19 */ + uint64_t IsEven0 : 1; /* 20 */ + uint64_t IsEven1 : 1; /* 21 */ + uint64_t IsEven2 : 1; /* 22 */ + uint64_t IsEven3 : 1; /* 23 */ + uint64_t IsEven4 : 1; /* 24 */ + uint64_t MMapCombine0 : 1; /* 25 */ + uint64_t MMapCombine1 : 1; /* 26 */ + uint64_t MMapCombine2 : 1; /* 27 */ + uint64_t MMapCombine3 : 1; /* 28 */ + uint64_t MMapCombine4 : 1; /* 29 */ + uint64_t reserved0 : 2; /* 31..30 */ + uint64_t PixelFormat0 : 7; /* 38..32 */ + uint64_t reserved1 : 1; /* 39 */ + uint64_t PixelFormat1 : 7; /* 46..40 */ + uint64_t reserved2 : 1; /* 47 */ + uint64_t PixelFormat2 : 7; /* 54..48 */ + uint64_t reserved3 : 1; /* 55 */ + uint64_t PixelFormat3 : 7; /* 62..56 */ + uint64_t reserved4 : 1; /* 63 */ + uint64_t PixelFormat4 : 7; /* 70..64 */ + uint64_t reserved5 : 1; /* 71 */ + uint64_t reserved6 : 24; /* 95..72 */ + uint64_t PPMotion0 : 1; /* 96 */ + uint64_t PPMotion1 : 1; /* 97 */ + uint64_t PPMotion2 : 1; /* 98 */ + uint64_t PPMotion3 : 1; /* 99 */ + uint64_t PPMotion4 : 1; /* 100 */ + uint64_t reserved7 : 3; /* 103..101 */ + uint64_t ChromaEven0 : 1; /* 104 */ + uint64_t ChromaEven1 : 1; /* 105 */ + uint64_t ChromaEven2 : 1; /* 106 */ + uint64_t ChromaEven3 : 1; /* 107 */ + uint64_t ChromaEven4 : 1; /* 108 */ + uint64_t reserved8 : 3; /* 111..109 */ + uint64_t AdvancedDenoise0 : 1; /* 112 */ + uint64_t AdvancedDenoise1 : 1; /* 113 */ + uint64_t AdvancedDenoise2 : 1; /* 114 */ + uint64_t AdvancedDenoise3 : 1; /* 115 */ + uint64_t AdvancedDenoise4 : 1; /* 116 */ + uint64_t reserved9 : 3; /* 119..117 */ + uint64_t reserved10 : 8; /* 127..120 */ +} SurfaceCache0Struct; + +typedef struct { + uint64_t ClearRectMask0 : 8; /* 7..0 */ + uint64_t ClearRectMask1 : 8; /* 15..8 */ + uint64_t ClearRectMask2 : 8; /* 23..16 */ + uint64_t ClearRectMask3 : 8; /* 31..24 */ + uint64_t ClearRectMask4 : 8; /* 39..32 */ + uint64_t reserved0 : 22; /* 61..40 */ + uint64_t OutputFlipX : 1; /* 62 */ + uint64_t OutputFlipY : 1; /* 63 */ + uint64_t TargetRectLeft : 14; /* 77..64 */ + uint64_t reserved1 : 2; /* 79..78 */ + uint64_t TargetRectRight : 14; /* 93..80 */ + uint64_t reserved2 : 2; /* 95..94 */ + uint64_t TargetRectTop : 14; /* 109..96 */ + uint64_t reserved3 : 2; /* 111..110 */ + uint64_t TargetRectBottom : 14; /* 125..112 */ + uint64_t reserved4 : 2; /* 127..126 */ +} SurfaceList0Struct; + +typedef struct { + uint64_t ClearRect0Left : 14; /* 13..0 */ + uint64_t reserved0 : 2; /* 15..14 */ + uint64_t ClearRect0Right : 14; /* 29..16 */ + uint64_t reserved1 : 2; /* 31..30 */ + uint64_t ClearRect0Top : 14; /* 45..32 */ + uint64_t reserved2 : 2; /* 47..46 */ + uint64_t ClearRect0Bottom : 14; /* 61..48 */ + uint64_t reserved3 : 2; /* 63..62 */ + uint64_t ClearRect1Left : 14; /* 77..64 */ + uint64_t reserved4 : 2; /* 79..78 */ + uint64_t ClearRect1Right : 14; /* 93..80 */ + uint64_t reserved5 : 2; /* 95..94 */ + uint64_t ClearRect1Top : 14; /* 109..96 */ + uint64_t reserved6 : 2; /* 111..110 */ + uint64_t ClearRect1Bottom : 14; /* 125..112 */ + uint64_t reserved7 : 2; /* 127..126 */ +} SurfaceListClearRectStruct; + +typedef struct { + uint64_t Enable : 1; /* 0 */ + uint64_t FrameFormat : 4; /* 4..1 */ + uint64_t PixelFormat : 7; /* 11..5 */ + uint64_t reserved0 : 2; /* 13..12 */ + uint64_t ChromaLocHoriz : 2; /* 15..14 */ + uint64_t ChromaLocVert : 2; /* 17..16 */ + uint64_t Panoramic : 12; /* 29..18 */ + uint64_t reserved1 : 4; /* 33..30 */ + uint64_t SurfaceWidth : 14; /* 47..34 */ + uint64_t reserved2 : 1; /* 48 */ + uint64_t SurfaceHeight : 14; /* 62..49 */ + uint64_t reserved3 : 1; /* 63 */ + uint64_t LumaWidth : 14; /* 77..64 */ + uint64_t reserved4 : 1; /* 78 */ + uint64_t LumaHeight : 14; /* 92..79 */ + uint64_t reserved5 : 1; /* 93 */ + uint64_t ChromaWidth : 14; /* 107..94 */ + uint64_t reserved6 : 1; /* 108 */ + uint64_t ChromaHeight : 14; /* 122..109 */ + uint64_t reserved7 : 1; /* 123 */ + uint64_t CacheWidth : 3; /* 126..124 */ + uint64_t reserved8 : 1; /* 127 */ + /* 128 */ + uint64_t FilterLengthY : 2; /* 1..0 */ + uint64_t FilterLengthX : 2; /* 3..2 */ + uint64_t DetailFltClamp : 6; /* 9..4 */ + uint64_t reserved9 : 2; /* 11..10 */ + uint64_t LightLevel : 4; /* 15..12 */ + uint64_t reserved10 : 4; /* 19..16 */ + uint64_t reserved11 : 8; /* 27..20 */ + uint64_t reserved12 : 32; /* 59..28 */ + uint64_t BlkKind : 4; /* 63..60 */ + uint64_t DestRectLeft : 14; /* 77..64 */ + uint64_t reserved13 : 1; /* 78 */ + uint64_t DestRectRight : 14; /* 92..79 */ + uint64_t reserved14 : 1; /* 93 */ + uint64_t DestRectTop : 14; /* 107..94 */ + uint64_t reserved15 : 1; /* 108 */ + uint64_t DestRectBottom : 14; /* 122..109 */ + uint64_t reserved16 : 1; /* 123 */ + uint64_t BlkHeight : 4; /* 127..124 */ + /* 256 */ + uint64_t SourceRectLeft : 30; /* 29..0 */ + uint64_t reserved17 : 2; /* 31..30 */ + uint64_t SourceRectRight : 30; /* 61..32 */ + uint64_t reserved18 : 2; /* 63..62 */ + uint64_t SourceRectTop : 30; /* 93..64 */ + uint64_t reserved19 : 2; /* 95..94 */ + uint64_t SourceRectBottom : 30; /* 125..96 */ + uint64_t reserved20 : 2; /* 127..126 */ +} SurfaceListSurfaceStruct; + +typedef struct { + uint64_t l0 : 20; /* 19..0 */ + uint64_t l1 : 20; /* 39..20 */ + uint64_t l2 : 20; /* 59..40 */ + uint64_t r_shift : 4; /* 63..60 */ + uint64_t l3 : 20; /* 83..64 */ + uint64_t PlanarAlpha : 10; /* 93..84 */ + uint64_t ConstantAlpha : 1; /* 94 */ + uint64_t ClipEnabled : 1; /* 95 */ + uint64_t LumaKeyLower : 10; /* 105..96 */ + uint64_t reserved6 : 3; /* 108..106 */ + uint64_t StereoInterleave : 3; /* 111..109 */ + uint64_t LumaKeyUpper : 10; /* 121..112 */ + uint64_t reserved7 : 2; /* 123..122 */ + uint64_t reserved8 : 1; /* 124 */ + uint64_t LumaKeyEnabled : 1; /* 125 */ + uint64_t reserved9 : 2; /* 127..126 */ +} ColorConversionLumaAlphaStruct; + +typedef struct { + uint64_t c00 : 20; /* 19..0 */ + uint64_t c10 : 20; /* 39..20 */ + uint64_t c20 : 20; /* 59..40 */ + uint64_t r_shift : 4; /* 63..60 */ + uint64_t c01 : 20; /* 83..64 */ + uint64_t c11 : 20; /* 103..84 */ + uint64_t c21 : 20; /* 123..104 */ + uint64_t reserved0 : 4; /* 127..124 */ + /* 128 */ + uint64_t c02 : 20; /* 19..0 */ + uint64_t c12 : 20; /* 39..20 */ + uint64_t c22 : 20; /* 59..40 */ + uint64_t reserved1 : 4; /* 63..60 */ + uint64_t c03 : 20; /* 83..64 */ + uint64_t c13 : 20; /* 103..84 */ + uint64_t c23 : 20; /* 123..104 */ + uint64_t reserved2 : 4; /* 127..124 */ +} ColorConversionMatrixStruct; + +typedef struct { + uint64_t low : 10; /* 9..0 */ + uint64_t reserved0 : 6; /* 15..10 */ + uint64_t high : 10; /* 25..16 */ + uint64_t reserved1 : 6; /* 31..26 */ + uint64_t reserved2 : 32; /* 63..32 */ + uint64_t reserved3 : 32; /* 95..64 */ + uint64_t reserved4 : 32; /* 127..96 */ +} ColorConversionClampStruct; + +typedef struct { + uint64_t PixelFormat : 7; /* 6..0 */ + uint64_t reserved0 : 1; /* 7 */ + uint64_t AlphaFillMode : 3; /* 10..8 */ + uint64_t AlphaFillSlot : 3; /* 13..11 */ + uint64_t BackgroundAlpha : 10; /* 23..14 */ + uint64_t BackgroundR : 10; /* 33..24 */ + uint64_t BackgroundG : 10; /* 43..34 */ + uint64_t BackgroundB : 10; /* 53..44 */ + uint64_t ChromaLocHoriz : 2; /* 55..54 */ + uint64_t ChromaLocVert : 2; /* 57..56 */ + uint64_t reserved1 : 6; /* 63..58 */ + uint64_t LumaWidth : 14; /* 77..64 */ + uint64_t reserved2 : 2; /* 79..78 */ + uint64_t LumaHeight : 14; /* 93..80 */ + uint64_t reserved3 : 2; /* 95..94 */ + uint64_t ChromaWidth : 14; /* 109..96 */ + uint64_t reserved4 : 2; /* 111..110 */ + uint64_t ChromaHeight : 14; /* 125..112 */ + uint64_t reserved5 : 2; /* 127..126 */ + /* 128 */ + uint64_t TargetRectLeft : 14; /* 13..0 */ + uint64_t reserved6 : 2; /* 15..14 */ + uint64_t TargetRectRight : 14; /* 29..16 */ + uint64_t reserved7 : 2; /* 31..30 */ + uint64_t TargetRectTop : 14; /* 45..32 */ + uint64_t reserved8 : 2; /* 47..46 */ + uint64_t TargetRectBottom : 14; /* 61..48 */ + uint64_t reserved9 : 2; /* 63..62 */ + uint64_t SurfaceWidth : 14; /* 77..64 */ + uint64_t reserved10 : 2; /* 79..78 */ + uint64_t SurfaceHeight : 14; /* 93..80 */ + uint64_t reserved11 : 2; /* 95..94 */ + uint64_t BlkKind : 4; /* 99..96 */ + uint64_t BlkHeight : 4; /* 103..100 */ + uint64_t OutputFlipX : 1; /* 104 */ + uint64_t OutputFlipY : 1; /* 105 */ + uint64_t OutputTranspose : 1; /* 106 */ + uint64_t reserved12 : 21; /* 127..107 */ +} Blending0Struct; + +typedef struct { + uint64_t AlphaK1 : 10; /* 9..0 */ + uint64_t reserved0 : 6; /* 15..10 */ + uint64_t AlphaK2 : 10; /* 25..16 */ + uint64_t reserved1 : 6; /* 31..26 */ + uint64_t SrcFactCMatchSelect : 3; /* 34..32 */ + uint64_t reserved2 : 1; /* 35 */ + uint64_t DstFactCMatchSelect : 3; /* 38..36 */ + uint64_t reserved3 : 1; /* 39 */ + uint64_t SrcFactAMatchSelect : 3; /* 42..40 */ + uint64_t reserved4 : 1; /* 43 */ + uint64_t DstFactAMatchSelect : 3; /* 46..44 */ + uint64_t reserved5 : 1; /* 47 */ + uint64_t reserved6 : 4; /* 51..48 */ + uint64_t reserved7 : 4; /* 55..52 */ + uint64_t reserved8 : 4; /* 59..56 */ + uint64_t reserved9 : 4; /* 63..60 */ + uint64_t reserved10 : 2; /* 65..64 */ + uint64_t OverrideR : 10; /* 75..66 */ + uint64_t OverrideG : 10; /* 85..76 */ + uint64_t OverrideB : 10; /* 95..86 */ + uint64_t OverrideA : 10; /* 105..96 */ + uint64_t reserved11 : 2; /* 107..106 */ + uint64_t UseOverrideR : 1; /* 108 */ + uint64_t UseOverrideG : 1; /* 109 */ + uint64_t UseOverrideB : 1; /* 110 */ + uint64_t UseOverrideA : 1; /* 111 */ + uint64_t MaskR : 1; /* 112 */ + uint64_t MaskG : 1; /* 113 */ + uint64_t MaskB : 1; /* 114 */ + uint64_t MaskA : 1; /* 115 */ + uint64_t reserved12 : 12; /* 127..116 */ +} BlendingSurfaceStruct; + +typedef struct { + uint64_t TargetRectLeft : 14; /* 13..0 */ + uint64_t reserved0 : 2; /* 15..14 */ + uint64_t TargetRectRight : 14; /* 29..16 */ + uint64_t reserved1 : 2; /* 31..30 */ + uint64_t TargetRectTop : 14; /* 45..32 */ + uint64_t reserved2 : 2; /* 47..46 */ + uint64_t TargetRectBottom : 14; /* 61..48 */ + uint64_t reserved3 : 2; /* 63..62 */ + uint64_t Enable0 : 8; /* 71..64 */ + uint64_t Enable1 : 8; /* 79..72 */ + uint64_t Enable2 : 8; /* 87..80 */ + uint64_t Enable3 : 8; /* 95..88 */ + uint64_t Enable4 : 8; /* 103..96 */ + uint64_t DownsampleHoriz : 11; /* 114..104 */ + uint64_t reserved4 : 1; /* 115 */ + uint64_t DownsampleVert : 11; /* 126..116 */ + uint64_t reserved5 : 1; /* 127 */ + /* 128 */ + uint64_t FilterNoise0 : 10; /* 9..0 */ + uint64_t FilterDetail0 : 10; /* 19..10 */ + uint64_t FilterNoise1 : 10; /* 29..20 */ + uint64_t reserved6 : 2; /* 31..30 */ + uint64_t FilterDetail1 : 10; /* 41..32 */ + uint64_t FilterNoise2 : 10; /* 51..42 */ + uint64_t FilterDetail2 : 10; /* 61..52 */ + uint64_t reserved7 : 2; /* 63..62 */ + uint64_t FilterNoise3 : 10; /* 73..64 */ + uint64_t FilterDetail3 : 10; /* 83..74 */ + uint64_t FilterNoise4 : 10; /* 93..84 */ + uint64_t reserved8 : 2; /* 95..94 */ + uint64_t FilterDetail4 : 10; /* 105..96 */ + uint64_t reserved9 : 22; /* 127..106 */ + /* 256 */ + uint64_t ChromaNoise0 : 10; /* 9..0 */ + uint64_t ChromaDetail0 : 10; /* 19..10 */ + uint64_t ChromaNoise1 : 10; /* 29..20 */ + uint64_t reserved10 : 2; /* 31..30 */ + uint64_t ChromaDetail1 : 10; /* 41..32 */ + uint64_t ChromaNoise2 : 10; /* 51..42 */ + uint64_t ChromaDetail2 : 10; /* 61..52 */ + uint64_t reserved11 : 2; /* 63..62 */ + uint64_t ChromaNoise3 : 10; /* 73..64 */ + uint64_t ChromaDetail3 : 10; /* 83..74 */ + uint64_t ChromaNoise4 : 10; /* 93..84 */ + uint64_t reserved12 : 2; /* 95..94 */ + uint64_t ChromaDetail4 : 10; /* 105..96 */ + uint64_t reserved13 : 22; /* 127..106 */ + /* 384 */ + uint64_t Mode0 : 4; /* 3..0 */ + uint64_t AccumWeight0 : 3; /* 6..4 */ + uint64_t Iir0 : 11; /* 17..7 */ + uint64_t reserved14 : 2; /* 19..18 */ + uint64_t Mode1 : 4; /* 23..20 */ + uint64_t AccumWeight1 : 3; /* 26..24 */ + uint64_t Iir1 : 11; /* 37..27 */ + uint64_t reserved15 : 2; /* 39..38 */ + uint64_t Mode2 : 4; /* 43..40 */ + uint64_t AccumWeight2 : 3; /* 46..44 */ + uint64_t Iir2 : 11; /* 57..47 */ + uint64_t reserved16 : 6; /* 63..58 */ + uint64_t Mode3 : 4; /* 67..64 */ + uint64_t AccumWeight3 : 3; /* 70..68 */ + uint64_t Iir3 : 11; /* 81..71 */ + uint64_t reserved17 : 2; /* 83..82 */ + uint64_t Mode4 : 4; /* 87..84 */ + uint64_t AccumWeight4 : 3; /* 90..88 */ + uint64_t Iir4 : 11; /* 101..91 */ + uint64_t reserved18 : 8; /* 109..102 */ + uint64_t OutputFlipX : 1; /* 110 */ + uint64_t OutputFlipY : 1; /* 111 */ + uint64_t reserved19 : 10; /* 121..112 */ + uint64_t reserved20 : 6; /* 127..122 */ +} FetchControl0Struct; + +typedef struct { + uint64_t f00 : 10; /* 9..0 */ + uint64_t f10 : 10; /* 19..10 */ + uint64_t f20 : 10; /* 29..20 */ + uint64_t reserved0 : 2; /* 31..30 */ + uint64_t f01 : 10; /* 41..32 */ + uint64_t f11 : 10; /* 51..42 */ + uint64_t f21 : 10; /* 61..52 */ + uint64_t reserved1 : 2; /* 63..62 */ + uint64_t f02 : 10; /* 73..64 */ + uint64_t f12 : 10; /* 83..74 */ + uint64_t f22 : 10; /* 93..84 */ + uint64_t reserved2 : 2; /* 95..94 */ + uint64_t f03 : 10; /* 105..96 */ + uint64_t f13 : 10; /* 115..106 */ + uint64_t f23 : 10; /* 125..116 */ + uint64_t reserved3 : 2; /* 127..126 */ +} FetchControlCoeffStruct; + +typedef struct { + SurfaceCache0Struct surfaceCache0Struct; + SurfaceList0Struct surfaceList0Struct; + SurfaceListClearRectStruct surfaceListClearRectStruct[4]; + SurfaceListSurfaceStruct surfaceListSurfaceStruct[5]; + ColorConversionLumaAlphaStruct colorConversionLumaAlphaStruct[5]; + ColorConversionMatrixStruct colorConversionMatrixStruct[5]; + ColorConversionClampStruct colorConversionClampStruct[5]; + Blending0Struct blending0Struct; + BlendingSurfaceStruct blendingSurfaceStruct[5]; + FetchControl0Struct fetchControl0Struct; + FetchControlCoeffStruct fetchControlCoeffStruct[520]; +} ConfigStruct; + +#endif diff --git a/lib/libdrm/tests/tegra/vic40.c b/lib/libdrm/tests/tegra/vic40.c new file mode 100644 index 000000000..1af092505 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic40.c @@ -0,0 +1,338 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <string.h> + +#include "private.h" +#include "tegra.h" +#include "vic.h" +#include "vic40.h" + +struct vic40 { + struct vic base; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } config; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } filter; +}; + +static int vic40_fill(struct vic *v, struct vic_image *output, + unsigned int left, unsigned int top, + unsigned int right, unsigned int bottom, + unsigned int alpha, unsigned int red, + unsigned int green, unsigned int blue) +{ + struct vic40 *vic = container_of(v, struct vic40, base); + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = top; + c->outputConfig.TargetRectLeft = left; + c->outputConfig.TargetRectRight = right; + c->outputConfig.TargetRectBottom = bottom; + c->outputConfig.BackgroundAlpha = alpha; + c->outputConfig.BackgroundR = red; + c->outputConfig.BackgroundG = green; + c->outputConfig.BackgroundB = blue; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic40_blit(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic40 *vic = container_of(v, struct vic40, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 1023; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 1023; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic40_flip(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic40 *vic = container_of(v, struct vic40, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 1023; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + c->outputConfig.OutputFlipY = 1; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 1023; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic40_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, struct vic_image *output, + struct vic_image **inputs, unsigned int num_inputs) +{ + struct vic40 *vic = container_of(v, struct vic40, base); + unsigned int i; + + if (num_inputs > 1) + return -EINVAL; + + VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1); + VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0); + + for (i = 0; i < num_inputs; i++) + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0); + + VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8); + + return 0; +} + +static void vic40_free(struct vic *v) +{ + struct vic40 *vic = container_of(v, struct vic40, base); + + drm_tegra_channel_unmap(vic->filter.map); + drm_tegra_bo_unref(vic->filter.bo); + + drm_tegra_channel_unmap(vic->config.map); + drm_tegra_bo_unref(vic->config.bo); + + drm_tegra_syncpoint_free(v->syncpt); + + free(vic); +} + +static const struct vic_ops vic40_ops = { + .fill = vic40_fill, + .blit = vic40_blit, + .flip = vic40_flip, + .execute = vic40_execute, + .free = vic40_free, +}; + +int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp) +{ + struct vic40 *vic; + void *ptr; + int err; + + vic = calloc(1, sizeof(*vic)); + if (!vic) + return -ENOMEM; + + vic->base.drm = drm; + vic->base.channel = channel; + vic->base.ops = &vic40_ops; + vic->base.version = 0x21; + + err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate configuration structurer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->config.map); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate filter buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(vic->filter.bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 16384); + drm_tegra_bo_unmap(vic->filter.bo); + + err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->filter.map); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", + strerror(-err)); + return err; + } + + if (vicp) + *vicp = &vic->base; + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic40.h b/lib/libdrm/tests/tegra/vic40.h new file mode 100644 index 000000000..a62301a8a --- /dev/null +++ b/lib/libdrm/tests/tegra/vic40.h @@ -0,0 +1,285 @@ +/* + * Copyright © 2016-2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIC40_H +#define VIC40_H + +#include <stdint.h> + +#define NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x00000200 +#define NVB0B6_VIDEO_COMPOSITOR_EXECUTE 0x00000300 +#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET 0x00000400 +#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_U_OFFSET 0x00000404 +#define NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_CHROMA_V_OFFSET 0x00000408 +#define NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x00000704 +#define NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x00000708 +#define NVB0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x00000714 +#define NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x00000720 + +typedef struct { + uint64_t SlotEnable : 1; /* 0 */ + uint64_t DeNoise : 1; /* 1 */ + uint64_t AdvancedDenoise : 1; /* 2 */ + uint64_t CadenceDetect : 1; /* 3 */ + uint64_t MotionMap : 1; /* 4 */ + uint64_t MMapCombine : 1; /* 5 */ + uint64_t IsEven : 1; /* 6 */ + uint64_t ChromaEven : 1; /* 7 */ + uint64_t CurrentFieldEnable : 1; /* 8 */ + uint64_t PrevFieldEnable : 1; /* 9 */ + uint64_t NextFieldEnable : 1; /* 10 */ + uint64_t NextNrFieldEnable : 1; /* 11 */ + uint64_t CurMotionFieldEnable : 1; /* 12 */ + uint64_t PrevMotionFieldEnable : 1; /* 13 */ + uint64_t PpMotionFieldEnable : 1; /* 14 */ + uint64_t CombMotionFieldEnable : 1; /* 15 */ + uint64_t FrameFormat : 4; /* 19..16 */ + uint64_t FilterLengthY : 2; /* 21..20 */ + uint64_t FilterLengthX : 2; /* 23..22 */ + uint64_t Panoramic : 12; /* 35..24 */ + uint64_t reserved1 : 22; /* 57..36 */ + uint64_t DetailFltClamp : 6; /* 63..58 */ + uint64_t FilterNoise : 10; /* 73..64 */ + uint64_t FilterDetail : 10; /* 83..74 */ + uint64_t ChromaNoise : 10; /* 93..84 */ + uint64_t ChromaDetail : 10; /* 103..94 */ + uint64_t DeinterlaceMode : 4; /* 107..104 */ + uint64_t MotionAccumWeight : 3; /* 110..108 */ + uint64_t NoiseIir : 11; /* 121..111 */ + uint64_t LightLevel : 4; /* 125..122 */ + uint64_t reserved4 : 2; /* 127..126 */ + /* 128 */ + uint64_t SoftClampLow : 10; /* 9..0 */ + uint64_t SoftClampHigh : 10; /* 19..10 */ + uint64_t reserved5 : 3; /* 22..20 */ + uint64_t reserved6 : 9; /* 31..23 */ + uint64_t PlanarAlpha : 10; /* 41..32 */ + uint64_t ConstantAlpha : 1; /* 42 */ + uint64_t StereoInterleave : 3; /* 45..43 */ + uint64_t ClipEnabled : 1; /* 46 */ + uint64_t ClearRectMask : 8; /* 54..47 */ + uint64_t DegammaMode : 2; /* 56..55 */ + uint64_t reserved7 : 1; /* 57 */ + uint64_t DecompressEnable : 1; /* 58 */ + uint64_t reserved9 : 5; /* 63..59 */ + uint64_t DecompressCtbCount : 8; /* 71..64 */ + uint64_t DecompressZbcColor : 32; /* 103..72 */ + uint64_t reserved12 : 24; /* 127..104 */ + /* 256 */ + uint64_t SourceRectLeft : 30; /* 29..0 */ + uint64_t reserved14 : 2; /* 31..30 */ + uint64_t SourceRectRight : 30; /* 61..32 */ + uint64_t reserved15 : 2; /* 63..62 */ + uint64_t SourceRectTop : 30; /* 93..64 */ + uint64_t reserved16 : 2; /* 95..94 */ + uint64_t SourceRectBottom : 30; /* 125..96 */ + uint64_t reserved17 : 2; /* 127..126 */ + /* 384 */ + uint64_t DestRectLeft : 14; /* 13..0 */ + uint64_t reserved18 : 2; /* 15..14 */ + uint64_t DestRectRight : 14; /* 29..16 */ + uint64_t reserved19 : 2; /* 31..30 */ + uint64_t DestRectTop : 14; /* 45..32 */ + uint64_t reserved20 : 2; /* 47..46 */ + uint64_t DestRectBottom : 14; /* 61..48 */ + uint64_t reserved21 : 2; /* 63..62 */ + uint64_t reserved22 : 32; /* 95..64 */ + uint64_t reserved23 : 32; /* 127..96 */ +} SlotConfig; + +typedef struct { + uint64_t SlotPixelFormat : 7; /* 6..0 */ + uint64_t SlotChromaLocHoriz : 2; /* 8..7 */ + uint64_t SlotChromaLocVert : 2; /* 10..9 */ + uint64_t SlotBlkKind : 4; /* 14..11 */ + uint64_t SlotBlkHeight : 4; /* 18..15 */ + uint64_t SlotCacheWidth : 3; /* 21..19 */ + uint64_t reserved0 : 10; /* 31..22 */ + uint64_t SlotSurfaceWidth : 14; /* 45..32 */ + uint64_t SlotSurfaceHeight : 14; /* 59..46 */ + uint64_t reserved1 : 4; /* 63..60 */ + uint64_t SlotLumaWidth : 14; /* 77..64 */ + uint64_t SlotLumaHeight : 14; /* 91..78 */ + uint64_t reserved2 : 4; /* 95..92 */ + uint64_t SlotChromaWidth : 14; /* 109..96 */ + uint64_t SlotChromaHeight : 14; /* 123..110 */ + uint64_t reserved3 : 4; /* 127..124 */ +} SlotSurfaceConfig; + +typedef struct { + uint64_t luma_coeff0 : 20; /* 19..0 */ + uint64_t luma_coeff1 : 20; /* 39..20 */ + uint64_t luma_coeff2 : 20; /* 59..40 */ + uint64_t luma_r_shift : 4; /* 63..60 */ + uint64_t luma_coeff3 : 20; /* 83..64 */ + uint64_t LumaKeyLower : 10; /* 93..84 */ + uint64_t LumaKeyUpper : 10; /* 103..94 */ + uint64_t LumaKeyEnabled : 1; /* 104 */ + uint64_t reserved0 : 2; /* 106..105 */ + uint64_t reserved1 : 21; /* 127..107 */ +} LumaKeyStruct; + +typedef struct { + uint64_t matrix_coeff00 : 20; /* 19..0 */ + uint64_t matrix_coeff10 : 20; /* 39..20 */ + uint64_t matrix_coeff20 : 20; /* 59..40 */ + uint64_t matrix_r_shift : 4; /* 63..60 */ + uint64_t matrix_coeff01 : 20; /* 83..64 */ + uint64_t matrix_coeff11 : 20; /* 103..84 */ + uint64_t matrix_coeff21 : 20; /* 123..104 */ + uint64_t reserved0 : 3; /* 126..124 */ + uint64_t matrix_enable : 1; /* 127 */ + /* 128 */ + uint64_t matrix_coeff02 : 20; /* 19..0 */ + uint64_t matrix_coeff12 : 20; /* 39..20 */ + uint64_t matrix_coeff22 : 20; /* 59..40 */ + uint64_t reserved1 : 4; /* 63..60 */ + uint64_t matrix_coeff03 : 20; /* 83..64 */ + uint64_t matrix_coeff13 : 20; /* 103..84 */ + uint64_t matrix_coeff23 : 20; /* 123..104 */ + uint64_t reserved2 : 4; /* 127..124 */ +} MatrixStruct; + +typedef struct { + uint64_t ClearRect0Left : 14; /* 13..0 */ + uint64_t reserved0 : 2; /* 15..14 */ + uint64_t ClearRect0Right : 14; /* 29..16 */ + uint64_t reserved1 : 2; /* 31..30 */ + uint64_t ClearRect0Top : 14; /* 45..32 */ + uint64_t reserved2 : 2; /* 47..46 */ + uint64_t ClearRect0Bottom : 14; /* 61..48 */ + uint64_t reserved3 : 2; /* 63..62 */ + uint64_t ClearRect1Left : 14; /* 77..64 */ + uint64_t reserved4 : 2; /* 79..78 */ + uint64_t ClearRect1Right : 14; /* 93..80 */ + uint64_t reserved5 : 2; /* 95..94 */ + uint64_t ClearRect1Top : 14; /* 109..96 */ + uint64_t reserved6 : 2; /* 111..110 */ + uint64_t ClearRect1Bottom : 14; /* 125..112 */ + uint64_t reserved7 : 2; /* 127..126 */ +} ClearRectStruct; + +typedef struct { + uint64_t AlphaK1 : 10; /* 9..0 */ + uint64_t reserved0 : 6; /* 15..10 */ + uint64_t AlphaK2 : 10; /* 25..16 */ + uint64_t reserved1 : 6; /* 31..26 */ + uint64_t SrcFactCMatchSelect : 3; /* 34..32 */ + uint64_t reserved2 : 1; /* 35 */ + uint64_t DstFactCMatchSelect : 3; /* 38..36 */ + uint64_t reserved3 : 1; /* 39 */ + uint64_t SrcFactAMatchSelect : 3; /* 42..40 */ + uint64_t reserved4 : 1; /* 43 */ + uint64_t DstFactAMatchSelect : 3; /* 46..44 */ + uint64_t reserved5 : 1; /* 47 */ + uint64_t reserved6 : 4; /* 51..48 */ + uint64_t reserved7 : 4; /* 55..52 */ + uint64_t reserved8 : 4; /* 59..56 */ + uint64_t reserved9 : 4; /* 63..60 */ + uint64_t reserved10 : 2; /* 65..64 */ + uint64_t OverrideR : 10; /* 75..66 */ + uint64_t OverrideG : 10; /* 85..76 */ + uint64_t OverrideB : 10; /* 95..86 */ + uint64_t OverrideA : 10; /* 105..96 */ + uint64_t reserved11 : 2; /* 107..106 */ + uint64_t UseOverrideR : 1; /* 108 */ + uint64_t UseOverrideG : 1; /* 109 */ + uint64_t UseOverrideB : 1; /* 110 */ + uint64_t UseOverrideA : 1; /* 111 */ + uint64_t MaskR : 1; /* 112 */ + uint64_t MaskG : 1; /* 113 */ + uint64_t MaskB : 1; /* 114 */ + uint64_t MaskA : 1; /* 115 */ + uint64_t reserved12 : 12; /* 127..116 */ +} BlendingSlotStruct; + +typedef struct { + uint64_t AlphaFillMode : 3; /* 2..0 */ + uint64_t AlphaFillSlot : 3; /* 5..3 */ + uint64_t BackgroundAlpha : 10; /* 15..6 */ + uint64_t BackgroundR : 10; /* 25..16 */ + uint64_t BackgroundG : 10; /* 35..26 */ + uint64_t BackgroundB : 10; /* 45..36 */ + uint64_t RegammaMode : 2; /* 47..46 */ + uint64_t OutputFlipX : 1; /* 48 */ + uint64_t OutputFlipY : 1; /* 49 */ + uint64_t OutputTranspose : 1; /* 50 */ + uint64_t reserved1 : 1; /* 51 */ + uint64_t reserved2 : 12; /* 63..52 */ + uint64_t TargetRectLeft : 14; /* 77..64 */ + uint64_t reserved3 : 2; /* 79..78 */ + uint64_t TargetRectRight : 14; /* 93..80 */ + uint64_t reserved4 : 2; /* 95..94 */ + uint64_t TargetRectTop : 14; /* 109..96 */ + uint64_t reserved5 : 2; /* 111..110 */ + uint64_t TargetRectBottom : 14; /* 125..112 */ + uint64_t reserved6 : 2; /* 127..126 */ +} OutputConfig; + +typedef struct { + uint64_t OutPixelFormat : 7; /* 6..0 */ + uint64_t OutChromaLocHoriz : 2; /* 8..7 */ + uint64_t OutChromaLocVert : 2; /* 10..9 */ + uint64_t OutBlkKind : 4; /* 14..11 */ + uint64_t OutBlkHeight : 4; /* 18..15 */ + uint64_t reserved0 : 3; /* 21..19 */ + uint64_t reserved1 : 10; /* 31..22 */ + uint64_t OutSurfaceWidth : 14; /* 45..32 */ + uint64_t OutSurfaceHeight : 14; /* 59..46 */ + uint64_t reserved2 : 4; /* 63..60 */ + uint64_t OutLumaWidth : 14; /* 77..64 */ + uint64_t OutLumaHeight : 14; /* 91..78 */ + uint64_t reserved3 : 4; /* 95..92 */ + uint64_t OutChromaWidth : 14; /* 109..96 */ + uint64_t OutChromaHeight : 14; /* 123..110 */ + uint64_t reserved4 : 4; /* 127..124 */ +} OutputSurfaceConfig; + +typedef struct { + uint64_t DownsampleHoriz : 11; /* 10..0 */ + uint64_t reserved0 : 5; /* 15..11 */ + uint64_t DownsampleVert : 11; /* 26..16 */ + uint64_t reserved1 : 5; /* 31..27 */ + uint64_t reserved2 : 32; /* 63..32 */ + uint64_t reserved3 : 32; /* 95..64 */ + uint64_t reserved4 : 32; /* 127..96 */ +} PipeConfig; + +typedef struct { + SlotConfig slotConfig; + SlotSurfaceConfig slotSurfaceConfig; + LumaKeyStruct lumaKeyStruct; + MatrixStruct colorMatrixStruct; + MatrixStruct gamutMatrixStruct; + BlendingSlotStruct blendingSlotStruct; +} SlotStruct; + +typedef struct { + PipeConfig pipeConfig; + OutputConfig outputConfig; + OutputSurfaceConfig outputSurfaceConfig; + MatrixStruct outColorMatrixStruct; + ClearRectStruct clearRectStruct[4]; + SlotStruct slotStruct[8]; +} ConfigStruct; + +#endif diff --git a/lib/libdrm/tests/tegra/vic41.c b/lib/libdrm/tests/tegra/vic41.c new file mode 100644 index 000000000..edbc748d1 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic41.c @@ -0,0 +1,342 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <string.h> + +#include "private.h" +#include "tegra.h" +#include "vic.h" +#include "vic41.h" + +struct vic41 { + struct vic base; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } config; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } filter; +}; + +static int vic41_fill(struct vic *v, struct vic_image *output, + unsigned int left, unsigned int top, + unsigned int right, unsigned int bottom, + unsigned int alpha, unsigned int red, + unsigned int green, unsigned int blue) +{ + struct vic41 *vic = container_of(v, struct vic41, base); + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = top; + c->outputConfig.TargetRectLeft = left; + c->outputConfig.TargetRectRight = right; + c->outputConfig.TargetRectBottom = bottom; + c->outputConfig.BackgroundAlpha = alpha; + c->outputConfig.BackgroundR = red; + c->outputConfig.BackgroundG = green; + c->outputConfig.BackgroundB = blue; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic41_blit(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic41 *vic = container_of(v, struct vic41, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 255; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 255; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic41_flip(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic41 *vic = container_of(v, struct vic41, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 255; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + c->outputConfig.OutputFlipY = 1; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 255; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic41_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, struct vic_image *output, + struct vic_image **inputs, unsigned int num_inputs) +{ + struct vic41 *vic = container_of(v, struct vic41, base); + unsigned int i; + + if (num_inputs > 1) + return -EINVAL; + + VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1); + VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET, vic->filter.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0); + + for (i = 0; i < num_inputs; i++) { + uint32_t method = NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(0) + (i * 3) * 4; + + VIC_PUSH_BUFFER(pushbuf, ptrp, method, inputs[i]->map, 0, 0); + } + + VIC_PUSH_METHOD(pushbuf, ptrp, NVB1B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8); + + return 0; +} + +static void vic41_free(struct vic *v) +{ + struct vic41 *vic = container_of(v, struct vic41, base); + + drm_tegra_channel_unmap(vic->filter.map); + drm_tegra_bo_unref(vic->filter.bo); + + drm_tegra_channel_unmap(vic->config.map); + drm_tegra_bo_unref(vic->config.bo); + + drm_tegra_syncpoint_free(v->syncpt); + + free(vic); +} + +static const struct vic_ops vic41_ops = { + .fill = vic41_fill, + .blit = vic41_blit, + .flip = vic41_flip, + .execute = vic41_execute, + .free = vic41_free, +}; + +int vic41_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp) +{ + struct vic41 *vic; + void *ptr; + int err; + + vic = calloc(1, sizeof(*vic)); + if (!vic) + return -ENOMEM; + + vic->base.drm = drm; + vic->base.channel = channel; + vic->base.ops = &vic41_ops; + vic->base.version = 0x18; + + err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate configuration structurer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->config.map); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate filter buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(vic->filter.bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 16384); + drm_tegra_bo_unmap(vic->filter.bo); + + err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->filter.map); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", + strerror(-err)); + return err; + } + + if (vicp) + *vicp = &vic->base; + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic41.h b/lib/libdrm/tests/tegra/vic41.h new file mode 100644 index 000000000..07d7019a7 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic41.h @@ -0,0 +1,372 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIC41_H +#define VIC41_H + +#include <stdint.h> + +#define NVB1B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID 0x00000200 +#define NVB1B6_VIDEO_COMPOSITOR_EXECUTE 0x00000300 +#define NVB1B6_VIDEO_COMPOSITOR_SET_PICTURE_INDEX 0x00000700 +#define NVB1B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS 0x00000704 +#define NVB1B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET 0x00000708 +#define NVB1B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET 0x0000070c +#define NVB1B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET 0x00000714 +#define NVB1B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET 0x00000720 +#define NVB1B6_VIDEO_COMPOSITOR_SET_HISTORY_BUFFER_OFFSET(slot) (0x00000780 + (slot) * 4) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(slot) (0x00001200 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_U_OFFSET(slot) (0x00001204 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE0_CHROMA_V_OFFSET(slot) (0x00001208 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_LUMA_OFFSET(slot) (0x0000120c + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_U_OFFSET(slot) (0x00001210 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE1_CHROMA_V_OFFSET(slot) (0x00001214 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_LUMA_OFFSET(slot) (0x00001218 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_U_OFFSET(slot) (0x0000121c + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE2_CHROMA_V_OFFSET(slot) (0x00001220 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_LUMA_OFFSET(slot) (0x00001224 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_U_OFFSET(slot) (0x00001228 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE3_CHROMA_V_OFFSET(slot) (0x0000122c + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_LUMA_OFFSET(slot) (0x00001230 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_U_OFFSET(slot) (0x00001234 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE4_CHROMA_V_OFFSET(slot) (0x00001238 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_LUMA_OFFSET(slot) (0x0000123c + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_U_OFFSET(slot) (0x00001240 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE5_CHROMA_V_OFFSET(slot) (0x00001244 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_LUMA_OFFSET(slot) (0x00001248 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_U_OFFSET(slot) (0x0000124c + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE6_CHROMA_V_OFFSET(slot) (0x00001250 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_LUMA_OFFSET(slot) (0x00001254 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_U_OFFSET(slot) (0x00001258 + (slot) * 0x00000060) +#define NVB1B6_VIDEO_COMPOSITOR_SET_SURFACE7_CHROMA_V_OFFSET(slot) (0x0000125c + (slot) * 0x00000060) + +typedef struct { + uint64_t SlotEnable : 1; /* 0 */ + uint64_t DeNoise : 1; /* 1 */ + uint64_t AdvancedDenoise : 1; /* 2 */ + uint64_t CadenceDetect : 1; /* 3 */ + uint64_t MotionMap : 1; /* 4 */ + uint64_t MMapCombine : 1; /* 5 */ + uint64_t IsEven : 1; /* 6 */ + uint64_t ChromaEven : 1; /* 7 */ + uint64_t CurrentFieldEnable : 1; /* 8 */ + uint64_t PrevFieldEnable : 1; /* 9 */ + uint64_t NextFieldEnable : 1; /* 10 */ + uint64_t NextNrFieldEnable : 1; /* 11 */ + uint64_t CurMotionFieldEnable : 1; /* 12 */ + uint64_t PrevMotionFieldEnable : 1; /* 13 */ + uint64_t PpMotionFieldEnable : 1; /* 14 */ + uint64_t CombMotionFieldEnable : 1; /* 15 */ + uint64_t FrameFormat : 4; /* 19..16 */ + uint64_t FilterLengthY : 2; /* 21..20 */ + uint64_t FilterLengthX : 2; /* 23..22 */ + uint64_t Panoramic : 12; /* 35..24 */ + uint64_t ChromaUpLengthY : 2; /* 37..36 */ + uint64_t ChromaUpLengthX : 2; /* 39..38 */ + uint64_t reserved1 : 18; /* 57..40 */ + uint64_t DetailFltClamp : 6; /* 63..58 */ + uint64_t FilterNoise : 10; /* 73..64 */ + uint64_t FilterDetail : 10; /* 83..74 */ + uint64_t ChromaNoise : 10; /* 93..84 */ + uint64_t ChromaDetail : 10; /* 103..94 */ + uint64_t DeinterlaceMode : 4; /* 107..104 */ + uint64_t MotionAccumWeight : 3; /* 110..108 */ + uint64_t NoiseIir : 11; /* 121..111 */ + uint64_t LightLevel : 4; /* 125..122 */ + uint64_t reserved4 : 2; /* 127..126 */ + /* 128 */ + uint64_t SoftClampLow : 10; /* 9..0 */ + uint64_t SoftClampHigh : 10; /* 19..10 */ + uint64_t reserved5 : 12; /* 31..20 */ + uint64_t reserved6 : 2; /* 33..32 */ + uint64_t PlanarAlpha : 8; /* 41..34 */ + uint64_t ConstantAlpha : 1; /* 42 */ + uint64_t StereoInterleave : 3; /* 45..43 */ + uint64_t ClipEnabled : 1; /* 46 */ + uint64_t ClearRectMask : 8; /* 54..47 */ + uint64_t DegammaMode : 2; /* 56..55 */ + uint64_t reserved7 : 1; /* 57 */ + uint64_t DecompressEnable : 1; /* 58 */ + uint64_t DecompressKind : 4; /* 62..59 */ + uint64_t reserved9 : 1; /* 63 */ + uint64_t DecompressCtbCount : 8; /* 71..64 */ + uint64_t DecompressZbcColor : 32; /* 103..72 */ + uint64_t reserved12 : 24; /* 127..104 */ + /* 256 */ + uint64_t SourceRectLeft : 30; /* 29..0 */ + uint64_t reserved14 : 2; /* 31..30 */ + uint64_t SourceRectRight : 30; /* 61..32 */ + uint64_t reserved15 : 2; /* 63..62 */ + uint64_t SourceRectTop : 30; /* 93..64 */ + uint64_t reserved16 : 2; /* 95..94 */ + uint64_t SourceRectBottom : 30; /* 125..96 */ + uint64_t reserved17 : 2; /* 127..126 */ + /* 384 */ + uint64_t DestRectLeft : 14; /* 13..0 */ + uint64_t reserved18 : 2; /* 15..14 */ + uint64_t DestRectRight : 14; /* 29..16 */ + uint64_t reserved19 : 2; /* 31..30 */ + uint64_t DestRectTop : 14; /* 45..32 */ + uint64_t reserved20 : 2; /* 47..46 */ + uint64_t DestRectBottom : 14; /* 61..48 */ + uint64_t reserved21 : 2; /* 63..62 */ + uint64_t reserved22 : 32; /* 95..64 */ + uint64_t reserved23 : 32; /* 127..96 */ +} SlotConfig; + +typedef struct { + uint64_t SlotPixelFormat : 7; /* 6..0 */ + uint64_t SlotChromaLocHoriz : 2; /* 8..7 */ + uint64_t SlotChromaLocVert : 2; /* 10..9 */ + uint64_t SlotBlkKind : 4; /* 14..11 */ + uint64_t SlotBlkHeight : 4; /* 18..15 */ + uint64_t SlotCacheWidth : 3; /* 21..19 */ + uint64_t reserved0 : 10; /* 31..22 */ + uint64_t SlotSurfaceWidth : 14; /* 45..32 */ + uint64_t SlotSurfaceHeight : 14; /* 59..46 */ + uint64_t reserved1 : 4; /* 63..60 */ + uint64_t SlotLumaWidth : 14; /* 77..64 */ + uint64_t SlotLumaHeight : 14; /* 91..78 */ + uint64_t reserved2 : 4; /* 95..92 */ + uint64_t SlotChromaWidth : 14; /* 109..96 */ + uint64_t SlotChromaHeight : 14; /* 123..110 */ + uint64_t reserved3 : 4; /* 127..124 */ +} SlotSurfaceConfig; + +typedef struct { + uint64_t luma_coeff0 : 20; /* 19..0 */ + uint64_t luma_coeff1 : 20; /* 39..20 */ + uint64_t luma_coeff2 : 20; /* 59..40 */ + uint64_t luma_r_shift : 4; /* 63..60 */ + uint64_t luma_coeff3 : 20; /* 83..64 */ + uint64_t LumaKeyLower : 10; /* 93..84 */ + uint64_t LumaKeyUpper : 10; /* 103..94 */ + uint64_t LumaKeyEnabled : 1; /* 104 */ + uint64_t reserved0 : 2; /* 106..105 */ + uint64_t reserved1 : 21; /* 127..107 */ +} LumaKeyStruct; + +typedef struct { + uint64_t matrix_coeff00 : 20; /* 19..0 */ + uint64_t matrix_coeff10 : 20; /* 39..20 */ + uint64_t matrix_coeff20 : 20; /* 59..40 */ + uint64_t matrix_r_shift : 4; /* 63..60 */ + uint64_t matrix_coeff01 : 20; /* 83..64 */ + uint64_t matrix_coeff11 : 20; /* 103..84 */ + uint64_t matrix_coeff21 : 20; /* 123..104 */ + uint64_t reserved0 : 3; /* 126..124 */ + uint64_t matrix_enable : 1; /* 127 */ + /* 128 */ + uint64_t matrix_coeff02 : 20; /* 19..0 */ + uint64_t matrix_coeff12 : 20; /* 39..20 */ + uint64_t matrix_coeff22 : 20; /* 59..40 */ + uint64_t reserved1 : 4; /* 63..60 */ + uint64_t matrix_coeff03 : 20; /* 83..64 */ + uint64_t matrix_coeff13 : 20; /* 103..84 */ + uint64_t matrix_coeff23 : 20; /* 123..104 */ + uint64_t reserved2 : 4; /* 127..124 */ +} MatrixStruct; + +typedef struct { + uint64_t ClearRect0Left : 14; /* 13..0 */ + uint64_t reserved0 : 2; /* 15..14 */ + uint64_t ClearRect0Right : 14; /* 29..16 */ + uint64_t reserved1 : 2; /* 31..30 */ + uint64_t ClearRect0Top : 14; /* 45..32 */ + uint64_t reserved2 : 2; /* 47..46 */ + uint64_t ClearRect0Bottom : 14; /* 61..48 */ + uint64_t reserved3 : 2; /* 63..62 */ + uint64_t ClearRect1Left : 14; /* 77..64 */ + uint64_t reserved4 : 2; /* 79..78 */ + uint64_t ClearRect1Right : 14; /* 93..80 */ + uint64_t reserved5 : 2; /* 95..94 */ + uint64_t ClearRect1Top : 14; /* 109..96 */ + uint64_t reserved6 : 2; /* 111..110 */ + uint64_t ClearRect1Bottom : 14; /* 125..112 */ + uint64_t reserved7 : 2; /* 127..126 */ +} ClearRectStruct; + +typedef struct { + uint64_t reserved0 : 2; /* 1..0 */ + uint64_t AlphaK1 : 8; /* 9..2 */ + uint64_t reserved1 : 6; /* 17..10 */ + uint64_t AlphaK2 : 8; /* 25..18 */ + uint64_t reserved2 : 6; /* 31..26 */ + uint64_t SrcFactCMatchSelect : 3; /* 34..32 */ + uint64_t reserved3 : 1; /* 35 */ + uint64_t DstFactCMatchSelect : 3; /* 38..36 */ + uint64_t reserved4 : 1; /* 39 */ + uint64_t SrcFactAMatchSelect : 3; /* 42..40 */ + uint64_t reserved5 : 1; /* 43 */ + uint64_t DstFactAMatchSelect : 3; /* 46..44 */ + uint64_t reserved6 : 1; /* 47 */ + uint64_t reserved7 : 4; /* 51..48 */ + uint64_t reserved8 : 4; /* 55..52 */ + uint64_t reserved9 : 4; /* 59..56 */ + uint64_t reserved10 : 4; /* 63..60 */ + uint64_t reserved11 : 2; /* 65..64 */ + uint64_t OverrideR : 10; /* 75..66 */ + uint64_t OverrideG : 10; /* 85..76 */ + uint64_t OverrideB : 10; /* 95..86 */ + uint64_t reserved12 : 2; /* 97..96 */ + uint64_t OverrideA : 8; /* 105..98 */ + uint64_t reserved13 : 2; /* 107..106 */ + uint64_t UseOverrideR : 1; /* 108 */ + uint64_t UseOverrideG : 1; /* 109 */ + uint64_t UseOverrideB : 1; /* 110 */ + uint64_t UseOverrideA : 1; /* 111 */ + uint64_t MaskR : 1; /* 112 */ + uint64_t MaskG : 1; /* 113 */ + uint64_t MaskB : 1; /* 114 */ + uint64_t MaskA : 1; /* 115 */ + uint64_t reserved14 : 12; /* 127..116 */ +} BlendingSlotStruct; + +typedef struct { + uint64_t AlphaFillMode : 3; /* 2..0 */ + uint64_t AlphaFillSlot : 3; /* 5..3 */ + uint64_t reserved0 : 2; /* 6..5 */ + uint64_t BackgroundAlpha : 8; /* 15..7 */ + uint64_t BackgroundR : 10; /* 25..16 */ + uint64_t BackgroundG : 10; /* 35..26 */ + uint64_t BackgroundB : 10; /* 45..36 */ + uint64_t RegammaMode : 2; /* 47..46 */ + uint64_t OutputFlipX : 1; /* 48 */ + uint64_t OutputFlipY : 1; /* 49 */ + uint64_t OutputTranspose : 1; /* 50 */ + uint64_t reserved1 : 1; /* 51 */ + uint64_t reserved2 : 12; /* 63..52 */ + uint64_t TargetRectLeft : 14; /* 77..64 */ + uint64_t reserved3 : 2; /* 79..78 */ + uint64_t TargetRectRight : 14; /* 93..80 */ + uint64_t reserved4 : 2; /* 95..94 */ + uint64_t TargetRectTop : 14; /* 109..96 */ + uint64_t reserved5 : 2; /* 111..110 */ + uint64_t TargetRectBottom : 14; /* 125..112 */ + uint64_t reserved6 : 2; /* 127..126 */ +} OutputConfig; + +typedef struct { + uint64_t OutPixelFormat : 7; /* 6..0 */ + uint64_t OutChromaLocHoriz : 2; /* 8..7 */ + uint64_t OutChromaLocVert : 2; /* 10..9 */ + uint64_t OutBlkKind : 4; /* 14..11 */ + uint64_t OutBlkHeight : 4; /* 18..15 */ + uint64_t reserved0 : 3; /* 21..19 */ + uint64_t reserved1 : 10; /* 31..22 */ + uint64_t OutSurfaceWidth : 14; /* 45..32 */ + uint64_t OutSurfaceHeight : 14; /* 59..46 */ + uint64_t reserved2 : 4; /* 63..60 */ + uint64_t OutLumaWidth : 14; /* 77..64 */ + uint64_t OutLumaHeight : 14; /* 91..78 */ + uint64_t reserved3 : 4; /* 95..92 */ + uint64_t OutChromaWidth : 14; /* 109..96 */ + uint64_t OutChromaHeight : 14; /* 123..110 */ + uint64_t reserved4 : 4; /* 127..124 */ +} OutputSurfaceConfig; + +typedef struct { + uint64_t f00 : 10; /* 9..0 */ + uint64_t f10 : 10; /* 19..10 */ + uint64_t f20 : 10; /* 29..20 */ + uint64_t reserved0 : 2; /* 31..30 */ + uint64_t f01 : 10; /* 41..32 */ + uint64_t f11 : 10; /* 51..42 */ + uint64_t f21 : 10; /* 61..52 */ + uint64_t reserved1 : 2; /* 63..62 */ + uint64_t f02 : 10; /* 73..64 */ + uint64_t f12 : 10; /* 83..74 */ + uint64_t f22 : 10; /* 93..84 */ + uint64_t reserved2 : 2; /* 95..94 */ + uint64_t f03 : 10; /* 105..96 */ + uint64_t f13 : 10; /* 115..106 */ + uint64_t f23 : 10; /* 125..116 */ + uint64_t reserved3 : 2; /* 127..126 */ +} FilterCoeffStruct; + +typedef struct { + uint64_t DownsampleHoriz : 11; /* 10..0 */ + uint64_t reserved0 : 5; /* 15..11 */ + uint64_t DownsampleVert : 11; /* 26..16 */ + uint64_t reserved1 : 5; /* 31..27 */ + uint64_t reserved2 : 32; /* 63..32 */ + uint64_t reserved3 : 32; /* 95..64 */ + uint64_t reserved4 : 32; /* 127..96 */ +} PipeConfig; + +typedef struct { + uint64_t OldCadence : 32; /* 31..0 */ + uint64_t OldDiff : 32; /* 63..32 */ + uint64_t OldWeave : 32; /* 95..64 */ + uint64_t OlderWeave : 32; /* 127..96 */ +} SlotHistoryBuffer; + +typedef struct { + uint64_t crc0 : 32; /* 31..0 */ + uint64_t crc1 : 32; /* 63..32 */ + uint64_t crc2 : 32; /* 95..64 */ + uint64_t crc3 : 32; /* 127..96 */ +} PartitionCrcStruct; + +typedef struct { + uint64_t crc0 : 32; /* 31..0 */ + uint64_t crc1 : 32; /* 63..32 */ +} SlotCrcStruct; + +typedef struct { + uint64_t ErrorStatus : 32; /* 31..0 */ + uint64_t CycleCount : 32; /* 63..32 */ + uint64_t reserved0 : 32; /* 95..64 */ + uint64_t reserved1 : 32; /* 127..96 */ +} StatusStruct; + +typedef struct { + SlotConfig slotConfig; + SlotSurfaceConfig slotSurfaceConfig; + LumaKeyStruct lumaKeyStruct; + MatrixStruct colorMatrixStruct; + MatrixStruct gamutMatrixStruct; + BlendingSlotStruct blendingSlotStruct; +} SlotStruct; + +typedef struct { + FilterCoeffStruct filterCoeffStruct[520]; +} FilterStruct; + +typedef struct { + PipeConfig pipeConfig; + OutputConfig outputConfig; + OutputSurfaceConfig outputSurfaceConfig; + MatrixStruct outColorMatrixStruct; + ClearRectStruct clearRectStruct[4]; + SlotStruct slotStruct[16]; +} ConfigStruct; + +typedef struct { + PartitionCrcStruct partitionCrcStruct[4]; +} InterfaceCrcStruct; + +typedef struct { + SlotCrcStruct slotCrcStruct[16]; +} InputCrcStruct; + +#endif diff --git a/lib/libdrm/tests/tegra/vic42.c b/lib/libdrm/tests/tegra/vic42.c new file mode 100644 index 000000000..068b712a8 --- /dev/null +++ b/lib/libdrm/tests/tegra/vic42.c @@ -0,0 +1,342 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <errno.h> +#include <string.h> + +#include "private.h" +#include "tegra.h" +#include "vic.h" +#include "vic42.h" + +struct vic42 { + struct vic base; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } config; + + struct { + struct drm_tegra_mapping *map; + struct drm_tegra_bo *bo; + } filter; +}; + +static int vic42_fill(struct vic *v, struct vic_image *output, + unsigned int left, unsigned int top, + unsigned int right, unsigned int bottom, + unsigned int alpha, unsigned int red, + unsigned int green, unsigned int blue) +{ + struct vic42 *vic = container_of(v, struct vic42, base); + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = top; + c->outputConfig.TargetRectLeft = left; + c->outputConfig.TargetRectRight = right; + c->outputConfig.TargetRectBottom = bottom; + c->outputConfig.BackgroundAlpha = alpha; + c->outputConfig.BackgroundR = red; + c->outputConfig.BackgroundG = green; + c->outputConfig.BackgroundB = blue; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic42_blit(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic42 *vic = container_of(v, struct vic42, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 255; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 255; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic42_flip(struct vic *v, struct vic_image *output, + struct vic_image *input) +{ + struct vic42 *vic = container_of(v, struct vic42, base); + SlotSurfaceConfig *surface; + SlotConfig *slot; + ConfigStruct *c; + int err; + + err = drm_tegra_bo_map(vic->config.bo, (void **)&c); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + memset(c, 0, sizeof(*c)); + + c->outputConfig.TargetRectTop = 0; + c->outputConfig.TargetRectLeft = 0; + c->outputConfig.TargetRectRight = output->width - 1; + c->outputConfig.TargetRectBottom = output->height - 1; + c->outputConfig.BackgroundAlpha = 255; + c->outputConfig.BackgroundR = 1023; + c->outputConfig.BackgroundG = 1023; + c->outputConfig.BackgroundB = 1023; + c->outputConfig.OutputFlipY = 1; + + c->outputSurfaceConfig.OutPixelFormat = output->format; + c->outputSurfaceConfig.OutBlkKind = output->kind; + c->outputSurfaceConfig.OutBlkHeight = 0; + c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1; + c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1; + c->outputSurfaceConfig.OutLumaWidth = output->stride - 1; + c->outputSurfaceConfig.OutLumaHeight = output->height - 1; + c->outputSurfaceConfig.OutChromaWidth = 16383; + c->outputSurfaceConfig.OutChromaHeight = 16383; + + slot = &c->slotStruct[0].slotConfig; + slot->SlotEnable = 1; + slot->CurrentFieldEnable = 1; + slot->PlanarAlpha = 255; + slot->ConstantAlpha = 1; + slot->SourceRectLeft = 0 << 16; + slot->SourceRectRight = (input->width - 1) << 16; + slot->SourceRectTop = 0 << 16; + slot->SourceRectBottom = (input->height - 1) << 16; + slot->DestRectLeft = 0; + slot->DestRectRight = output->width - 1; + slot->DestRectTop = 0; + slot->DestRectBottom = output->height - 1; + slot->SoftClampHigh = 1023; + + surface = &c->slotStruct[0].slotSurfaceConfig; + surface->SlotPixelFormat = input->format; + surface->SlotBlkKind = input->kind; + surface->SlotBlkHeight = 0; /* XXX */ + surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */ + surface->SlotSurfaceWidth = input->width - 1; + surface->SlotSurfaceHeight = input->height - 1; + surface->SlotLumaWidth = input->stride - 1; + surface->SlotLumaHeight = input->height - 1; + surface->SlotChromaWidth = 16383; + surface->SlotChromaHeight = 16383; + + drm_tegra_bo_unmap(vic->config.bo); + + return 0; +} + +static int vic42_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf, + uint32_t **ptrp, struct vic_image *output, + struct vic_image **inputs, unsigned int num_inputs) +{ + struct vic42 *vic = container_of(v, struct vic42, base); + unsigned int i; + + if (num_inputs > 1) + return -EINVAL; + + VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1); + VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET, vic->filter.map, 0, 0); + VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0); + + for (i = 0; i < num_inputs; i++) { + uint32_t method = NVC5B6_VIDEO_COMPOSITOR_SET_SURFACE0_LUMA_OFFSET(0) + (i * 3) * 4; + + VIC_PUSH_BUFFER(pushbuf, ptrp, method, inputs[i]->map, 0, 0); + } + + VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8); + + return 0; +} + +static void vic42_free(struct vic *v) +{ + struct vic42 *vic = container_of(v, struct vic42, base); + + drm_tegra_channel_unmap(vic->filter.map); + drm_tegra_bo_unref(vic->filter.bo); + + drm_tegra_channel_unmap(vic->config.map); + drm_tegra_bo_unref(vic->config.bo); + + drm_tegra_syncpoint_free(v->syncpt); + + free(vic); +} + +static const struct vic_ops vic42_ops = { + .fill = vic42_fill, + .blit = vic42_blit, + .flip = vic42_flip, + .execute = vic42_execute, + .free = vic42_free, +}; + +int vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, + struct vic **vicp) +{ + struct vic42 *vic; + void *ptr; + int err; + + vic = calloc(1, sizeof(*vic)); + if (!vic) + return -ENOMEM; + + vic->base.drm = drm; + vic->base.channel = channel; + vic->base.ops = &vic42_ops; + vic->base.version = 0x19; + + err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt); + if (err < 0) { + fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate configuration structurer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->config.map); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo); + if (err < 0) { + fprintf(stderr, "failed to allocate filter buffer: %s\n", + strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(vic->filter.bo, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 16384); + drm_tegra_bo_unmap(vic->filter.bo); + + err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ, + &vic->filter.map); + if (err < 0) { + fprintf(stderr, "failed to map filter buffer: %s\n", + strerror(-err)); + return err; + } + + if (vicp) + *vicp = &vic->base; + + return 0; +} diff --git a/lib/libdrm/tests/tegra/vic42.h b/lib/libdrm/tests/tegra/vic42.h new file mode 100644 index 000000000..3ed5cdbd3 --- /dev/null +++ b/lib/libdrm/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 |