summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_crtc.c46
-rw-r--r--include/drm/drm_crtc.h5
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