diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
| -rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 03583887cfec..98a36e6c69ad 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -402,6 +402,7 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
| 402 | { | 402 | { |
| 403 | struct drm_mode_crtc *crtc_resp = data; | 403 | struct drm_mode_crtc *crtc_resp = data; |
| 404 | struct drm_crtc *crtc; | 404 | struct drm_crtc *crtc; |
| 405 | struct drm_plane *plane; | ||
| 405 | 406 | ||
| 406 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 407 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
| 407 | return -EINVAL; | 408 | return -EINVAL; |
| @@ -410,34 +411,36 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
| 410 | if (!crtc) | 411 | if (!crtc) |
| 411 | return -ENOENT; | 412 | return -ENOENT; |
| 412 | 413 | ||
| 414 | plane = crtc->primary; | ||
| 415 | |||
| 413 | crtc_resp->gamma_size = crtc->gamma_size; | 416 | crtc_resp->gamma_size = crtc->gamma_size; |
| 414 | 417 | ||
| 415 | drm_modeset_lock(&crtc->primary->mutex, NULL); | 418 | drm_modeset_lock(&plane->mutex, NULL); |
| 416 | if (crtc->primary->state && crtc->primary->state->fb) | 419 | if (plane->state && plane->state->fb) |
| 417 | crtc_resp->fb_id = crtc->primary->state->fb->base.id; | 420 | crtc_resp->fb_id = plane->state->fb->base.id; |
| 418 | else if (!crtc->primary->state && crtc->primary->fb) | 421 | else if (!plane->state && plane->fb) |
| 419 | crtc_resp->fb_id = crtc->primary->fb->base.id; | 422 | crtc_resp->fb_id = plane->fb->base.id; |
| 420 | else | 423 | else |
| 421 | crtc_resp->fb_id = 0; | 424 | crtc_resp->fb_id = 0; |
| 422 | 425 | ||
| 423 | if (crtc->primary->state) { | 426 | if (plane->state) { |
| 424 | crtc_resp->x = crtc->primary->state->src_x >> 16; | 427 | crtc_resp->x = plane->state->src_x >> 16; |
| 425 | crtc_resp->y = crtc->primary->state->src_y >> 16; | 428 | crtc_resp->y = plane->state->src_y >> 16; |
| 426 | } | 429 | } |
| 427 | drm_modeset_unlock(&crtc->primary->mutex); | 430 | drm_modeset_unlock(&plane->mutex); |
| 428 | 431 | ||
| 429 | drm_modeset_lock(&crtc->mutex, NULL); | 432 | drm_modeset_lock(&crtc->mutex, NULL); |
| 430 | if (crtc->state) { | 433 | if (crtc->state) { |
| 431 | if (crtc->state->enable) { | 434 | if (crtc->state->enable) { |
| 432 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); | 435 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); |
| 433 | crtc_resp->mode_valid = 1; | 436 | crtc_resp->mode_valid = 1; |
| 434 | |||
| 435 | } else { | 437 | } else { |
| 436 | crtc_resp->mode_valid = 0; | 438 | crtc_resp->mode_valid = 0; |
| 437 | } | 439 | } |
| 438 | } else { | 440 | } else { |
| 439 | crtc_resp->x = crtc->x; | 441 | crtc_resp->x = crtc->x; |
| 440 | crtc_resp->y = crtc->y; | 442 | crtc_resp->y = crtc->y; |
| 443 | |||
| 441 | if (crtc->enabled) { | 444 | if (crtc->enabled) { |
| 442 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode); | 445 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode); |
| 443 | crtc_resp->mode_valid = 1; | 446 | crtc_resp->mode_valid = 1; |
| @@ -446,6 +449,8 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
| 446 | crtc_resp->mode_valid = 0; | 449 | crtc_resp->mode_valid = 0; |
| 447 | } | 450 | } |
| 448 | } | 451 | } |
| 452 | if (!file_priv->aspect_ratio_allowed) | ||
| 453 | crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; | ||
| 449 | drm_modeset_unlock(&crtc->mutex); | 454 | drm_modeset_unlock(&crtc->mutex); |
| 450 | 455 | ||
| 451 | return 0; | 456 | return 0; |
| @@ -471,7 +476,7 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set, | |||
| 471 | 476 | ||
| 472 | ret = crtc->funcs->set_config(set, ctx); | 477 | ret = crtc->funcs->set_config(set, ctx); |
| 473 | if (ret == 0) { | 478 | if (ret == 0) { |
| 474 | crtc->primary->crtc = crtc; | 479 | crtc->primary->crtc = fb ? crtc : NULL; |
| 475 | crtc->primary->fb = fb; | 480 | crtc->primary->fb = fb; |
| 476 | } | 481 | } |
| 477 | 482 | ||
| @@ -554,6 +559,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 554 | struct drm_mode_config *config = &dev->mode_config; | 559 | struct drm_mode_config *config = &dev->mode_config; |
| 555 | struct drm_mode_crtc *crtc_req = data; | 560 | struct drm_mode_crtc *crtc_req = data; |
| 556 | struct drm_crtc *crtc; | 561 | struct drm_crtc *crtc; |
| 562 | struct drm_plane *plane; | ||
| 557 | struct drm_connector **connector_set = NULL, *connector; | 563 | struct drm_connector **connector_set = NULL, *connector; |
| 558 | struct drm_framebuffer *fb = NULL; | 564 | struct drm_framebuffer *fb = NULL; |
| 559 | struct drm_display_mode *mode = NULL; | 565 | struct drm_display_mode *mode = NULL; |
| @@ -580,22 +586,33 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
| 580 | } | 586 | } |
| 581 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); | 587 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
| 582 | 588 | ||
| 589 | plane = crtc->primary; | ||
| 590 | |||
| 583 | mutex_lock(&crtc->dev->mode_config.mutex); | 591 | mutex_lock(&crtc->dev->mode_config.mutex); |
| 584 | drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); | 592 | drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); |
| 585 | retry: | 593 | retry: |
| 586 | ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); | 594 | ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); |
| 587 | if (ret) | 595 | if (ret) |
| 588 | goto out; | 596 | goto out; |
| 597 | |||
| 589 | if (crtc_req->mode_valid) { | 598 | if (crtc_req->mode_valid) { |
| 590 | /* If we have a mode we need a framebuffer. */ | 599 | /* If we have a mode we need a framebuffer. */ |
| 591 | /* If we pass -1, set the mode with the currently bound fb */ | 600 | /* If we pass -1, set the mode with the currently bound fb */ |
| 592 | if (crtc_req->fb_id == -1) { | 601 | if (crtc_req->fb_id == -1) { |
| 593 | if (!crtc->primary->fb) { | 602 | struct drm_framebuffer *old_fb; |
| 603 | |||
| 604 | if (plane->state) | ||
| 605 | old_fb = plane->state->fb; | ||
| 606 | else | ||
| 607 | old_fb = plane->fb; | ||
| 608 | |||
| 609 | if (!old_fb) { | ||
| 594 | DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); | 610 | DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); |
| 595 | ret = -EINVAL; | 611 | ret = -EINVAL; |
| 596 | goto out; | 612 | goto out; |
| 597 | } | 613 | } |
| 598 | fb = crtc->primary->fb; | 614 | |
| 615 | fb = old_fb; | ||
| 599 | /* Make refcounting symmetric with the lookup path. */ | 616 | /* Make refcounting symmetric with the lookup path. */ |
| 600 | drm_framebuffer_get(fb); | 617 | drm_framebuffer_get(fb); |
| 601 | } else { | 618 | } else { |
| @@ -613,6 +630,13 @@ retry: | |||
| 613 | ret = -ENOMEM; | 630 | ret = -ENOMEM; |
| 614 | goto out; | 631 | goto out; |
| 615 | } | 632 | } |
| 633 | if (!file_priv->aspect_ratio_allowed && | ||
| 634 | (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) { | ||
| 635 | DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n"); | ||
| 636 | ret = -EINVAL; | ||
| 637 | goto out; | ||
| 638 | } | ||
| 639 | |||
| 616 | 640 | ||
| 617 | ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode); | 641 | ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode); |
| 618 | if (ret) { | 642 | if (ret) { |
| @@ -627,8 +651,8 @@ retry: | |||
| 627 | * match real hardware capabilities. Skip the check in that | 651 | * match real hardware capabilities. Skip the check in that |
| 628 | * case. | 652 | * case. |
| 629 | */ | 653 | */ |
| 630 | if (!crtc->primary->format_default) { | 654 | if (!plane->format_default) { |
| 631 | ret = drm_plane_check_pixel_format(crtc->primary, | 655 | ret = drm_plane_check_pixel_format(plane, |
| 632 | fb->format->format, | 656 | fb->format->format, |
| 633 | fb->modifier); | 657 | fb->modifier); |
| 634 | if (ret) { | 658 | if (ret) { |
