[PATCH v2 04/20] drm/i915: Do not update pfit state when toggling crtc enabled.

Maarten Lankhorst
2015-07-07T07:08:48Z

This must be done in advance, and during crtc_disable all scalers
can be force disabled.

This means intel_atomic_setup_scalers is only called in 1 place now,
during crtc_check.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
drivers/gpu/drm/i915/intel_atomic.c | 14 ++------
drivers/gpu/drm/i915/intel_display.c | 68 +++++++++++++++++++++++-------------
drivers/gpu/drm/i915/intel_dp.c | 2 +-
drivers/gpu/drm/i915/intel_drv.h | 2 +-
4 files changed, 48 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 0aeced82201e..429677a111d5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -272,17 +272,12 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
struct drm_plane *plane = NULL;
struct intel_plane *intel_plane;
struct intel_plane_state *plane_state = NULL;
- struct intel_crtc_scaler_state *scaler_state;
- struct drm_atomic_state *drm_state;
+ struct intel_crtc_scaler_state *scaler_state =
+ &crtc_state->scaler_state;
+ struct drm_atomic_state *drm_state = crtc_state->base.state;
int num_scalers_need;
int i, j;

- if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state)
- return 0;
-
- scaler_state = &crtc_state->scaler_state;
- drm_state = crtc_state->base.state;
-
num_scalers_need = hweight32(scaler_state->scaler_users);
DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n",
crtc_state, num_scalers_need, intel_crtc->num_scalers,
@@ -327,9 +322,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
name = "PLANE";
idx = plane->base.id;

- if (!drm_state)
- continue;
-
/* plane scaler case: assign as a plane scaler */
/* find the plane that set the bit as scaler_user */
plane = drm_state->planes[i];
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4d1a474e0d13..8cd3a7eb1e30 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2909,29 +2909,32 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
return i915_gem_obj_ggtt_offset_view(obj, view);
}

+static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
+{
+ struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, id), 0);
+ I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, id), 0);
+ I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0);
+ DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n",
+ intel_crtc->base.base.id, intel_crtc->pipe, id);
+}
+
/*
* This function detaches (aka. unbinds) unused scalers in hardware
*/
static void skl_detach_scalers(struct intel_crtc *intel_crtc)
{
- struct drm_device *dev;
- struct drm_i915_private *dev_priv;
struct intel_crtc_scaler_state *scaler_state;
int i;

- dev = intel_crtc->base.dev;
- dev_priv = dev->dev_private;
scaler_state = &intel_crtc->config->scaler_state;

/* loop through and disable scalers that aren't in use */
for (i = 0; i < intel_crtc->num_scalers; i++) {
- if (!scaler_state->scalers[i].in_use) {
- I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, i), 0);
- I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, i), 0);
- I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, i), 0);
- DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n",
- intel_crtc->base.base.id, intel_crtc->pipe, i);
- }
+ if (!scaler_state->scalers[i].in_use)
+ skl_detach_scaler(intel_crtc, i);
}
}

@@ -4362,13 +4365,12 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
* skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
*
* @state: crtc's scaler state
- * @force_detach: whether to forcibly disable scaler
*
* Return
* 0 - scaler_usage updated successfully
* error - requested scaling cannot be supported or other error condition
*/
-int skl_update_scaler_crtc(struct intel_crtc_state *state, int force_detach)
+int skl_update_scaler_crtc(struct intel_crtc_state *state)
{
struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
struct drm_display_mode *adjusted_mode =
@@ -4377,7 +4379,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state, int force_detach)
DRM_DEBUG_KMS("Updating scaler for [CRTC:%i] scaler_user index %u.%u\n",
intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);

- return skl_update_scaler(state, force_detach, SKL_CRTC_INDEX,
+ return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
&state->scaler_state.scaler_id, DRM_ROTATE_0,
state->pipe_src_w, state->pipe_src_h,
adjusted_mode->hdisplay, adjusted_mode->vdisplay);
@@ -4451,7 +4453,15 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
return 0;
}

-static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
+static void skylake_scaler_disable(struct intel_crtc *crtc)
+{
+ int i;
+
+ for (i = 0; i < crtc->num_scalers; i++)
+ skl_detach_scaler(crtc, i);
+}
+
+static void skylake_pfit_enable(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4461,13 +4471,6 @@ static void skylake_pfit_update(struct intel_crtc *crtc, int enable)

DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);

- /* To update pfit, first update scaler state */
- skl_update_scaler_crtc(crtc->config, !enable);
- intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
- skl_detach_scalers(crtc);
- if (!enable)
- return;
-
if (crtc->config->pch_pfit.enabled) {
int id;

@@ -4941,7 +4944,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_ddi_enable_pipe_clock(intel_crtc);

if (INTEL_INFO(dev)->gen == 9)
- skylake_pfit_update(intel_crtc, 1);
+ skylake_pfit_enable(intel_crtc);
else if (INTEL_INFO(dev)->gen < 9)
ironlake_pfit_enable(intel_crtc);
else
@@ -5075,7 +5078,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);

if (INTEL_INFO(dev)->gen == 9)
- skylake_pfit_update(intel_crtc, 0);
+ skylake_scaler_disable(intel_crtc);
else if (INTEL_INFO(dev)->gen < 9)
ironlake_pfit_disable(intel_crtc);
else
@@ -11823,7 +11826,17 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
return ret;
}

- return intel_atomic_setup_scalers(dev, intel_crtc, pipe_config);
+ ret = 0;
+ if (INTEL_INFO(dev)->gen >= 9) {
+ if (mode_changed)
+ ret = skl_update_scaler_crtc(pipe_config);
+
+ if (!ret)
+ ret = intel_atomic_setup_scalers(dev, intel_crtc,
+ pipe_config);
+ }
+
+ return ret;
}

static const struct drm_crtc_helper_funcs intel_helper_funcs = {
@@ -15327,6 +15340,11 @@ static void readout_plane_state(struct intel_crtc *crtc,
continue;

drm_plane_state = p->base.state;
+
+ /* Plane scaler state is not touched here. The first atomic
+ * commit will restore all plane scalers to its old state.
+ */
+
if (active && p->base.type == DRM_PLANE_TYPE_PRIMARY) {
visible = primary_get_hw_state(crtc);
to_intel_plane_state(drm_plane_state)->visible = visible;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index fcc64e5ef9c8..f1b9f939b435 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1384,7 +1384,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,

if (INTEL_INFO(dev)->gen >= 9) {
int ret;
- ret = skl_update_scaler_crtc(pipe_config, 0);
+ ret = skl_update_scaler_crtc(pipe_config);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 63d7d32e6123..2ed618f78fe6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1152,7 +1152,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);

-int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state, int force_detach);
+int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);

unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
--
2.1.0