diff options
-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 | ||