diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 86 | 
1 files changed, 26 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index ebff850a9ab..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,  }  static int intel_overlay_do_wait_request(struct intel_overlay *overlay, -					 struct drm_i915_gem_request *request,  					 void (*tail)(struct intel_overlay *))  {  	struct drm_device *dev = overlay->dev; @@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,  	int ret;  	BUG_ON(overlay->last_flip_req); -	ret = i915_add_request(ring, NULL, request); -	if (ret) { -	    kfree(request); -	    return ret; -	} -	overlay->last_flip_req = request->seqno; +	ret = i915_add_request(ring, NULL, &overlay->last_flip_req); +	if (ret) +		return ret; +  	overlay->flip_tail = tail;  	ret = i915_wait_seqno(ring, overlay->last_flip_req);  	if (ret) @@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	struct drm_device *dev = overlay->dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; -	struct drm_i915_gem_request *request;  	int ret;  	BUG_ON(overlay->active); @@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) { -		ret = -ENOMEM; -		goto out; -	} -  	ret = intel_ring_begin(ring, 4); -	if (ret) { -		kfree(request); -		goto out; -	} +	if (ret) +		return ret;  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);  	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); @@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	intel_ring_emit(ring, MI_NOOP);  	intel_ring_advance(ring); -	ret = intel_overlay_do_wait_request(overlay, request, NULL); -out: -	return ret; +	return intel_overlay_do_wait_request(overlay, NULL);  }  /* overlay needs to be enabled in OCMD reg */ @@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay,  	struct drm_device *dev = overlay->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; -	struct drm_i915_gem_request *request;  	u32 flip_addr = overlay->flip_addr;  	u32 tmp;  	int ret;  	BUG_ON(!overlay->active); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) -		return -ENOMEM; -  	if (load_polyphase_filter)  		flip_addr |= OFC_UPDATE; @@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay,  		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);  	ret = intel_ring_begin(ring, 2); -	if (ret) { -		kfree(request); +	if (ret)  		return ret; -	} +  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);  	intel_ring_emit(ring, flip_addr);  	intel_ring_advance(ring); -	ret = i915_add_request(ring, NULL, request); -	if (ret) { -		kfree(request); -		return ret; -	} - -	overlay->last_flip_req = request->seqno; -	return 0; +	return i915_add_request(ring, NULL, &overlay->last_flip_req);  }  static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];  	u32 flip_addr = overlay->flip_addr; -	struct drm_i915_gem_request *request;  	int ret;  	BUG_ON(!overlay->active); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) -		return -ENOMEM; -  	/* According to intel docs the overlay hw may hang (when switching  	 * off) without loading the filter coeffs. It is however unclear whether  	 * this applies to the disabling of the overlay or to the switching off @@ -365,22 +333,28 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	flip_addr |= OFC_UPDATE;  	ret = intel_ring_begin(ring, 6); -	if (ret) { -		kfree(request); +	if (ret)  		return ret; -	} +  	/* wait for overlay to go idle */  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);  	intel_ring_emit(ring, flip_addr);  	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  	/* turn overlay off */ -	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -	intel_ring_emit(ring, flip_addr); -	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	if (IS_I830(dev)) { +		/* Workaround: Don't disable the overlay fully, since otherwise +		 * it dies on the next OVERLAY_ON cmd. */ +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +	} else { +		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); +		intel_ring_emit(ring, flip_addr); +		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	}  	intel_ring_advance(ring); -	return intel_overlay_do_wait_request(overlay, request, -					     intel_overlay_off_tail); +	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);  }  /* recover from an interruption due to a signal @@ -425,24 +399,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)  		return 0;  	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { -		struct drm_i915_gem_request *request; -  		/* synchronous slowpath */ -		request = kzalloc(sizeof(*request), GFP_KERNEL); -		if (request == NULL) -			return -ENOMEM; -  		ret = intel_ring_begin(ring, 2); -		if (ret) { -			kfree(request); +		if (ret)  			return ret; -		}  		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  		intel_ring_emit(ring, MI_NOOP);  		intel_ring_advance(ring); -		ret = intel_overlay_do_wait_request(overlay, request, +		ret = intel_overlay_do_wait_request(overlay,  						    intel_overlay_release_old_vid_tail);  		if (ret)  			return ret;  |