diff options
author | Rob Clark <rob@ti.com> | 2012-05-14 11:56:19 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2012-06-20 12:06:17 +0800 |
commit | 8fd96717b9c4202747ce7bdf7b09a522414c3901 (patch) | |
tree | 7d14df2fc6076e5054eaaf326aaca2504f194716 | |
parent | c446cafb10f00c53bf8d66f13c72066a7a1bade0 (diff) |
drm: support for rotated scanouttracking-topic-omapdrm-rotation
For drivers that can support rotated scanout, the extra parameter
checking in drm-core, while nice, tends to get confused. To solve
this drivers can set the crtc or plane invert_dimensions field so
that the dimension checking takes into account the rotation that
the driver is performing.
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 50 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 9 |
2 files changed, 43 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c196c8d43b0..6e38c608ed9 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -375,6 +375,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, crtc->dev = dev; crtc->funcs = funcs; + crtc->invert_dimensions = false; mutex_lock(&dev->mode_config.mutex); @@ -609,6 +610,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->base.properties = &plane->properties; plane->dev = dev; plane->funcs = funcs; + plane->invert_dimensions = false; plane->format_types = kmalloc(sizeof(uint32_t) * format_count, GFP_KERNEL); if (!plane->format_types) { @@ -1758,6 +1760,9 @@ int drm_mode_setplane(struct drm_device *dev, void *data, fb_width = fb->width << 16; fb_height = fb->height << 16; + if (plane->invert_dimensions) + swap(fb_width, fb_height); + /* Make sure source coordinates are inside the fb. */ if (plane_req->src_w > fb_width || plane_req->src_x > fb_width - plane_req->src_w || @@ -1856,6 +1861,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); if (crtc_req->mode_valid) { + int hdisplay, vdisplay; /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ if (crtc_req->fb_id == -1) { @@ -1891,14 +1897,20 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - if (mode->hdisplay > fb->width || - mode->vdisplay > fb->height || - crtc_req->x > fb->width - mode->hdisplay || - crtc_req->y > fb->height - mode->vdisplay) { - DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", - mode->hdisplay, mode->vdisplay, - crtc_req->x, crtc_req->y, - fb->width, fb->height); + hdisplay = mode->hdisplay; + vdisplay = mode->vdisplay; + + if (crtc->invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay > fb->width || + vdisplay > fb->height || + crtc_req->x > fb->width - hdisplay || + crtc_req->y > fb->height - vdisplay) { + DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", + fb->width, fb->height, + hdisplay, vdisplay, crtc_req->x, crtc_req->y, + crtc->invert_dimensions ? " (inverted)" : ""); ret = -ENOSPC; goto out; } @@ -3457,6 +3469,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_framebuffer *fb; struct drm_pending_vblank_event *e = NULL; unsigned long flags; + int hdisplay, vdisplay; int ret = -EINVAL; if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || @@ -3486,14 +3499,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, goto out; fb = obj_to_fb(obj); - if (crtc->mode.hdisplay > fb->width || - crtc->mode.vdisplay > fb->height || - crtc->x > fb->width - crtc->mode.hdisplay || - crtc->y > fb->height - crtc->mode.vdisplay) { - DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", - fb->width, fb->height, - crtc->mode.hdisplay, crtc->mode.vdisplay, - crtc->x, crtc->y); + hdisplay = crtc->mode.hdisplay; + vdisplay = crtc->mode.vdisplay; + + if (crtc->invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay > fb->width || + vdisplay > fb->height || + crtc->x > fb->width - hdisplay || + crtc->y > fb->height - vdisplay) { + DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", + fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y, + crtc->invert_dimensions ? " (inverted)" : ""); ret = -ENOSPC; goto out; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 405555a53f1..c32de9bd338 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -364,6 +364,9 @@ struct drm_crtc_funcs { * @enabled: is this CRTC enabled? * @mode: current mode timings * @hwmode: mode timings as programmed to hw regs + * @invert_dimensions: for purposes of error checking crtc vs fb sizes, + * invert the width/height of the crtc. This is used if the driver + * is performing 90 or 270 degree rotated scanout * @x: x position on screen * @y: y position on screen * @funcs: CRTC control functions @@ -397,6 +400,8 @@ struct drm_crtc { */ struct drm_display_mode hwmode; + bool invert_dimensions; + int x, y; const struct drm_crtc_funcs *funcs; @@ -636,6 +641,9 @@ struct drm_plane_funcs { * @gamma_size: size of gamma table * @gamma_store: gamma correction table * @enabled: enabled flag + * @invert_dimensions: for purposes of error checking plane vs fb sizes, + * invert the width/height of the plane. This is used if the driver + * is performing 90 or 270 degree rotated scanout * @funcs: helper functions * @helper_private: storage for drver layer */ @@ -657,6 +665,7 @@ struct drm_plane { uint16_t *gamma_store; bool enabled; + bool invert_dimensions; const struct drm_plane_funcs *funcs; void *helper_private; |