Commit b303cf95 authored by Chris Wilson's avatar Chris Wilson

drm/i915/overlay: Use a continuation hook to finish work after a flip.

Slightly easier to follow than the state machine and now possible as the
control structure is opaque and hw_wedged is no longer interferred with.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 23f09ce3
...@@ -186,11 +186,7 @@ struct intel_overlay { ...@@ -186,11 +186,7 @@ struct intel_overlay {
struct drm_i915_gem_object *reg_bo; struct drm_i915_gem_object *reg_bo;
/* flip handling */ /* flip handling */
uint32_t last_flip_req; uint32_t last_flip_req;
int hw_wedged; void (*flip_tail)(struct intel_overlay *);
#define HW_WEDGED 1
#define NEEDS_WAIT_FOR_FLIP 2
#define RELEASE_OLD_VID 3
#define SWITCH_OFF 4
}; };
static struct overlay_registers * static struct overlay_registers *
...@@ -243,25 +239,25 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, ...@@ -243,25 +239,25 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
static int intel_overlay_do_wait_request(struct intel_overlay *overlay, static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
struct drm_i915_gem_request *request, struct drm_i915_gem_request *request,
bool interruptible, bool interruptible,
int stage) void (*tail)(struct intel_overlay *))
{ {
struct drm_device *dev = overlay->dev; struct drm_device *dev = overlay->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
int ret; int ret;
BUG_ON(overlay->last_flip_req);
overlay->last_flip_req = overlay->last_flip_req =
i915_add_request(dev, NULL, request, &dev_priv->render_ring); i915_add_request(dev, NULL, request, &dev_priv->render_ring);
if (overlay->last_flip_req == 0) if (overlay->last_flip_req == 0)
return -ENOMEM; return -ENOMEM;
overlay->hw_wedged = stage; overlay->flip_tail = tail;
ret = i915_do_wait_request(dev, ret = i915_do_wait_request(dev,
overlay->last_flip_req, true, overlay->last_flip_req, true,
&dev_priv->render_ring); &dev_priv->render_ring);
if (ret) if (ret)
return ret; return ret;
overlay->hw_wedged = 0;
overlay->last_flip_req = 0; overlay->last_flip_req = 0;
return 0; return 0;
} }
...@@ -344,8 +340,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) ...@@ -344,8 +340,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
OUT_RING(MI_NOOP); OUT_RING(MI_NOOP);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
ret = intel_overlay_do_wait_request(overlay, request, true, ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
NEEDS_WAIT_FOR_FLIP);
out: out:
if (pipe_a_quirk) if (pipe_a_quirk)
i830_deactivate_pipe_a(dev); i830_deactivate_pipe_a(dev);
...@@ -387,6 +382,33 @@ static int intel_overlay_continue(struct intel_overlay *overlay, ...@@ -387,6 +382,33 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
return 0; return 0;
} }
static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
{
struct drm_gem_object *obj = &overlay->old_vid_bo->base;
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
overlay->old_vid_bo = NULL;
}
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
struct drm_gem_object *obj;
/* never have the overlay hw on without showing a frame */
BUG_ON(!overlay->vid_bo);
obj = &overlay->vid_bo->base;
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
overlay->vid_bo = NULL;
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
overlay->active = 0;
}
/* overlay needs to be disabled in OCMD reg */ /* overlay needs to be disabled in OCMD reg */
static int intel_overlay_off(struct intel_overlay *overlay, static int intel_overlay_off(struct intel_overlay *overlay,
bool interruptible) bool interruptible)
...@@ -419,34 +441,7 @@ static int intel_overlay_off(struct intel_overlay *overlay, ...@@ -419,34 +441,7 @@ static int intel_overlay_off(struct intel_overlay *overlay,
ADVANCE_LP_RING(); ADVANCE_LP_RING();
return intel_overlay_do_wait_request(overlay, request, interruptible, return intel_overlay_do_wait_request(overlay, request, interruptible,
SWITCH_OFF); intel_overlay_off_tail);
}
static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
{
struct drm_gem_object *obj = &overlay->old_vid_bo->base;
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
overlay->old_vid_bo = NULL;
}
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
struct drm_gem_object *obj;
/* never have the overlay hw on without showing a frame */
BUG_ON(!overlay->vid_bo);
obj = &overlay->vid_bo->base;
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
overlay->vid_bo = NULL;
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
overlay->active = 0;
} }
/* recover from an interruption due to a signal /* recover from an interruption due to a signal
...@@ -458,28 +453,17 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, ...@@ -458,28 +453,17 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
int ret; int ret;
if (overlay->hw_wedged == HW_WEDGED) if (overlay->last_flip_req == 0)
return -EIO; return 0;
ret = i915_do_wait_request(dev, overlay->last_flip_req, ret = i915_do_wait_request(dev, overlay->last_flip_req,
interruptible, &dev_priv->render_ring); interruptible, &dev_priv->render_ring);
if (ret) if (ret)
return ret; return ret;
switch (overlay->hw_wedged) { if (overlay->flip_tail)
case RELEASE_OLD_VID: overlay->flip_tail(overlay);
intel_overlay_release_old_vid_tail(overlay);
break;
case SWITCH_OFF:
intel_overlay_off_tail(overlay);
break;
default:
BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
}
overlay->hw_wedged = 0;
overlay->last_flip_req = 0; overlay->last_flip_req = 0;
return 0; return 0;
} }
...@@ -514,7 +498,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) ...@@ -514,7 +498,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
ADVANCE_LP_RING(); ADVANCE_LP_RING();
ret = intel_overlay_do_wait_request(overlay, request, true, ret = intel_overlay_do_wait_request(overlay, request, true,
RELEASE_OLD_VID); intel_overlay_release_old_vid_tail);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -889,12 +873,9 @@ int intel_overlay_switch_off(struct intel_overlay *overlay, ...@@ -889,12 +873,9 @@ int intel_overlay_switch_off(struct intel_overlay *overlay,
BUG_ON(!mutex_is_locked(&dev->struct_mutex)); BUG_ON(!mutex_is_locked(&dev->struct_mutex));
BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
if (overlay->hw_wedged) { ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
ret = intel_overlay_recover_from_interrupt(overlay, if (ret != 0)
interruptible); return ret;
if (ret != 0)
return ret;
}
if (!overlay->active) if (!overlay->active)
return 0; return 0;
...@@ -912,7 +893,6 @@ int intel_overlay_switch_off(struct intel_overlay *overlay, ...@@ -912,7 +893,6 @@ int intel_overlay_switch_off(struct intel_overlay *overlay,
return ret; return ret;
intel_overlay_off_tail(overlay); intel_overlay_off_tail(overlay);
return 0; return 0;
} }
...@@ -1153,11 +1133,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, ...@@ -1153,11 +1133,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (overlay->hw_wedged) { ret = intel_overlay_recover_from_interrupt(overlay, true);
ret = intel_overlay_recover_from_interrupt(overlay, 1); if (ret != 0)
if (ret != 0) goto out_unlock;
goto out_unlock;
}
if (overlay->crtc != crtc) { if (overlay->crtc != crtc) {
struct drm_display_mode *mode = &crtc->base.mode; struct drm_display_mode *mode = &crtc->base.mode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment