diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 7cb062daa71..8086c96e0b0 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -303,8 +303,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) if (update_pending && (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, &vpos, &hpos)) && - (vpos >=0) && - (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) { + ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || + (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { + /* crtc didn't flip in this target vblank interval, + * but flip is pending in crtc. Based on the current + * scanout position we know that the current frame is + * (nearly) complete and the flip will (likely) + * complete before the start of the next frame. + */ + update_pending = 0; + } + if (update_pending) { /* crtc didn't flip in this target vblank interval, * but flip is pending in crtc. It will complete it * in next vblank interval, so complete the flip at @@ -393,7 +402,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, DRM_ERROR("failed to reserve new rbo buffer before flip\n"); goto pflip_cleanup; } - r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); + /* Only 27 bit offset for legacy CRTC */ + r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); if (unlikely(r != 0)) { radeon_bo_unreserve(rbo); r = -EINVAL; @@ -1078,15 +1089,21 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = { .create_handle = radeon_user_framebuffer_create_handle, }; -void +int radeon_framebuffer_init(struct drm_device *dev, struct radeon_framebuffer *rfb, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object *obj) { + int ret; rfb->obj = obj; - drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); + ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); + if (ret) { + rfb->obj = NULL; + return ret; + } drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd); + return 0; } static struct drm_framebuffer * @@ -1096,6 +1113,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, { struct drm_gem_object *obj; struct radeon_framebuffer *radeon_fb; + int ret; obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); if (obj == NULL) { @@ -1108,7 +1126,12 @@ radeon_user_framebuffer_create(struct drm_device *dev, if (radeon_fb == NULL) return ERR_PTR(-ENOMEM); - radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); + ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); + if (ret) { + kfree(radeon_fb); + drm_gem_object_unreference_unlocked(obj); + return NULL; + } return &radeon_fb->base; } @@ -1273,7 +1296,7 @@ int radeon_modeset_init(struct radeon_device *rdev) /* init dig PHYs, disp eng pll */ if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); - radeon_atom_dcpll_init(rdev); + radeon_atom_disp_eng_pll_init(rdev); } /* initialize hpd */ |