[PATCH 34/36] drm/i915: Clean up intel_atomic_setup_scalers()
Ville Syrjala
ville.syrjala at linux.intel.com
Wed Dec 18 16:10:51 UTC 2019
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
intel_atomic_setup_scalers() is very hard to read.
Restructure it by making a clean separation between
the pfit and planes.
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/i915/display/intel_atomic.c | 135 ++++++++-----------
drivers/gpu/drm/i915/display/intel_atomic.h | 5 +-
drivers/gpu/drm/i915/display/intel_display.c | 3 +-
3 files changed, 62 insertions(+), 81 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 5ade7c1a6114..085351d59655 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -423,11 +423,37 @@ static void intel_plane_setup_scaler(struct intel_crtc_state *crtc_state,
plane->base.base.id, plane->base.name);
}
+static int skl_add_scaled_planes(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_scaler_state *scaler_state =
+ &crtc_state->scaler_state;
+ struct intel_plane *plane;
+
+ for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
+ int scaler_user = intel_plane_scaler_user(plane);
+ struct intel_plane_state *plane_state;
+
+ if ((scaler_state->scaler_users & BIT(scaler_user)) == 0)
+ continue;
+
+ plane_state = intel_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state))
+ return PTR_ERR(plane_state);
+
+ crtc_state->update_planes |= BIT(plane->id);
+ }
+
+ return 0;
+}
+
/**
* intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
- * @dev_priv: i915 device
- * @intel_crtc: intel crtc
- * @crtc_state: incoming crtc_state to validate and setup scalers
+ * @state: the atomic state
+ * @crtc: the crtc
*
* This function sets up scalers based on staged scaling requests for
* a @crtc and its planes. It is called from crtc level check path. If request
@@ -440,89 +466,46 @@ static void intel_plane_setup_scaler(struct intel_crtc_state *crtc_state,
* 0 - scalers were setup succesfully
* error code - otherwise
*/
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state)
+int intel_atomic_setup_scalers(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct drm_plane *plane = NULL;
- struct intel_plane *intel_plane;
- struct intel_plane_state *plane_state = NULL;
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_scaler_state *scaler_state =
- &crtc_state->scaler_state;
- struct drm_atomic_state *drm_state = crtc_state->uapi.state;
- struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
- int num_scalers_need;
+ &new_crtc_state->scaler_state;
+ struct intel_plane_state *new_plane_state;
+ struct intel_plane *plane;
+ int num_scaler_users = hweight32(scaler_state->scaler_users);
int i;
- num_scalers_need = hweight32(scaler_state->scaler_users);
+ if (num_scaler_users > crtc->num_scalers) {
+ DRM_DEBUG_KMS("[CRTC:%d:%s] Too many scaling requests %d > %d\n",
+ crtc->base.base.id, crtc->base.name,
+ num_scaler_users, crtc->num_scalers);
+ return -EINVAL;
+ }
- /*
- * High level flow:
- * - staged scaler requests are already in scaler_state->scaler_users
- * - check whether staged scaling requests can be supported
- * - add planes using scalers that aren't in current transaction
- * - assign scalers to requested users
- * - as part of plane commit, scalers will be committed
- * (i.e., either attached or detached) to respective planes in hw
- * - as part of crtc_commit, scaler will be either attached or detached
- * to crtc in hw
- */
+ if (skl_can_use_hq_scaler(old_crtc_state) !=
+ skl_can_use_hq_scaler(new_crtc_state)) {
+ int ret;
- /* fail if required scalers > available scalers */
- if (num_scalers_need > intel_crtc->num_scalers){
- DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
- num_scalers_need, intel_crtc->num_scalers);
- return -EINVAL;
+ ret = skl_add_scaled_planes(state, crtc);
+ if (ret)
+ return ret;
+
+ if (scaler_state->scaler_users & BIT(intel_crtc_scaler_user()))
+ new_crtc_state->update_pipe = true;
}
- /* walkthrough scaler_users bits and start assigning scalers */
- for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
- /* skip if scaler not required */
- if (!(scaler_state->scaler_users & (1 << i)))
+ intel_crtc_setup_scaler(new_crtc_state);
+
+ for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
+ if (plane->pipe != crtc->pipe)
continue;
- if (i == SKL_CRTC_INDEX) {
- intel_crtc_setup_scaler(crtc_state);
- } else {
- /* plane scaler case: assign as a plane scaler */
- /* find the plane that set the bit as scaler_user */
- plane = drm_state->planes[i].ptr;
-
- /*
- * to enable/disable hq mode, add planes that are using scaler
- * into this transaction
- */
- if (!plane) {
- struct drm_plane_state *state;
-
- /*
- * GLK+ scalers don't have a HQ mode so it
- * isn't necessary to change between HQ and dyn mode
- * on those platforms.
- */
- if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
- continue;
-
- plane = drm_plane_from_index(&dev_priv->drm, i);
- state = drm_atomic_get_plane_state(drm_state, plane);
- if (IS_ERR(state)) {
- DRM_DEBUG_KMS("Failed to add [PLANE:%d] to drm_state\n",
- plane->base.id);
- return PTR_ERR(state);
- }
- }
-
- intel_plane = to_intel_plane(plane);
-
- /* plane on different crtc cannot be a scaler user of this crtc */
- if (WARN_ON(intel_plane->pipe != intel_crtc->pipe))
- continue;
-
- plane_state = intel_atomic_get_new_plane_state(intel_state,
- intel_plane);
-
- intel_plane_setup_scaler(crtc_state, plane_state);
- }
+ intel_plane_setup_scaler(new_crtc_state, new_plane_state);
}
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
index 4cb565fd9c9b..bb8b1d7de72f 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic.h
@@ -46,9 +46,8 @@ struct intel_crtc_state *
intel_atomic_get_crtc_state(struct drm_atomic_state *state,
struct intel_crtc *crtc);
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state);
+int intel_atomic_setup_scalers(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
bool skl_can_use_hq_scaler(const struct intel_crtc_state *crtc_state);
int intel_plane_scaler_user(struct intel_plane *plane);
int intel_crtc_scaler_user(void);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index b38c2d8ffde2..99e90e8ef67e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -12335,8 +12335,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
if (mode_changed || crtc_state->update_pipe)
ret = skl_update_scaler_crtc(crtc_state);
if (!ret)
- ret = intel_atomic_setup_scalers(dev_priv, crtc,
- crtc_state);
+ ret = intel_atomic_setup_scalers(state, crtc);
}
if (HAS_IPS(dev_priv))
--
2.23.0
More information about the Intel-gfx-trybot
mailing list