X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fintel_sprite.c;h=8afaad6bcc4821981a2843a843d2d69c33151dd4;hb=4c445e0ebc648ee42c0d21713b8f76597854d47a;hp=b859f944b53bdd2319c35e12b21cc7dd9fea9c7c;hpb=82284b6becdbef6d8cd3fb43e8698510833a5129;p=deliverable%2Flinux.git diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b859f944b53b..8afaad6bcc48 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -521,16 +521,28 @@ intel_enable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (!intel_crtc->primary_disabled) + if (intel_crtc->primary_enabled) return; - intel_crtc->primary_disabled = false; + intel_crtc->primary_enabled = true; + + I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); + intel_flush_primary_plane(dev_priv, intel_crtc->plane); + + /* + * FIXME IPS should be fine as long as one plane is + * enabled, but in practice it seems to have problems + * when going from primary only to sprite only and vice + * versa. + */ + if (intel_crtc->config.ips_enabled) { + intel_wait_for_vblank(dev, intel_crtc->pipe); + hsw_enable_ips(intel_crtc); + } mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); mutex_unlock(&dev->struct_mutex); - - I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); } static void @@ -541,16 +553,26 @@ intel_disable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (intel_crtc->primary_disabled) + if (!intel_crtc->primary_enabled) return; - I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); - - intel_crtc->primary_disabled = true; + intel_crtc->primary_enabled = false; mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + if (dev_priv->fbc.plane == intel_crtc->plane) + intel_disable_fbc(dev); mutex_unlock(&dev->struct_mutex); + + /* + * FIXME IPS should be fine as long as one plane is + * enabled, but in practice it seems to have problems + * when going from primary only to sprite only and vice + * versa. + */ + hsw_disable_ips(intel_crtc); + + I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); + intel_flush_primary_plane(dev_priv, intel_crtc->plane); } static int @@ -631,9 +653,10 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_device *dev = plane->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj, *old_obj; - int ret = 0; + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *old_obj = intel_plane->obj; + int ret; bool disable_primary = false; bool visible; int hscale, vscale; @@ -657,20 +680,20 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, }; - - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; - - old_obj = intel_plane->obj; - - intel_plane->crtc_x = crtc_x; - intel_plane->crtc_y = crtc_y; - intel_plane->crtc_w = crtc_w; - intel_plane->crtc_h = crtc_h; - intel_plane->src_x = src_x; - intel_plane->src_y = src_y; - intel_plane->src_w = src_w; - intel_plane->src_h = src_h; + const struct { + int crtc_x, crtc_y; + unsigned int crtc_w, crtc_h; + uint32_t src_x, src_y, src_w, src_h; + } orig = { + .crtc_x = crtc_x, + .crtc_y = crtc_y, + .crtc_w = crtc_w, + .crtc_h = crtc_h, + .src_x = src_x, + .src_y = src_y, + .src_w = src_w, + .src_h = src_h, + }; /* Don't modify another pipe's plane */ if (intel_plane->pipe != intel_crtc->pipe) { @@ -822,6 +845,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; + intel_plane->crtc_x = orig.crtc_x; + intel_plane->crtc_y = orig.crtc_y; + intel_plane->crtc_w = orig.crtc_w; + intel_plane->crtc_h = orig.crtc_h; + intel_plane->src_x = orig.src_x; + intel_plane->src_y = orig.src_y; + intel_plane->src_w = orig.src_w; + intel_plane->src_h = orig.src_h; intel_plane->obj = obj; if (intel_crtc->active) { @@ -852,7 +883,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * do the pin & ref bookkeeping. */ if (old_obj != obj && intel_crtc->active) - intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); + intel_wait_for_vblank(dev, intel_crtc->pipe); mutex_lock(&dev->struct_mutex); intel_unpin_fb_obj(old_obj); @@ -868,7 +899,6 @@ intel_disable_plane(struct drm_plane *plane) struct drm_device *dev = plane->dev; struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_crtc *intel_crtc; - int ret = 0; if (!plane->fb) return 0; @@ -883,20 +913,18 @@ intel_disable_plane(struct drm_plane *plane) intel_plane->disable_plane(plane, plane->crtc); } - if (!intel_plane->obj) - goto out; - - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_plane->pipe); + if (intel_plane->obj) { + if (intel_crtc->active) + intel_wait_for_vblank(dev, intel_plane->pipe); - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_plane->obj); - mutex_unlock(&dev->struct_mutex); + mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(intel_plane->obj); + mutex_unlock(&dev->struct_mutex); - intel_plane->obj = NULL; -out: + intel_plane->obj = NULL; + } - return ret; + return 0; } static void intel_destroy_plane(struct drm_plane *plane)