Commit 176c0b55 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Joonas Lahtinen

drm/i915: Check async flip capability early on

Since the async flip state check is done very late and
thus it can see potentially all the planes in the state
(due to the wm/ddb optimization) we need to move the
"can the requested plane do async flips at all?" check
much earlier. For this purpose we introduce
intel_async_flip_check_uapi() that gets called early during
the atomic check.

And for good measure we'll throw in a couple of basic checks:
- is the crtc active?
- was a modeset flagged?
- is+was the plane enabled?
Though atm all of those should be guaranteed by the fact
that the async flip can only be requested through the legacy
page flip ioctl.

Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Fixes: c3639f3b ("drm/i915: Use wm0 only during async flips for DG2")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220214105532.13049-3-ville.syrjala@linux.intel.comReviewed-by: default avatarStanislav Lisovskiy <stanislav.lisovskiy@intel.com>
(cherry picked from commit b0b2bed2)
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 117f5bb3
......@@ -7401,7 +7401,7 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state,
* Correspondingly, support is currently added for primary plane only.
*
* Async flip can only change the plane surface address, so anything else
* changing is rejected from the intel_atomic_check_async() function.
* changing is rejected from the intel_async_flip_check_hw() function.
* Once this check is cleared, flip done interrupt is enabled using
* the intel_crtc_enable_flip_done() function.
*
......@@ -7411,7 +7411,65 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state,
* correspond to the last vblank and have no relation to the actual time when
* the flip done event was sent.
*/
static int intel_atomic_check_async(struct intel_atomic_state *state, struct intel_crtc *crtc)
static int intel_async_flip_check_uapi(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_plane_state *old_plane_state;
struct intel_plane_state *new_plane_state;
struct intel_plane *plane;
int i;
if (!new_crtc_state->uapi.async_flip)
return 0;
if (!new_crtc_state->uapi.active) {
drm_dbg_kms(&i915->drm,
"[CRTC:%d:%s] not active\n",
crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
if (intel_crtc_needs_modeset(new_crtc_state)) {
drm_dbg_kms(&i915->drm,
"[CRTC:%d:%s] modeset required\n",
crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
if (plane->pipe != crtc->pipe)
continue;
/*
* TODO: Async flip is only supported through the page flip IOCTL
* as of now. So support currently added for primary plane only.
* Support for other planes on platforms on which supports
* this(vlv/chv and icl+) should be added when async flip is
* enabled in the atomic IOCTL path.
*/
if (!plane->async_flip) {
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] async flip not supported\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (!old_plane_state->uapi.fb || !new_plane_state->uapi.fb) {
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] no old or new framebuffer\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
}
return 0;
}
static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state, *new_crtc_state;
......@@ -7422,6 +7480,9 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int
old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state->uapi.async_flip)
return 0;
if (intel_crtc_needs_modeset(new_crtc_state)) {
drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n");
return -EINVAL;
......@@ -7616,6 +7677,12 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
ret = intel_async_flip_check_uapi(state, crtc);
if (ret)
return ret;
}
ret = intel_bigjoiner_add_affected_crtcs(state);
if (ret)
goto fail;
......@@ -7772,11 +7839,9 @@ static int intel_atomic_check(struct drm_device *dev,
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (new_crtc_state->uapi.async_flip) {
ret = intel_atomic_check_async(state, crtc);
if (ret)
goto fail;
}
ret = intel_async_flip_check_hw(state, crtc);
if (ret)
goto fail;
if (!intel_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->update_pipe)
......
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