diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_atomic_plane.c | 118 |
1 files changed, 72 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index aabebe0d2e9b..905f8ef3ba4f 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -36,28 +36,31 @@ #include <drm/drm_plane_helper.h> #include "intel_drv.h" -/** - * intel_create_plane_state - create plane state object - * @plane: drm plane - * - * Allocates a fresh plane state for the given plane and sets some of - * the state values to sensible initial values. - * - * Returns: A newly allocated plane state, or NULL on failure - */ -struct intel_plane_state * -intel_create_plane_state(struct drm_plane *plane) +struct intel_plane *intel_plane_alloc(void) { - struct intel_plane_state *state; + struct intel_plane_state *plane_state; + struct intel_plane *plane; - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (!state) - return NULL; + plane = kzalloc(sizeof(*plane), GFP_KERNEL); + if (!plane) + return ERR_PTR(-ENOMEM); - state->base.plane = plane; - state->base.rotation = DRM_MODE_ROTATE_0; + plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); + if (!plane_state) { + kfree(plane); + return ERR_PTR(-ENOMEM); + } - return state; + __drm_atomic_helper_plane_reset(&plane->base, &plane_state->base); + plane_state->scaler_id = -1; + + return plane; +} + +void intel_plane_free(struct intel_plane *plane) +{ + intel_plane_destroy_state(&plane->base, plane->base.state); + kfree(plane); } /** @@ -117,10 +120,14 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ struct intel_plane *intel_plane = to_intel_plane(plane); int ret; + crtc_state->active_planes &= ~BIT(intel_plane->id); + crtc_state->nv12_planes &= ~BIT(intel_plane->id); + intel_state->base.visible = false; + + /* If this is a cursor plane, no further checks are needed. */ if (!intel_state->base.crtc && !old_plane_state->base.crtc) return 0; - intel_state->base.visible = false; ret = intel_plane->check_plane(crtc_state, intel_state); if (ret) return ret; @@ -128,13 +135,9 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ /* FIXME pre-g4x don't work like this */ if (state->visible) crtc_state->active_planes |= BIT(intel_plane->id); - else - crtc_state->active_planes &= ~BIT(intel_plane->id); if (state->visible && state->fb->format->format == DRM_FORMAT_NV12) crtc_state->nv12_planes |= BIT(intel_plane->id); - else - crtc_state->nv12_planes &= ~BIT(intel_plane->id); return intel_plane_atomic_calc_changes(old_crtc_state, &crtc_state->base, @@ -152,6 +155,7 @@ static int intel_plane_atomic_check(struct drm_plane *plane, const struct drm_crtc_state *old_crtc_state; struct drm_crtc_state *new_crtc_state; + new_plane_state->visible = false; if (!crtc) return 0; @@ -164,29 +168,52 @@ static int intel_plane_atomic_check(struct drm_plane *plane, to_intel_plane_state(new_plane_state)); } -static void intel_plane_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_state) +void intel_update_planes_on_crtc(struct intel_atomic_state *old_state, + struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) { - struct intel_atomic_state *state = to_intel_atomic_state(old_state->state); - struct intel_plane *intel_plane = to_intel_plane(plane); - const struct intel_plane_state *new_plane_state = - intel_atomic_get_new_plane_state(state, intel_plane); - struct drm_crtc *crtc = new_plane_state->base.crtc ?: old_state->crtc; - - if (new_plane_state->base.visible) { - const struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(state, to_intel_crtc(crtc)); - - trace_intel_update_plane(plane, - to_intel_crtc(crtc)); - - intel_plane->update_plane(intel_plane, - new_crtc_state, new_plane_state); - } else { - trace_intel_disable_plane(plane, - to_intel_crtc(crtc)); - - intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc)); + struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + u32 update_mask; + int i; + + update_mask = old_crtc_state->active_planes; + update_mask |= new_crtc_state->active_planes; + + for_each_new_intel_plane_in_state(old_state, plane, new_plane_state, i) { + if (crtc->pipe != plane->pipe || + !(update_mask & BIT(plane->id))) + continue; + + if (new_plane_state->base.visible) { + trace_intel_update_plane(&plane->base, crtc); + + plane->update_plane(plane, new_crtc_state, new_plane_state); + } else if (new_plane_state->slave) { + struct intel_plane *master = + new_plane_state->linked_plane; + + /* + * We update the slave plane from this function because + * programming it from the master plane's update_plane + * callback runs into issues when the Y plane is + * reassigned, disabled or used by a different plane. + * + * The slave plane is updated with the master plane's + * plane_state. + */ + new_plane_state = + intel_atomic_get_new_plane_state(old_state, master); + + trace_intel_update_plane(&plane->base, crtc); + + plane->update_slave(plane, new_crtc_state, new_plane_state); + } else { + trace_intel_disable_plane(&plane->base, crtc); + + plane->disable_plane(plane, crtc); + } } } @@ -194,7 +221,6 @@ const struct drm_plane_helper_funcs intel_plane_helper_funcs = { .prepare_fb = intel_prepare_plane_fb, .cleanup_fb = intel_cleanup_plane_fb, .atomic_check = intel_plane_atomic_check, - .atomic_update = intel_plane_atomic_update, }; /** |