drm/tegra: Add SET/GET_TILING IOCTLs
authorThierry Reding <treding@nvidia.com>
Tue, 3 Jun 2014 12:56:57 +0000 (14:56 +0200)
committerThierry Reding <treding@nvidia.com>
Mon, 4 Aug 2014 08:07:34 +0000 (10:07 +0200)
Currently the tiling parameters of buffer objects can only be set at
allocation time, and only a single tiled mode is supported. This new
DRM_TEGRA_GEM_SET_TILING IOCTL allows more modes to be set and also
allows the tiling mode to be changed after the allocation. This will
enable the Tegra DRM driver to import buffers from a GPU and directly
scan them out by configuring the display controller appropriately.

To complement this, the DRM_TEGRA_GEM_GET_TILING IOCTL can query the
current tiling mode of a buffer object. This is necessary when importing
buffers via handle (as is done in Mesa for example) so that userspace
can determine the proper parameters for the 2D or 3D engines.

Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Tested-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/drm.c
include/uapi/drm/tegra_drm.h

index fd736efd14bd963cd38571ae7de02fb54c785ce8..a029525b598f2a5e8c09155985ec12d93c7f70a5 100644 (file)
@@ -455,6 +455,99 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
 
        return 0;
 }
+
+static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
+                               struct drm_file *file)
+{
+       struct drm_tegra_gem_set_tiling *args = data;
+       enum tegra_bo_tiling_mode mode;
+       struct drm_gem_object *gem;
+       unsigned long value = 0;
+       struct tegra_bo *bo;
+
+       switch (args->mode) {
+       case DRM_TEGRA_GEM_TILING_MODE_PITCH:
+               mode = TEGRA_BO_TILING_MODE_PITCH;
+
+               if (args->value != 0)
+                       return -EINVAL;
+
+               break;
+
+       case DRM_TEGRA_GEM_TILING_MODE_TILED:
+               mode = TEGRA_BO_TILING_MODE_TILED;
+
+               if (args->value != 0)
+                       return -EINVAL;
+
+               break;
+
+       case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
+               mode = TEGRA_BO_TILING_MODE_BLOCK;
+
+               if (args->value > 5)
+                       return -EINVAL;
+
+               value = args->value;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       gem = drm_gem_object_lookup(drm, file, args->handle);
+       if (!gem)
+               return -ENOENT;
+
+       bo = to_tegra_bo(gem);
+
+       bo->tiling.mode = mode;
+       bo->tiling.value = value;
+
+       drm_gem_object_unreference(gem);
+
+       return 0;
+}
+
+static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
+                               struct drm_file *file)
+{
+       struct drm_tegra_gem_get_tiling *args = data;
+       struct drm_gem_object *gem;
+       struct tegra_bo *bo;
+       int err = 0;
+
+       gem = drm_gem_object_lookup(drm, file, args->handle);
+       if (!gem)
+               return -ENOENT;
+
+       bo = to_tegra_bo(gem);
+
+       switch (bo->tiling.mode) {
+       case TEGRA_BO_TILING_MODE_PITCH:
+               args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
+               args->value = 0;
+               break;
+
+       case TEGRA_BO_TILING_MODE_TILED:
+               args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
+               args->value = 0;
+               break;
+
+       case TEGRA_BO_TILING_MODE_BLOCK:
+               args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+               args->value = bo->tiling.value;
+               break;
+
+       default:
+               err = -EINVAL;
+               break;
+       }
+
+       drm_gem_object_unreference(gem);
+
+       return err;
+}
 #endif
 
 static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
@@ -469,6 +562,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
        DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
        DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
        DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
 #endif
 };
 
index b75482112428afa8eaab6cd266f3221d8decab28..0829f75eb9869f28bd23832c2bf1f8c03782e150 100644 (file)
@@ -129,6 +129,27 @@ struct drm_tegra_submit {
        __u32 reserved[5];      /* future expansion */
 };
 
+#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
+#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
+#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
+
+struct drm_tegra_gem_set_tiling {
+       /* input */
+       __u32 handle;
+       __u32 mode;
+       __u32 value;
+       __u32 pad;
+};
+
+struct drm_tegra_gem_get_tiling {
+       /* input */
+       __u32 handle;
+       /* output */
+       __u32 mode;
+       __u32 value;
+       __u32 pad;
+};
+
 #define DRM_TEGRA_GEM_CREATE           0x00
 #define DRM_TEGRA_GEM_MMAP             0x01
 #define DRM_TEGRA_SYNCPT_READ          0x02
@@ -139,6 +160,8 @@ struct drm_tegra_submit {
 #define DRM_TEGRA_GET_SYNCPT           0x07
 #define DRM_TEGRA_SUBMIT               0x08
 #define DRM_TEGRA_GET_SYNCPT_BASE      0x09
+#define DRM_TEGRA_GEM_SET_TILING       0x0a
+#define DRM_TEGRA_GEM_GET_TILING       0x0b
 
 #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_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
@@ -150,5 +173,7 @@ struct drm_tegra_submit {
 #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
 #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
 #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
+#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
+#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
 
 #endif