Modify skylake panel fitting implementation to use shared scalers.

v2:
-added log message in pfit enable/disable (me)
-read crtc scaler state from hw state (Daniel)
-replaced both skylake_pfit_enable and disable with skylake_pfit_update (me)
-added scaler id check to intel_pipe_config_compare (Daniel)

Signed-off-by: Chandra Konduru <chandra.kond...@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   81 ++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index c393480..16dcd31 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4189,16 +4189,39 @@ static void cpt_verify_modeset(struct drm_device *dev, 
int pipe)
        }
 }
 
-static void skylake_pfit_enable(struct intel_crtc *crtc)
+static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
+       struct intel_crtc_scaler_state *scaler_state =
+               &crtc->config->scaler_state;
+
+       DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
+
+       /* To update pfit, first update scaler state */
+       skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable);
+       intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
+       skl_detach_scaler(&crtc->base, NULL);
+       if (!enable)
+               return;
 
        if (crtc->config->pch_pfit.enabled) {
-               I915_WRITE(PS_CTL(pipe), PS_ENABLE);
-               I915_WRITE(PS_WIN_POS(pipe), crtc->config->pch_pfit.pos);
-               I915_WRITE(PS_WIN_SZ(pipe), crtc->config->pch_pfit.size);
+               int id;
+
+               if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
+                       DRM_ERROR("Requesting pfit without getting a scaler 
first\n");
+                       return;
+               }
+
+               id = scaler_state->scaler_id;
+               I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
+                       scaler_state->scalers[id].mode |
+                       scaler_state->scalers[id].filter);
+               I915_WRITE(SKL_PS_WIN_POS(pipe, id), 
crtc->config->pch_pfit.pos);
+               I915_WRITE(SKL_PS_WIN_SZ(pipe, id), 
crtc->config->pch_pfit.size);
+
+               DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", 
crtc->config, id);
        }
 }
 
@@ -4628,7 +4651,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        intel_ddi_enable_pipe_clock(intel_crtc);
 
        if (IS_SKYLAKE(dev))
-               skylake_pfit_enable(intel_crtc);
+               skylake_pfit_update(intel_crtc, 1);
        else
                ironlake_pfit_enable(intel_crtc);
 
@@ -4664,21 +4687,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_enable_planes(crtc);
 }
 
-static void skylake_pfit_disable(struct intel_crtc *crtc)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe = crtc->pipe;
-
-       /* To avoid upsetting the power well on haswell only disable the pfit if
-        * it's in use. The hw state code will make sure we get this right. */
-       if (crtc->config->pch_pfit.enabled) {
-               I915_WRITE(PS_CTL(pipe), 0);
-               I915_WRITE(PS_WIN_POS(pipe), 0);
-               I915_WRITE(PS_WIN_SZ(pipe), 0);
-       }
-}
-
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
@@ -4791,7 +4799,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
        if (IS_SKYLAKE(dev))
-               skylake_pfit_disable(intel_crtc);
+               skylake_pfit_update(intel_crtc, 0);
        else
                ironlake_pfit_disable(intel_crtc);
 
@@ -7955,14 +7963,28 @@ static void skylake_get_pfit_config(struct intel_crtc 
*crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t tmp;
+       struct intel_crtc_scaler_state *scaler_state = 
&pipe_config->scaler_state;
+       uint32_t ps_ctrl = 0;
+       int id = -1;
+       int i;
 
-       tmp = I915_READ(PS_CTL(crtc->pipe));
+       /* find scaler attached to this pipe */
+       for (i = 0; i < scaler_state->num_scalers; i++) {
+               ps_ctrl = I915_READ(SKL_PS_CTRL(crtc->pipe, i));
+               if (ps_ctrl & PS_SCALER_EN && !(ps_ctrl & PS_PLANE_SEL_MASK)) {
+                       id = i;
+                       pipe_config->pch_pfit.enabled = true;
+                       pipe_config->pch_pfit.pos = 
I915_READ(SKL_PS_WIN_POS(crtc->pipe, i));
+                       pipe_config->pch_pfit.size = 
I915_READ(SKL_PS_WIN_SZ(crtc->pipe, i));
+                       break;
+               }
+       }
 
-       if (tmp & PS_ENABLE) {
-               pipe_config->pch_pfit.enabled = true;
-               pipe_config->pch_pfit.pos = I915_READ(PS_WIN_POS(crtc->pipe));
-               pipe_config->pch_pfit.size = I915_READ(PS_WIN_SZ(crtc->pipe));
+       scaler_state->scaler_id = id;
+       if (id >= 0) {
+               scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
+       } else {
+               scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
        }
 }
 
@@ -8607,6 +8629,9 @@ static bool haswell_get_pipe_config(struct intel_crtc 
*crtc,
                        skylake_get_pfit_config(crtc, pipe_config);
                else
                        ironlake_get_pfit_config(crtc, pipe_config);
+       } else {
+               pipe_config->scaler_state.scaler_id = -1;
+               pipe_config->scaler_state.scaler_users &= ~(1 << 
SKL_CRTC_INDEX);
        }
 
        if (IS_HASWELL(dev))
@@ -11112,6 +11137,8 @@ intel_pipe_config_compare(struct drm_device *dev,
                PIPE_CONF_CHECK_I(pch_pfit.size);
        }
 
+       PIPE_CONF_CHECK_I(scaler_state.scaler_id);
+
        /* BDW+ don't expose a synchronous way to read the state */
        if (IS_HASWELL(dev))
                PIPE_CONF_CHECK_I(ips_enabled);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to