From 62ef0dd3cc0c217c3d58a1e92577c66c08598f7b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 20 Sep 2018 12:27:06 +0200 Subject: drm/i915: Unconditionally clear plane visibility, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to assume the plane has been visible before, even if no CRTC is assigned to the plane. This is because when enabling a nv12 plane on gen11, we will have to enable an extra plane and make it visible by marking it in crtc_state->active_planes for intel_update_planes_on_crtc(). Additionally, clear visible flag in intel_plane_atomic_check, in case we ever hit a bug with visibility. Our code implicitly assumes that plane_state->visible is only true when crtc and fb are set, so we will either null deref in intel_fbc_choose_crtc() or do something bad during the actual commit which cares even more. Changes since v1: - Unconditionally clear crtc_state->active_planes as well. - Reword commit message, since this is now a preparation patch for NV12 Y / UV plane linking. Signed-off-by: Maarten Lankhorst [mlankhorst: Clear nv12_planes in the beginning as well, clarify commit message] Reviewed-by: Matt Roper Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180920102711.4184-4-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index aabebe0d2e9b..59f6ab60904d 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -117,10 +117,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 +132,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 +152,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; -- cgit From 6c246b81f9380855b13433d1d8fbd67ff7f67583 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 20 Sep 2018 12:27:08 +0200 Subject: drm/i915: Replace call to commit_planes_on_crtc with internal update, v2. drm_atomic_helper_commit_planes_on_crtc calls begin_commit, then plane_update hooks, then flush_commit. Because we keep our own visibility tracking through plane_state->visible there's no need to rely on the atomic hooks for this. By explicitly writing our own helper, we can update visible planes as needed, which is useful to make NV12 support work as intended. Changes since v1: - Reword commit message. (Matt Roper) - Rename to intel_update_planes_on_crtc(). (Matt) Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20180920102711.4184-6-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 41 +++++++++++++++++-------------- drivers/gpu/drm/i915/intel_display.c | 10 +++++--- drivers/gpu/drm/i915/intel_drv.h | 4 +++ 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 59f6ab60904d..984bc1f26625 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -165,29 +165,33 @@ 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; + 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; - 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)); + 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; - trace_intel_update_plane(plane, - to_intel_crtc(crtc)); + if (new_plane_state->base.visible) { + trace_intel_update_plane(&plane->base, crtc); - intel_plane->update_plane(intel_plane, - new_crtc_state, new_plane_state); - } else { - trace_intel_disable_plane(plane, - to_intel_crtc(crtc)); + plane->update_plane(plane, new_crtc_state, new_plane_state); + } else { + trace_intel_disable_plane(&plane->base, crtc); - intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc)); + plane->disable_plane(plane, crtc); + } } } @@ -195,7 +199,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, }; /** diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c0e431c59c4f..ac1e0db4cb16 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10812,8 +10812,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs intel_helper_funcs = { - .atomic_begin = intel_begin_crtc_commit, - .atomic_flush = intel_finish_crtc_commit, .atomic_check = intel_crtc_atomic_check, }; @@ -12482,6 +12480,7 @@ static void intel_update_crtc(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *old_intel_cstate = to_intel_crtc_state(old_crtc_state); struct intel_crtc_state *pipe_config = to_intel_crtc_state(new_crtc_state); bool modeset = needs_modeset(new_crtc_state); struct intel_plane_state *new_plane_state = @@ -12502,7 +12501,12 @@ static void intel_update_crtc(struct drm_crtc *crtc, if (new_plane_state) intel_fbc_enable(intel_crtc, pipe_config, new_plane_state); - drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); + intel_begin_crtc_commit(crtc, old_crtc_state); + + intel_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc, + old_intel_cstate, pipe_config); + + intel_finish_crtc_commit(crtc, old_crtc_state); } static void intel_update_crtcs(struct drm_atomic_state *state) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 521d6aaa2d44..07707728e4b6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -2186,6 +2186,10 @@ struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; +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); int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *crtc_state, const struct intel_plane_state *old_plane_state, -- cgit From 2d72dc8b7c15e4a83b4f7c6976feaf96e7e3e63e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Oct 2018 15:58:13 +0300 Subject: drm/i915: Move plane_state->scaler_id initialization into intel_create_plane_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in having each caller of intel_create_plane_state() initialize the scaler_id to -1. Instead just do it in intel_create_plane_state(). Previously we left scaler_id at 0 for pre-SKL platforms, but I can't see how initializing it to -1 always would cause any harm. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Reviewed-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20181005125817.22576-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 1 + drivers/gpu/drm/i915/intel_display.c | 5 ----- drivers/gpu/drm/i915/intel_sprite.c | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 984bc1f26625..b957ad63cd87 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -56,6 +56,7 @@ intel_create_plane_state(struct drm_plane *plane) state->base.plane = plane; state->base.rotation = DRM_MODE_ROTATE_0; + state->scaler_id = -1; return state; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c3f434e49a5b..d2246ec8a87e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13783,8 +13783,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->base.state = &state->base; - if (INTEL_GEN(dev_priv) >= 9) - state->scaler_id = -1; primary->pipe = pipe; /* * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS @@ -14006,9 +14004,6 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180); - if (INTEL_GEN(dev_priv) >= 9) - state->scaler_id = -1; - drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); return cursor; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0481f8249fee..5860530289b5 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1821,8 +1821,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->base.state = &state->base; if (INTEL_GEN(dev_priv) >= 9) { - state->scaler_id = -1; - intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane); -- cgit From 1ab554b0099b655141c47ec5cd05d126eaed4868 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 22 Oct 2018 15:51:52 +0200 Subject: drm/i915/gen11: Link nv12 Y and UV planes in the atomic state, v5. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make NV12 working on icl, we need to update 2 planes simultaneously. I've chosen to do this in the CRTC step after plane validation is done, so we know what planes are (in)visible. The linked Y plane will get updated in intel_plane_update_planes_on_crtc(), by the call to update_slave, which gets the master's plane_state as argument. The link requires both planes for atomic_update to work, so make sure skl_ddb_add_affected_planes() adds both states. Changes since v1: - Introduce icl_is_nv12_y_plane(), instead of hardcoding sprite numbers. - Put all the state updating login in intel_plane_atomic_check_with_state(). - Clean up changes in intel_plane_atomic_check(). Changes since v2: - Fix intel_atomic_get_old_plane_state() to actually return old state. - Move visibility changes to preparation patch. - Only try to find a Y plane on gen11, earlier platforms only require a single plane. Changes since v3: - Fix checkpatch warning about to_intel_crtc() usage. - Add affected planes from icl_add_linked_planes() before check_planes(), it's a cleaner way to do this. (Ville) Changes since v4: - Clear plane links in icl_check_nv12_planes() for clarity. - Only pass crtc_state to icl_check_nv12_planes(). - Use for_each_new_intel_plane_in_state() in icl_check_nv12_planes. - Rename aux to linked. (Ville) Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181022135152.15324-1-maarten.lankhorst@linux.intel.com [mlankhorst: Change bool slave to u32, to satisfy checkpatch] [mlankhorst: Add WARN_ON's based on Ville's suggestion] --- drivers/gpu/drm/i915/intel_atomic_plane.c | 19 ++++++ drivers/gpu/drm/i915/intel_display.c | 98 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 53 +++++++++++++++++ drivers/gpu/drm/i915/intel_pm.c | 12 +++- 4 files changed, 181 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index b957ad63cd87..7d3685075201 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -188,6 +188,25 @@ void intel_update_planes_on_crtc(struct intel_atomic_state *old_state, 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); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 969d22ca8dcd..0224221ee214 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10713,6 +10713,98 @@ static bool check_single_encoder_cloning(struct drm_atomic_state *state, return true; } +static int icl_add_linked_planes(struct intel_atomic_state *state) +{ + struct intel_plane *plane, *linked; + struct intel_plane_state *plane_state, *linked_plane_state; + int i; + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + linked = plane_state->linked_plane; + + if (!linked) + continue; + + linked_plane_state = intel_atomic_get_plane_state(state, linked); + if (IS_ERR(linked_plane_state)) + return PTR_ERR(linked_plane_state); + + WARN_ON(linked_plane_state->linked_plane != plane); + WARN_ON(linked_plane_state->slave == plane_state->slave); + } + + return 0; +} + +static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state); + struct intel_plane *plane, *linked; + struct intel_plane_state *plane_state; + int i; + + if (INTEL_GEN(dev_priv) < 11) + return 0; + + /* + * Destroy all old plane links and make the slave plane invisible + * in the crtc_state->active_planes mask. + */ + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane->pipe != crtc->pipe || !plane_state->linked_plane) + continue; + + plane_state->linked_plane = NULL; + if (plane_state->slave && !plane_state->base.visible) + crtc_state->active_planes &= ~BIT(plane->id); + + plane_state->slave = false; + } + + if (!crtc_state->nv12_planes) + return 0; + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + struct intel_plane_state *linked_state = NULL; + + if (plane->pipe != crtc->pipe || + !(crtc_state->nv12_planes & BIT(plane->id))) + continue; + + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, linked) { + if (!icl_is_nv12_y_plane(linked->id)) + continue; + + if (crtc_state->active_planes & BIT(linked->id)) + continue; + + linked_state = intel_atomic_get_plane_state(state, linked); + if (IS_ERR(linked_state)) + return PTR_ERR(linked_state); + + break; + } + + if (!linked_state) { + DRM_DEBUG_KMS("Need %d free Y planes for NV12\n", + hweight8(crtc_state->nv12_planes)); + + return -EINVAL; + } + + plane_state->linked_plane = linked; + + linked_state->slave = true; + linked_state->linked_plane = plane; + crtc_state->active_planes |= BIT(linked->id); + DRM_DEBUG_KMS("Using %s as Y plane for %s\n", linked->base.name, plane->base.name); + } + + return 0; +} + static int intel_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) { @@ -10784,6 +10876,8 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, if (mode_changed) ret = skl_update_scaler_crtc(pipe_config); + if (!ret) + ret = icl_check_nv12_planes(pipe_config); if (!ret) ret = skl_check_pipe_max_pixel_rate(intel_crtc, pipe_config); @@ -12450,6 +12544,10 @@ static int intel_atomic_check(struct drm_device *dev, intel_state->cdclk.logical = dev_priv->cdclk.logical; } + ret = icl_add_linked_planes(intel_state); + if (ret) + return ret; + ret = drm_atomic_helper_check_planes(dev, state); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1adcdcc6202b..45e9bacc1eaa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -539,6 +539,26 @@ struct intel_plane_state { */ int scaler_id; + /* + * linked_plane: + * + * ICL planar formats require 2 planes that are updated as pairs. + * This member is used to make sure the other plane is also updated + * when required, and for update_slave() to find the correct + * plane_state to pass as argument. + */ + struct intel_plane *linked_plane; + + /* + * slave: + * If set don't update use the linked plane's state for updating + * this plane during atomic commit with the update_slave() callback. + * + * It's also used by the watermark code to ignore wm calculations on + * this plane. They're calculated by the linked plane's wm code. + */ + u32 slave; + struct drm_intel_sprite_colorkey ckey; }; @@ -983,6 +1003,9 @@ struct intel_plane { void (*update_plane)(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); + void (*update_slave)(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); void (*disable_plane)(struct intel_plane *plane, struct intel_crtc *crtc); bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe); @@ -1357,6 +1380,27 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } +static inline struct intel_plane_state * +intel_atomic_get_plane_state(struct intel_atomic_state *state, + struct intel_plane *plane) +{ + struct drm_plane_state *ret = + drm_atomic_get_plane_state(&state->base, &plane->base); + + if (IS_ERR(ret)) + return ERR_CAST(ret); + + return to_intel_plane_state(ret); +} + +static inline struct intel_plane_state * +intel_atomic_get_old_plane_state(struct intel_atomic_state *state, + struct intel_plane *plane) +{ + return to_intel_plane_state(drm_atomic_get_old_plane_state(&state->base, + &plane->base)); +} + static inline struct intel_plane_state * intel_atomic_get_new_plane_state(struct intel_atomic_state *state, struct intel_plane *plane) @@ -2165,6 +2209,15 @@ struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id); +static inline bool icl_is_nv12_y_plane(enum plane_id id) +{ + /* Don't need to do a gen check, these planes are only available on gen11 */ + if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5) + return true; + + return false; +} + /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f42b8c319046..9ba39a9c7d1c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5153,11 +5153,12 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; - struct drm_plane_state *plane_state; struct drm_plane *plane; enum pipe pipe = intel_crtc->pipe; drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { + struct drm_plane_state *plane_state; + struct intel_plane *linked; enum plane_id plane_id = to_intel_plane(plane)->id; if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id], @@ -5169,6 +5170,15 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) return PTR_ERR(plane_state); + + /* Make sure linked plane is updated too */ + linked = to_intel_plane_state(plane_state)->linked_plane; + if (!linked) + continue; + + plane_state = drm_atomic_get_plane_state(state, &linked->base); + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); } return 0; -- cgit From 87b94026ff31b90a382d368123d31b2c4888069b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 13 Nov 2018 10:28:04 +0100 Subject: drm/i915: Fix plane allocation/free functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use intel_plane_destroy_state in intel_plane_free to free the state. Also fix intel_plane_alloc() to use __drm_atomic_helper_plane_reset(), to get sane defaults from the atomic core. This is needed to get the correct alpha value and blend mode from the core, and any new default values added from new properties. Signed-off-by: Maarten Lankhorst Reported-by: Ville Syrjälä Cc: Ville Syrjälä Fixes: b20815255693 ("drm/i915: Add plane alpha blending support, v2.") [mlankhorst: Update commit description to mention alpha blend support] Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181113092804.13304-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 40 ++++++++++++++++--------------- drivers/gpu/drm/i915/intel_drv.h | 5 ++-- drivers/gpu/drm/i915/intel_sprite.c | 29 ---------------------- 3 files changed, 23 insertions(+), 51 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_atomic_plane.c') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 7d3685075201..905f8ef3ba4f 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -36,29 +36,31 @@ #include #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; - state->scaler_id = -1; + 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); } /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 18b419f7f7fe..f575ba2a59da 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -2219,8 +2219,6 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); int intel_plane_check_stride(const struct intel_plane_state *plane_state); int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); int chv_plane_check_rotation(const struct intel_plane_state *plane_state); -struct intel_plane *intel_plane_alloc(void); -void intel_plane_free(struct intel_plane *plane); struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id); @@ -2282,7 +2280,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, struct intel_crtc_state *crtc_state); /* intel_atomic_plane.c */ -struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane); +struct intel_plane *intel_plane_alloc(void); +void intel_plane_free(struct intel_plane *plane); struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5e0f7b575a50..abe193815ccc 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1983,35 +1983,6 @@ static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, plane_id == PLANE_SPRITE0); } -struct intel_plane *intel_plane_alloc(void) -{ - struct intel_plane_state *plane_state; - struct intel_plane *plane; - - plane = kzalloc(sizeof(*plane), GFP_KERNEL); - if (!plane) - return ERR_PTR(-ENOMEM); - - plane_state = intel_create_plane_state(&plane->base); - if (!plane_state) { - kfree(plane); - return ERR_PTR(-ENOMEM); - } - - plane->base.state = &plane_state->base; - - return plane; -} - -void intel_plane_free(struct intel_plane *plane) -{ - struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - - kfree(plane_state); - kfree(plane); -} - struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id) -- cgit