mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
drm: Refactor setplane to allow internal use (v3)
Refactor DRM setplane code into a new setplane_internal() function that takes DRM objects directly as parameters rather than looking them up by ID. We'll use this in a future patch when we implement legacy cursor ioctls on top of the universal plane interface. v3: - Move integer overflow checking from setplane_internal to setplane ioctl. The upcoming legacy cursor support via universal planes needs to maintain current cursor ioctl semantics and not return error for these extreme values (found via intel-gpu-tools kms_cursor_crc test). v2: - Allow planes to be disabled without a valid crtc again (and add mention of this to setplane's kerneldoc, since it doesn't seem to be mentioned anywhere else). - Reformat some parameter line wrap Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Pallavi G<pallavi.g@intel.com> Acked-by: Dave Airlie <airlied@linux.ie> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
c394c2b08e
commit
b36552b32a
1 changed files with 102 additions and 74 deletions
|
@ -2122,45 +2122,32 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* drm_mode_setplane - configure a plane's configuration
|
* setplane_internal - setplane handler for internal callers
|
||||||
* @dev: DRM device
|
|
||||||
* @data: ioctl data*
|
|
||||||
* @file_priv: DRM file info
|
|
||||||
*
|
*
|
||||||
* Set plane configuration, including placement, fb, scaling, and other factors.
|
* Note that we assume an extra reference has already been taken on fb. If the
|
||||||
* Or pass a NULL fb to disable.
|
* update fails, this reference will be dropped before return; if it succeeds,
|
||||||
|
* the previous framebuffer (if any) will be unreferenced instead.
|
||||||
*
|
*
|
||||||
* Returns:
|
* src_{x,y,w,h} are provided in 16.16 fixed point format
|
||||||
* Zero on success, errno on failure.
|
|
||||||
*/
|
*/
|
||||||
int drm_mode_setplane(struct drm_device *dev, void *data,
|
static int setplane_internal(struct drm_crtc *crtc,
|
||||||
struct drm_file *file_priv)
|
struct drm_plane *plane,
|
||||||
|
struct drm_framebuffer *fb,
|
||||||
|
int32_t crtc_x, int32_t crtc_y,
|
||||||
|
uint32_t crtc_w, uint32_t crtc_h,
|
||||||
|
/* src_{x,y,w,h} values are 16.16 fixed point */
|
||||||
|
uint32_t src_x, uint32_t src_y,
|
||||||
|
uint32_t src_w, uint32_t src_h)
|
||||||
{
|
{
|
||||||
struct drm_mode_set_plane *plane_req = data;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct drm_plane *plane;
|
struct drm_framebuffer *old_fb = NULL;
|
||||||
struct drm_crtc *crtc;
|
|
||||||
struct drm_framebuffer *fb = NULL, *old_fb = NULL;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int fb_width, fb_height;
|
unsigned int fb_width, fb_height;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, find the plane, crtc, and fb objects. If not available,
|
|
||||||
* we don't bother to call the driver.
|
|
||||||
*/
|
|
||||||
plane = drm_plane_find(dev, plane_req->plane_id);
|
|
||||||
if (!plane) {
|
|
||||||
DRM_DEBUG_KMS("Unknown plane ID %d\n",
|
|
||||||
plane_req->plane_id);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No fb means shut it down */
|
/* No fb means shut it down */
|
||||||
if (!plane_req->fb_id) {
|
if (!fb) {
|
||||||
drm_modeset_lock_all(dev);
|
drm_modeset_lock_all(dev);
|
||||||
old_fb = plane->fb;
|
old_fb = plane->fb;
|
||||||
ret = plane->funcs->disable_plane(plane);
|
ret = plane->funcs->disable_plane(plane);
|
||||||
|
@ -2174,14 +2161,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
crtc = drm_crtc_find(dev, plane_req->crtc_id);
|
|
||||||
if (!crtc) {
|
|
||||||
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
|
|
||||||
plane_req->crtc_id);
|
|
||||||
ret = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether this plane is usable on this CRTC */
|
/* Check whether this plane is usable on this CRTC */
|
||||||
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
|
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
|
||||||
DRM_DEBUG_KMS("Invalid crtc for plane\n");
|
DRM_DEBUG_KMS("Invalid crtc for plane\n");
|
||||||
|
@ -2189,14 +2168,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
|
|
||||||
if (!fb) {
|
|
||||||
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
|
|
||||||
plane_req->fb_id);
|
|
||||||
ret = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether this plane supports the fb pixel format. */
|
/* Check whether this plane supports the fb pixel format. */
|
||||||
for (i = 0; i < plane->format_count; i++)
|
for (i = 0; i < plane->format_count; i++)
|
||||||
if (fb->pixel_format == plane->format_types[i])
|
if (fb->pixel_format == plane->format_types[i])
|
||||||
|
@ -2212,43 +2183,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||||
fb_height = fb->height << 16;
|
fb_height = fb->height << 16;
|
||||||
|
|
||||||
/* Make sure source coordinates are inside the fb. */
|
/* Make sure source coordinates are inside the fb. */
|
||||||
if (plane_req->src_w > fb_width ||
|
if (src_w > fb_width ||
|
||||||
plane_req->src_x > fb_width - plane_req->src_w ||
|
src_x > fb_width - src_w ||
|
||||||
plane_req->src_h > fb_height ||
|
src_h > fb_height ||
|
||||||
plane_req->src_y > fb_height - plane_req->src_h) {
|
src_y > fb_height - src_h) {
|
||||||
DRM_DEBUG_KMS("Invalid source coordinates "
|
DRM_DEBUG_KMS("Invalid source coordinates "
|
||||||
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
|
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
|
||||||
plane_req->src_w >> 16,
|
src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
|
||||||
((plane_req->src_w & 0xffff) * 15625) >> 10,
|
src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
|
||||||
plane_req->src_h >> 16,
|
src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
|
||||||
((plane_req->src_h & 0xffff) * 15625) >> 10,
|
src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
|
||||||
plane_req->src_x >> 16,
|
|
||||||
((plane_req->src_x & 0xffff) * 15625) >> 10,
|
|
||||||
plane_req->src_y >> 16,
|
|
||||||
((plane_req->src_y & 0xffff) * 15625) >> 10);
|
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give drivers some help against integer overflows */
|
|
||||||
if (plane_req->crtc_w > INT_MAX ||
|
|
||||||
plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
|
|
||||||
plane_req->crtc_h > INT_MAX ||
|
|
||||||
plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
|
|
||||||
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
|
|
||||||
plane_req->crtc_w, plane_req->crtc_h,
|
|
||||||
plane_req->crtc_x, plane_req->crtc_y);
|
|
||||||
ret = -ERANGE;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
drm_modeset_lock_all(dev);
|
drm_modeset_lock_all(dev);
|
||||||
old_fb = plane->fb;
|
old_fb = plane->fb;
|
||||||
ret = plane->funcs->update_plane(plane, crtc, fb,
|
ret = plane->funcs->update_plane(plane, crtc, fb,
|
||||||
plane_req->crtc_x, plane_req->crtc_y,
|
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||||
plane_req->crtc_w, plane_req->crtc_h,
|
src_x, src_y, src_w, src_h);
|
||||||
plane_req->src_x, plane_req->src_y,
|
|
||||||
plane_req->src_w, plane_req->src_h);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
plane->crtc = crtc;
|
plane->crtc = crtc;
|
||||||
plane->fb = fb;
|
plane->fb = fb;
|
||||||
|
@ -2265,6 +2218,81 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||||
drm_framebuffer_unreference(old_fb);
|
drm_framebuffer_unreference(old_fb);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_mode_setplane - configure a plane's configuration
|
||||||
|
* @dev: DRM device
|
||||||
|
* @data: ioctl data*
|
||||||
|
* @file_priv: DRM file info
|
||||||
|
*
|
||||||
|
* Set plane configuration, including placement, fb, scaling, and other factors.
|
||||||
|
* Or pass a NULL fb to disable (planes may be disabled without providing a
|
||||||
|
* valid crtc).
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Zero on success, errno on failure.
|
||||||
|
*/
|
||||||
|
int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv)
|
||||||
|
{
|
||||||
|
struct drm_mode_set_plane *plane_req = data;
|
||||||
|
struct drm_mode_object *obj;
|
||||||
|
struct drm_plane *plane;
|
||||||
|
struct drm_crtc *crtc = NULL;
|
||||||
|
struct drm_framebuffer *fb = NULL;
|
||||||
|
|
||||||
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Give drivers some help against integer overflows */
|
||||||
|
if (plane_req->crtc_w > INT_MAX ||
|
||||||
|
plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
|
||||||
|
plane_req->crtc_h > INT_MAX ||
|
||||||
|
plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
|
||||||
|
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
|
||||||
|
plane_req->crtc_w, plane_req->crtc_h,
|
||||||
|
plane_req->crtc_x, plane_req->crtc_y);
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, find the plane, crtc, and fb objects. If not available,
|
||||||
|
* we don't bother to call the driver.
|
||||||
|
*/
|
||||||
|
obj = drm_mode_object_find(dev, plane_req->plane_id,
|
||||||
|
DRM_MODE_OBJECT_PLANE);
|
||||||
|
if (!obj) {
|
||||||
|
DRM_DEBUG_KMS("Unknown plane ID %d\n",
|
||||||
|
plane_req->plane_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
plane = obj_to_plane(obj);
|
||||||
|
|
||||||
|
if (plane_req->fb_id) {
|
||||||
|
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
|
||||||
|
if (!fb) {
|
||||||
|
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
|
||||||
|
plane_req->fb_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = drm_mode_object_find(dev, plane_req->crtc_id,
|
||||||
|
DRM_MODE_OBJECT_CRTC);
|
||||||
|
if (!obj) {
|
||||||
|
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
|
||||||
|
plane_req->crtc_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
crtc = obj_to_crtc(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setplane_internal(crtc, plane, fb,
|
||||||
|
plane_req->crtc_x, plane_req->crtc_y,
|
||||||
|
plane_req->crtc_w, plane_req->crtc_h,
|
||||||
|
plane_req->src_x, plane_req->src_y,
|
||||||
|
plane_req->src_w, plane_req->src_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue