diff options
| author | Rob Clark <rob@ti.com> | 2012-09-04 12:35:56 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-10-02 08:16:07 -0400 |
| commit | 7c80e128429d639742043f8fbdd7f1551c940ea3 (patch) | |
| tree | d387994498a91a65785ab7e0e559531c45395323 | |
| parent | f7eff60ea0e4e35732604e3591e2ff7b3ef41981 (diff) | |
drm: support for rotated scanout
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.
v1: original
v2: remove invert_dimensions from plane, at Ville's suggestion.
Userspace can give rotated src coordinates, so invert_dimensions
is not required for planes.
Signed-off-by: Rob Clark <rob@ti.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 46 | ||||
| -rw-r--r-- | include/drm/drm_crtc.h | 5 |
2 files changed, 35 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 39afe13a5fa2..9c346a50379f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -437,6 +437,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
| 437 | 437 | ||
| 438 | crtc->dev = dev; | 438 | crtc->dev = dev; |
| 439 | crtc->funcs = funcs; | 439 | crtc->funcs = funcs; |
| 440 | crtc->invert_dimensions = false; | ||
| 440 | 441 | ||
| 441 | mutex_lock(&dev->mode_config.mutex); | 442 | mutex_lock(&dev->mode_config.mutex); |
| 442 | 443 | ||
| @@ -1912,6 +1913,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 1912 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); | 1913 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
| 1913 | 1914 | ||
| 1914 | if (crtc_req->mode_valid) { | 1915 | if (crtc_req->mode_valid) { |
| 1916 | int hdisplay, vdisplay; | ||
| 1915 | /* If we have a mode we need a framebuffer. */ | 1917 | /* If we have a mode we need a framebuffer. */ |
| 1916 | /* If we pass -1, set the mode with the currently bound fb */ | 1918 | /* If we pass -1, set the mode with the currently bound fb */ |
| 1917 | if (crtc_req->fb_id == -1) { | 1919 | if (crtc_req->fb_id == -1) { |
| @@ -1947,14 +1949,20 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 1947 | 1949 | ||
| 1948 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | 1950 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
| 1949 | 1951 | ||
| 1950 | if (mode->hdisplay > fb->width || | 1952 | hdisplay = mode->hdisplay; |
| 1951 | mode->vdisplay > fb->height || | 1953 | vdisplay = mode->vdisplay; |
| 1952 | crtc_req->x > fb->width - mode->hdisplay || | 1954 | |
| 1953 | crtc_req->y > fb->height - mode->vdisplay) { | 1955 | if (crtc->invert_dimensions) |
| 1954 | DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", | 1956 | swap(hdisplay, vdisplay); |
| 1955 | mode->hdisplay, mode->vdisplay, | 1957 | |
| 1956 | crtc_req->x, crtc_req->y, | 1958 | if (hdisplay > fb->width || |
| 1957 | fb->width, fb->height); | 1959 | vdisplay > fb->height || |
| 1960 | crtc_req->x > fb->width - hdisplay || | ||
| 1961 | crtc_req->y > fb->height - vdisplay) { | ||
| 1962 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", | ||
| 1963 | fb->width, fb->height, | ||
| 1964 | hdisplay, vdisplay, crtc_req->x, crtc_req->y, | ||
| 1965 | crtc->invert_dimensions ? " (inverted)" : ""); | ||
| 1958 | ret = -ENOSPC; | 1966 | ret = -ENOSPC; |
| 1959 | goto out; | 1967 | goto out; |
| 1960 | } | 1968 | } |
| @@ -3546,6 +3554,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
| 3546 | struct drm_framebuffer *fb; | 3554 | struct drm_framebuffer *fb; |
| 3547 | struct drm_pending_vblank_event *e = NULL; | 3555 | struct drm_pending_vblank_event *e = NULL; |
| 3548 | unsigned long flags; | 3556 | unsigned long flags; |
| 3557 | int hdisplay, vdisplay; | ||
| 3549 | int ret = -EINVAL; | 3558 | int ret = -EINVAL; |
| 3550 | 3559 | ||
| 3551 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || | 3560 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || |
| @@ -3575,14 +3584,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
| 3575 | goto out; | 3584 | goto out; |
| 3576 | fb = obj_to_fb(obj); | 3585 | fb = obj_to_fb(obj); |
| 3577 | 3586 | ||
| 3578 | if (crtc->mode.hdisplay > fb->width || | 3587 | hdisplay = crtc->mode.hdisplay; |
| 3579 | crtc->mode.vdisplay > fb->height || | 3588 | vdisplay = crtc->mode.vdisplay; |
| 3580 | crtc->x > fb->width - crtc->mode.hdisplay || | 3589 | |
| 3581 | crtc->y > fb->height - crtc->mode.vdisplay) { | 3590 | if (crtc->invert_dimensions) |
| 3582 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", | 3591 | swap(hdisplay, vdisplay); |
| 3583 | fb->width, fb->height, | 3592 | |
| 3584 | crtc->mode.hdisplay, crtc->mode.vdisplay, | 3593 | if (hdisplay > fb->width || |
| 3585 | crtc->x, crtc->y); | 3594 | vdisplay > fb->height || |
| 3595 | crtc->x > fb->width - hdisplay || | ||
| 3596 | crtc->y > fb->height - vdisplay) { | ||
| 3597 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", | ||
| 3598 | fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y, | ||
| 3599 | crtc->invert_dimensions ? " (inverted)" : ""); | ||
| 3586 | ret = -ENOSPC; | 3600 | ret = -ENOSPC; |
| 3587 | goto out; | 3601 | goto out; |
| 3588 | } | 3602 | } |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 68fdb299e39f..8e405b82707d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -368,6 +368,9 @@ struct drm_crtc_funcs { | |||
| 368 | * @enabled: is this CRTC enabled? | 368 | * @enabled: is this CRTC enabled? |
| 369 | * @mode: current mode timings | 369 | * @mode: current mode timings |
| 370 | * @hwmode: mode timings as programmed to hw regs | 370 | * @hwmode: mode timings as programmed to hw regs |
| 371 | * @invert_dimensions: for purposes of error checking crtc vs fb sizes, | ||
| 372 | * invert the width/height of the crtc. This is used if the driver | ||
| 373 | * is performing 90 or 270 degree rotated scanout | ||
| 371 | * @x: x position on screen | 374 | * @x: x position on screen |
| 372 | * @y: y position on screen | 375 | * @y: y position on screen |
| 373 | * @funcs: CRTC control functions | 376 | * @funcs: CRTC control functions |
| @@ -401,6 +404,8 @@ struct drm_crtc { | |||
| 401 | */ | 404 | */ |
| 402 | struct drm_display_mode hwmode; | 405 | struct drm_display_mode hwmode; |
| 403 | 406 | ||
| 407 | bool invert_dimensions; | ||
| 408 | |||
| 404 | int x, y; | 409 | int x, y; |
| 405 | const struct drm_crtc_funcs *funcs; | 410 | const struct drm_crtc_funcs *funcs; |
| 406 | 411 | ||
