drm/vc4: Add get/set tiling ioctls.
authorEric Anholt <eric@anholt.net>
Thu, 8 Jun 2017 00:13:36 +0000 (17:13 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 15 Jun 2017 23:02:45 +0000 (16:02 -0700)
This allows mesa to set the tiling format for a BO and have that
tiling format be respected by mesa on the other side of an
import/export (and by vc4 scanout in the kernel), without defining a
protocol to pass the tiling through userspace.

Signed-off-by: Eric Anholt <eric@anholt.net>
Link: http://patchwork.freedesktop.org/patch/msgid/20170608001336.12842-2-eric@anholt.net
Acked-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_kms.c
include/uapi/drm/vc4_drm.h

index 590c0912afc153b42be4f06e55d2c0bd3961ffcd..487f96412d35999a03713dc9e59a4106b740bb6c 100644 (file)
@@ -343,6 +343,7 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
                bo->validated_shader = NULL;
        }
 
+       bo->t_format = false;
        bo->free_time = jiffies;
        list_add(&bo->size_head, cache_list);
        list_add(&bo->unref_head, &vc4->bo_cache.time_list);
@@ -568,6 +569,88 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
        return ret;
 }
 
+/**
+ * vc4_set_tiling_ioctl() - Sets the tiling modifier for a BO.
+ * @dev: DRM device
+ * @data: ioctl argument
+ * @file_priv: DRM file for this fd
+ *
+ * The tiling state of the BO decides the default modifier of an fb if
+ * no specific modifier was set by userspace, and the return value of
+ * vc4_get_tiling_ioctl() (so that userspace can treat a BO it
+ * received from dmabuf as the same tiling format as the producer
+ * used).
+ */
+int vc4_set_tiling_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_vc4_set_tiling *args = data;
+       struct drm_gem_object *gem_obj;
+       struct vc4_bo *bo;
+       bool t_format;
+
+       if (args->flags != 0)
+               return -EINVAL;
+
+       switch (args->modifier) {
+       case DRM_FORMAT_MOD_NONE:
+               t_format = false;
+               break;
+       case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               t_format = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+       if (!gem_obj) {
+               DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+               return -ENOENT;
+       }
+       bo = to_vc4_bo(gem_obj);
+       bo->t_format = t_format;
+
+       drm_gem_object_unreference_unlocked(gem_obj);
+
+       return 0;
+}
+
+/**
+ * vc4_get_tiling_ioctl() - Gets the tiling modifier for a BO.
+ * @dev: DRM device
+ * @data: ioctl argument
+ * @file_priv: DRM file for this fd
+ *
+ * Returns the tiling modifier for a BO as set by vc4_set_tiling_ioctl().
+ */
+int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_vc4_get_tiling *args = data;
+       struct drm_gem_object *gem_obj;
+       struct vc4_bo *bo;
+
+       if (args->flags != 0 || args->modifier != 0)
+               return -EINVAL;
+
+       gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+       if (!gem_obj) {
+               DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+               return -ENOENT;
+       }
+       bo = to_vc4_bo(gem_obj);
+
+       if (bo->t_format)
+               args->modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED;
+       else
+               args->modifier = DRM_FORMAT_MOD_NONE;
+
+       drm_gem_object_unreference_unlocked(gem_obj);
+
+       return 0;
+}
+
 void vc4_bo_cache_init(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
index 136bb4213dc0ecf4575a968fbd16d3157218e382..c6b487c3d2b7645b0ae249f0ce40f4795c80bf1f 100644 (file)
@@ -138,6 +138,8 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
        DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
                          DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(VC4_GET_PARAM, vc4_get_param_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_SET_TILING, vc4_set_tiling_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_GET_TILING, vc4_get_tiling_ioctl, DRM_RENDER_ALLOW),
 };
 
 static struct drm_driver vc4_drm_driver = {
index a5bf2e5e0b57f117ffdfd72abb36c6c6a7815ee0..df22698d62ee5ca89f00bcd42b10a6862506a4cf 100644 (file)
@@ -148,6 +148,8 @@ struct vc4_bo {
         */
        uint64_t write_seqno;
 
+       bool t_format;
+
        /* List entry for the BO's position in either
         * vc4_exec_info->unref_list or vc4_dev->bo_cache.time_list
         */
@@ -470,6 +472,10 @@ int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file_priv);
 int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
                      struct drm_file *file_priv);
+int vc4_set_tiling_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
 int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv);
 int vc4_mmap(struct file *filp, struct vm_area_struct *vma);
index 928d191ef90f3af06e0cfacb8c25efbd5ddec845..202f7ebf5a7ba863436909df20f9f1d06a5f1ebf 100644 (file)
@@ -202,11 +202,50 @@ static int vc4_atomic_commit(struct drm_device *dev,
        return 0;
 }
 
+static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
+                                            struct drm_file *file_priv,
+                                            const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       struct drm_mode_fb_cmd2 mode_cmd_local;
+
+       /* If the user didn't specify a modifier, use the
+        * vc4_set_tiling_ioctl() state for the BO.
+        */
+       if (!(mode_cmd->flags & DRM_MODE_FB_MODIFIERS)) {
+               struct drm_gem_object *gem_obj;
+               struct vc4_bo *bo;
+
+               gem_obj = drm_gem_object_lookup(file_priv,
+                                               mode_cmd->handles[0]);
+               if (!gem_obj) {
+                       DRM_ERROR("Failed to look up GEM BO %d\n",
+                                 mode_cmd->handles[0]);
+                       return ERR_PTR(-ENOENT);
+               }
+               bo = to_vc4_bo(gem_obj);
+
+               mode_cmd_local = *mode_cmd;
+
+               if (bo->t_format) {
+                       mode_cmd_local.modifier[0] =
+                               DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED;
+               } else {
+                       mode_cmd_local.modifier[0] = DRM_FORMAT_MOD_NONE;
+               }
+
+               drm_gem_object_unreference_unlocked(gem_obj);
+
+               mode_cmd = &mode_cmd_local;
+       }
+
+       return drm_fb_cma_create(dev, file_priv, mode_cmd);
+}
+
 static const struct drm_mode_config_funcs vc4_mode_funcs = {
        .output_poll_changed = vc4_output_poll_changed,
        .atomic_check = drm_atomic_helper_check,
        .atomic_commit = vc4_atomic_commit,
-       .fb_create = drm_fb_cma_create,
+       .fb_create = vc4_fb_create,
 };
 
 int vc4_kms_load(struct drm_device *dev)
index f07a090167261131076438960c1dec175d7d376e..6ac4c5c014cb9b98343f25721f74b727a88f2bb5 100644 (file)
@@ -38,6 +38,8 @@ extern "C" {
 #define DRM_VC4_CREATE_SHADER_BO                  0x05
 #define DRM_VC4_GET_HANG_STATE                    0x06
 #define DRM_VC4_GET_PARAM                         0x07
+#define DRM_VC4_SET_TILING                        0x08
+#define DRM_VC4_GET_TILING                        0x09
 
 #define DRM_IOCTL_VC4_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
 #define DRM_IOCTL_VC4_WAIT_SEQNO          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
@@ -47,6 +49,8 @@ extern "C" {
 #define DRM_IOCTL_VC4_CREATE_SHADER_BO    DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo)
 #define DRM_IOCTL_VC4_GET_HANG_STATE      DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state)
 #define DRM_IOCTL_VC4_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param)
+#define DRM_IOCTL_VC4_SET_TILING          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling)
+#define DRM_IOCTL_VC4_GET_TILING          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
 
 struct drm_vc4_submit_rcl_surface {
        __u32 hindex; /* Handle index, or ~0 if not present. */
@@ -295,6 +299,18 @@ struct drm_vc4_get_param {
        __u64 value;
 };
 
+struct drm_vc4_get_tiling {
+       __u32 handle;
+       __u32 flags;
+       __u64 modifier;
+};
+
+struct drm_vc4_set_tiling {
+       __u32 handle;
+       __u32 flags;
+       __u64 modifier;
+};
+
 #if defined(__cplusplus)
 }
 #endif