diff options
author | Eric Anholt <eric@anholt.net> | 2017-06-07 17:13:36 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2017-06-15 16:02:45 -0700 |
commit | 83753117f1de4f6ef7588fac9545065eed1e85e2 (patch) | |
tree | 1471f2539093b056b46311390fc8555869913352 /drivers/gpu | |
parent | 98830d91da082b0285d35bdf5b5ae98decac7df6 (diff) | |
download | op-kernel-dev-83753117f1de4f6ef7588fac9545065eed1e85e2.zip op-kernel-dev-83753117f1de4f6ef7588fac9545065eed1e85e2.tar.gz |
drm/vc4: Add get/set tiling ioctls.
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_bo.c | 83 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_kms.c | 41 |
4 files changed, 131 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 590c091..487f964 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -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); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 136bb42..c6b487c 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -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 = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index a5bf2e5..df22698 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -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); diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 928d191..202f7eb 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -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) |