From patchwork Tue Dec 4 15:13:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1838601 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 6EC603FCA5 for ; Tue, 4 Dec 2012 15:15:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3AB83E6381 for ; Tue, 4 Dec 2012 07:15:58 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.171]) by gabe.freedesktop.org (Postfix) with ESMTP id 62210E6397 for ; Tue, 4 Dec 2012 07:14:01 -0800 (PST) Received: from mailbox.adnet.avionic-design.de (mailbox.avionic-design.de [109.75.18.3]) by mrelayeu.kundenserver.de (node=mrbap1) with ESMTP (Nemesis) id 0MeMN5-1TpaiQ3qqF-00Pp5S; Tue, 04 Dec 2012 16:13:58 +0100 Received: from localhost (localhost [127.0.0.1]) by mailbox.adnet.avionic-design.de (Postfix) with ESMTP id 305622A280EF; Tue, 4 Dec 2012 16:13:57 +0100 (CET) X-Virus-Scanned: amavisd-new at avionic-design.de Received: from mailbox.adnet.avionic-design.de ([127.0.0.1]) by localhost (mailbox.avionic-design.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id se5yowt+IGRn; Tue, 4 Dec 2012 16:13:55 +0100 (CET) Received: from localhost (avionic-0098.adnet.avionic-design.de [172.20.31.233]) (Authenticated sender: thierry.reding) by mailbox.adnet.avionic-design.de (Postfix) with ESMTPA id 418DE2A280FD; Tue, 4 Dec 2012 16:13:55 +0100 (CET) From: Thierry Reding To: dri-devel@lists.freedesktop.org Subject: =?UTF-8?q?=5BRFC=20libdrm=5D=20Add=20NVIDIA=20Tegra=20support?= Date: Tue, 4 Dec 2012 16:13:52 +0100 Message-Id: <1354634032-9986-2-git-send-email-thierry.reding@avionic-design.de> X-Mailer: git-send-email 1.8.0.1 In-Reply-To: <1354634032-9986-1-git-send-email-thierry.reding@avionic-design.de> References: <1354634032-9986-1-git-send-email-thierry.reding@avionic-design.de> MIME-Version: 1.0 X-Provags-ID: V02:K0:5CciZZH6+tsUpM8mTCXfzFh6YFagppuXxTjq4JLUukn W1dQuJYu7VmzGe4KfssigvIkESfF/ddfJQIvX+gkyrn2qPMQt+ wT8qQxAmN61sW4yQKwfAE71fjSSTA/oGY61C/PKQ1aT+fDgS55 6puX3yyYPETGcA4kZZb7SXUnIJqHHCA1kDXV5IETjgXXJ4YawU 5Wf0zmP96i7tS0NGS2VAnrfH22NTC5eIWaWX2Jw4LJmWTcNEo5 t+PvGuyVGJEYdzmhIM8HoLd+glfPaKR0mMvr8Ftxxliiyr1fFF ZV1jifFkQWVe9xn6rfU27YaD8YDu63Y1ZMy6AMrmVp3Lgy7AB/ zk0wRt9Lz+GZo4mKRgZPXSOxwJ4ZV1tzmdyoDClX+xOHwj5Rm2 Lf7hrNsU0K29tITxIg0Tcs2skrKpcHTiEQYP0LRJCZetbC5YJ6 Feukw Cc: linux-tegra@vger.kernel.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Add the libdrm_tegra helper library to encapsulate Tegra-specific interfaces to the DRM. Furthermore, Tegra is added to the list of supported chips in the modetest and vbltest programs. Signed-off-by: Thierry Reding --- Makefile.am | 6 +- configure.ac | 15 ++- include/drm/Makefile.am | 1 + include/drm/tegra_drm.h | 48 ++++++++++ tegra/Makefile.am | 17 ++++ tegra/libdrm_tegra.pc.in | 11 +++ tegra/tegra.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++ tegra/tegra.h | 51 +++++++++++ tests/modetest/modetest.c | 2 +- tests/vbltest/vbltest.c | 2 +- 10 files changed, 376 insertions(+), 4 deletions(-) create mode 100644 include/drm/tegra_drm.h create mode 100644 tegra/Makefile.am create mode 100644 tegra/libdrm_tegra.pc.in create mode 100644 tegra/tegra.c create mode 100644 tegra/tegra.h diff --git a/Makefile.am b/Makefile.am index 8ecd9d9..e90ae43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,11 @@ if HAVE_EXYNOS EXYNOS_SUBDIR = exynos endif -SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man +if HAVE_TEGRA +TEGRA_SUBDIR = tegra +endif + +SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(TEGRA_SUBDIR) tests include man libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) diff --git a/configure.ac b/configure.ac index 0c19929..72d6dfa 100644 --- a/configure.ac +++ b/configure.ac @@ -114,6 +114,11 @@ AC_ARG_ENABLE(exynos-experimental-api, [Enable support for EXYNOS's experimental API (default: disabled)]), [EXYNOS=$enableval], [EXYNOS=no]) +AC_ARG_ENABLE(tegra-experimental-api, + AS_HELP_STRING([--enable-tegra-experimental-api], + [Enable support for Tegra's experimental API (default: disabled)]), + [TEGRA=$enableval], [TEGRA=no]) + dnl =========================================================================== dnl check compiler flags AC_DEFUN([LIBDRM_CC_TRY_FLAG], [ @@ -222,6 +227,11 @@ if test "x$EXYNOS" = xyes; then AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support]) fi +AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes]) +if test "x$TEGRA" = xyes; then + AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support]) +fi + AC_ARG_ENABLE([cairo-tests], [AS_HELP_STRING([--enable-cairo-tests], [Enable support for Cairo rendering in tests (default: auto)])], @@ -247,7 +257,7 @@ if test "x$HAVE_LIBUDEV" = xyes; then fi AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes]) -if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno"; then +if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$TEGRA" != "xno"; then # Check for atomic intrinsics AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives, [ @@ -358,6 +368,8 @@ AC_CONFIG_FILES([ omap/libdrm_omap.pc exynos/Makefile exynos/libdrm_exynos.pc + tegra/Makefile + tegra/libdrm_tegra.pc tests/Makefile tests/modeprint/Makefile tests/modetest/Makefile @@ -380,4 +392,5 @@ echo " Radeon API $RADEON" echo " Nouveau API $NOUVEAU" echo " OMAP API $OMAP" echo " EXYNOS API $EXYNOS" +echo " Tegra API $TEGRA" echo "" diff --git a/include/drm/Makefile.am b/include/drm/Makefile.am index 2923ab4..3e33ed0 100644 --- a/include/drm/Makefile.am +++ b/include/drm/Makefile.am @@ -35,6 +35,7 @@ klibdrminclude_HEADERS = \ radeon_drm.h \ savage_drm.h \ sis_drm.h \ + tegra_drm.h \ via_drm.h \ mach64_drm.h diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h new file mode 100644 index 0000000..eaec602 --- /dev/null +++ b/include/drm/tegra_drm.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2012 Thierry Reding + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __TEGRA_DRM_H__ +#define __TEGRA_DRM_H__ + +struct drm_tegra_gem_create { + uint32_t handle; + uint32_t offset; + uint32_t flags; + uint32_t size; +}; + +struct drm_tegra_gem_info { + uint32_t handle; + uint32_t offset; + uint32_t flags; + uint32_t size; +}; + +#define DRM_TEGRA_GEM_CREATE 0x40 +#define DRM_TEGRA_GEM_INFO 0x41 + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) +#define DRM_IOCTL_TEGRA_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_INFO, struct drm_tegra_gem_info) + +#endif /* __TEGRA_DRM_H__ */ diff --git a/tegra/Makefile.am b/tegra/Makefile.am new file mode 100644 index 0000000..65cd628 --- /dev/null +++ b/tegra/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/include/drm + +libdrm_tegra_ladir = $(libdir) +libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la +libdrm_tegra_la_LDFLAGS = -version-number 0:0:0 -no-undefined +libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ + +libdrm_tegra_la_SOURCES = \ + tegra.c + +libdrm_tegraincludedir = ${includedir}/libdrm +libdrm_tegrainclude_HEADERS = tegra.h + +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libdrm_tegra.pc diff --git a/tegra/libdrm_tegra.pc.in b/tegra/libdrm_tegra.pc.in new file mode 100644 index 0000000..f83c74c --- /dev/null +++ b/tegra/libdrm_tegra.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm_tegra +Description: Userspace interface to Tegra kernel DRM services +Version: 2.4.40 +Libs: -L${libdir} -ldrm_tegra +Cflags: -I${includedir} -I${includedir}/libdrm +Requires.private: libdrm diff --git a/tegra/tegra.c b/tegra/tegra.c new file mode 100644 index 0000000..d92eca5 --- /dev/null +++ b/tegra/tegra.c @@ -0,0 +1,227 @@ +/* + * Copyright © 2012 Thierry Reding + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#include + +#include "tegra.h" + +struct drm_tegra { + drmMMListHead bo_list; + int fd; +}; +struct tegra_bo { + struct drm_tegra_bo base; + drmMMListHead list; + atomic_t ref; +}; + +static inline struct tegra_bo *tegra_bo(struct drm_tegra_bo *bo) +{ + return (struct tegra_bo *)bo; +} + +static void drm_tegra_bo_free(struct drm_tegra_bo *bo) +{ + struct tegra_bo *priv = tegra_bo(bo); + struct drm_gem_close args; + + DRMLISTDEL(&priv->list); + + if (bo->map) + munmap(bo->map, bo->size); + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + + drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &args); + + free(bo); +} + +int drm_tegra_open(const char *path, struct drm_tegra **devicep) +{ + struct drm_tegra *device; + int err; + + if (!path || !devicep) + return -EINVAL; + + device = calloc(1, sizeof(*device)); + if (!device) + return -ENOMEM; + + DRMINITLISTHEAD(&device->bo_list); + + device->fd = open(path, O_RDWR); + if (device->fd < 0) { + err = -errno; + free(device); + return err; + } + + *devicep = device; + + return 0; +} + +void drm_tegra_close(struct drm_tegra *device) +{ + if (device) { + close(device->fd); + free(device); + } +} + +int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size, + struct drm_tegra_bo **bop) +{ + struct drm_tegra_gem_create args; + struct drm_tegra_bo *bo; + struct tegra_bo *priv; + int err; + + if (!device || size == 0 || !bop) + return -EINVAL; + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + priv = tegra_bo(bo); + + DRMLISTINITHEAD(&priv->list); + atomic_set(&priv->ref, 1); + bo->device = device; + bo->flags = flags; + bo->size = size; + + memset(&args, 0, sizeof(args)); + args.flags = flags; + args.size = size; + + err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_CREATE, &args, + sizeof(args)); + if (err < 0) { + err = -errno; + free(bo); + return err; + } + + DRMLISTADD(&priv->list, &device->bo_list); + bo->handle = args.handle; + bo->offset = args.offset; + + *bop = bo; + + return 0; +} + +int drm_tegra_bo_open(struct drm_tegra *device, uint32_t handle, + struct drm_tegra_bo **bop) +{ + struct drm_tegra_gem_info args; + struct drm_tegra_bo *bo; + struct tegra_bo *priv; + int err; + + if (!device || !bop) + return -EINVAL; + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + priv = tegra_bo(bo); + + DRMLISTINITHEAD(&priv->list); + atomic_set(&priv->ref, 1); + bo->device = device; + + memset(&args, 0, sizeof(args)); + args.handle = handle; + + err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_INFO, &args, + sizeof(args)); + if (err < 0) { + err = -errno; + free(bo); + return err; + } + + DRMLISTADD(&priv->list, &device->bo_list); + bo->handle = args.handle; + bo->offset = args.offset; + bo->flags = args.flags; + bo->size = args.size; + + *bop = bo; + + return 0; +} + +struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo) +{ + if (bo) { + struct tegra_bo *priv = tegra_bo(bo); + atomic_inc(&priv->ref); + } + + return bo; +} + +void drm_tegra_bo_put(struct drm_tegra_bo *bo) +{ + if (bo) { + struct tegra_bo *priv = tegra_bo(bo); + + if (atomic_dec_and_test(&priv->ref)) + drm_tegra_bo_free(bo); + } +} + +int drm_tegra_bo_map(struct drm_tegra_bo *bo) +{ + if (!bo->map) { + bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, + MAP_SHARED, bo->device->fd, bo->offset); + if (bo->map == MAP_FAILED) { + bo->map = NULL; + return -errno; + } + } + + return 0; +} diff --git a/tegra/tegra.h b/tegra/tegra.h new file mode 100644 index 0000000..619090c --- /dev/null +++ b/tegra/tegra.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2012 Thierry Reding + * + * 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 __DRM_TEGRA_H__ +#define __DRM_TEGRA_H__ 1 + +#include +#include + +struct drm_tegra; + +struct drm_tegra_bo { + struct drm_tegra *device; + uint32_t handle; + uint32_t offset; + uint32_t flags; + uint32_t size; + void *map; +}; + +int drm_tegra_open(const char *path, struct drm_tegra **devicep); +void drm_tegra_close(struct drm_tegra *device); + +int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size, + struct drm_tegra_bo **bop); +int drm_tegra_bo_open(struct drm_tegra *device, uint32_t handle, + struct drm_tegra_bo **bop); +int drm_tegra_bo_map(struct drm_tegra_bo *bo); +struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo); +void drm_tegra_bo_put(struct drm_tegra_bo *bo); + +#endif /* __DRM_TEGRA_H__ */ diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index c91bb9d..913ede8 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -939,7 +939,7 @@ int main(int argc, char **argv) int c; int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0; int test_vsync = 0; - char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tegra" }; unsigned int i; int count = 0, plane_count = 0; struct connector con_args[2]; diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 4fccd59..22a5339 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -103,7 +103,7 @@ static void usage(char *name) int main(int argc, char **argv) { int i, c, fd, ret; - char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "tegra" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info;