drm/i915/overlay: Combine SWITCH_OFF into a single step
We can program the h/w to first wait on the flip and then switch off without relying on s/w intervention. This removes the need for a double step switch off, bringing much rejoicing. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
9bb2ff731b
commit
8dfbc34031
@ -167,8 +167,7 @@ struct intel_overlay {
|
|||||||
#define HW_WEDGED 1
|
#define HW_WEDGED 1
|
||||||
#define NEEDS_WAIT_FOR_FLIP 2
|
#define NEEDS_WAIT_FOR_FLIP 2
|
||||||
#define RELEASE_OLD_VID 3
|
#define RELEASE_OLD_VID 3
|
||||||
#define SWITCH_OFF_STAGE_1 4
|
#define SWITCH_OFF 4
|
||||||
#define SWITCH_OFF_STAGE_2 5
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct intel_crtc {
|
struct intel_crtc {
|
||||||
|
@ -325,7 +325,6 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|||||||
{
|
{
|
||||||
u32 flip_addr = overlay->flip_addr;
|
u32 flip_addr = overlay->flip_addr;
|
||||||
struct drm_device *dev = overlay->dev;
|
struct drm_device *dev = overlay->dev;
|
||||||
int ret;
|
|
||||||
|
|
||||||
BUG_ON(!overlay->active);
|
BUG_ON(!overlay->active);
|
||||||
|
|
||||||
@ -335,29 +334,18 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|||||||
* of the hw. Do it in both cases */
|
* of the hw. Do it in both cases */
|
||||||
flip_addr |= OFC_UPDATE;
|
flip_addr |= OFC_UPDATE;
|
||||||
|
|
||||||
|
BEGIN_LP_RING(6);
|
||||||
/* wait for overlay to go idle */
|
/* wait for overlay to go idle */
|
||||||
BEGIN_LP_RING(4);
|
|
||||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
||||||
OUT_RING(flip_addr);
|
OUT_RING(flip_addr);
|
||||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||||
OUT_RING(MI_NOOP);
|
|
||||||
ADVANCE_LP_RING();
|
|
||||||
|
|
||||||
ret = intel_overlay_do_wait_request(overlay, true,
|
|
||||||
SWITCH_OFF_STAGE_1);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* turn overlay off */
|
/* turn overlay off */
|
||||||
BEGIN_LP_RING(4);
|
|
||||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||||
OUT_RING(flip_addr);
|
OUT_RING(flip_addr);
|
||||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||||
OUT_RING(MI_NOOP);
|
|
||||||
ADVANCE_LP_RING();
|
ADVANCE_LP_RING();
|
||||||
|
|
||||||
return intel_overlay_do_wait_request(overlay, true,
|
return intel_overlay_do_wait_request(overlay, true, SWITCH_OFF);
|
||||||
SWITCH_OFF_STAGE_2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_overlay_off_tail(struct intel_overlay *overlay)
|
static void intel_overlay_off_tail(struct intel_overlay *overlay)
|
||||||
@ -383,9 +371,8 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
|
|||||||
bool interruptible)
|
bool interruptible)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = overlay->dev;
|
struct drm_device *dev = overlay->dev;
|
||||||
struct drm_gem_object *obj;
|
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
u32 flip_addr;
|
struct drm_gem_object *obj;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (overlay->hw_wedged == HW_WEDGED)
|
if (overlay->hw_wedged == HW_WEDGED)
|
||||||
@ -404,25 +391,10 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
|
|||||||
overlay->old_vid_bo = NULL;
|
overlay->old_vid_bo = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SWITCH_OFF_STAGE_1:
|
case SWITCH_OFF:
|
||||||
flip_addr = overlay->flip_addr;
|
|
||||||
flip_addr |= OFC_UPDATE;
|
|
||||||
|
|
||||||
BEGIN_LP_RING(4);
|
|
||||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
|
||||||
OUT_RING(flip_addr);
|
|
||||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
|
||||||
OUT_RING(MI_NOOP);
|
|
||||||
ADVANCE_LP_RING();
|
|
||||||
|
|
||||||
ret = intel_overlay_do_wait_request(overlay, interruptible,
|
|
||||||
SWITCH_OFF_STAGE_2);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
case SWITCH_OFF_STAGE_2:
|
|
||||||
intel_overlay_off_tail(overlay);
|
intel_overlay_off_tail(overlay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
|
BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user