Skylake style watermarks program the UV parameters into wm->uv_wm,
and have a separate DDB allocation for UV blocks into the same plane.

Gen11 watermarks have a separate plane for Y and UV, with separate
mechanisms. The simplest way to make it work is to keep the current
way of programming watermarks and calculate the Y and UV plane
watermarks from the master plane.

Signed-off-by: Maarten Lankhorst <[email protected]>
---
 drivers/gpu/drm/i915/intel_pm.c | 122 +++++++++++++++++++-------------
 1 file changed, 72 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d76d93452137..b85403798593 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3945,14 +3945,9 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private 
*dev_priv,
                                      val & PLANE_CTL_ALPHA_MASK);
 
        val = I915_READ(PLANE_BUF_CFG(pipe, plane_id));
-       /*
-        * FIXME: add proper NV12 support for ICL. Avoid reading unclaimed
-        * registers for now.
-        */
-       if (INTEL_GEN(dev_priv) < 11)
+       if (fourcc == DRM_FORMAT_NV12 && INTEL_GEN(dev_priv) < 11) {
                val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id));
 
-       if (fourcc == DRM_FORMAT_NV12) {
                skl_ddb_entry_init_from_hw(dev_priv,
                                           &ddb->plane[pipe][plane_id], val2);
                skl_ddb_entry_init_from_hw(dev_priv,
@@ -4207,19 +4202,29 @@ skl_get_total_relative_data_rate(struct 
intel_crtc_state *intel_cstate,
        drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) {
                enum plane_id plane_id = to_intel_plane(plane)->id;
                unsigned int rate;
+               struct intel_plane_state *plane_state =
+                       to_intel_plane_state(pstate);
+               enum plane_id plane0_id =
+                       plane_state->linked_plane ?
+                       plane_state->linked_plane->id : plane_id;
+               unsigned int *uv_data_rate =
+                       plane_state->linked_plane ?
+                       &plane_data_rate[plane_id] :
+                       &uv_plane_data_rate[plane_id];
+
+               if (plane_state->slave)
+                       continue;
 
                /* packed/y */
                rate = skl_plane_relative_data_rate(intel_cstate,
                                                    pstate, 0);
-               plane_data_rate[plane_id] = rate;
-
+               plane_data_rate[plane0_id] = rate;
                total_data_rate += rate;
 
                /* uv-plane */
                rate = skl_plane_relative_data_rate(intel_cstate,
                                                    pstate, 1);
-               uv_plane_data_rate[plane_id] = rate;
-
+               *uv_data_rate = rate;
                total_data_rate += rate;
        }
 
@@ -4298,6 +4303,7 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, 
int num_active,
 
        drm_atomic_crtc_state_for_each_plane_state(plane, pstate, 
&cstate->base) {
                enum plane_id plane_id = to_intel_plane(plane)->id;
+               struct intel_plane_state *plane_state = 
to_intel_plane_state(pstate);
 
                if (plane_id == PLANE_CURSOR)
                        continue;
@@ -4305,8 +4311,14 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, 
int num_active,
                if (!pstate->visible)
                        continue;
 
-               minimum[plane_id] = skl_ddb_min_alloc(pstate, 0);
-               uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
+               if (!plane_state->linked_plane) {
+                       minimum[plane_id] = skl_ddb_min_alloc(pstate, 0);
+                       uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
+               } else {
+                       enum plane_id aux = plane_state->linked_plane->id;
+                       minimum[aux] = skl_ddb_min_alloc(pstate, 0);
+                       minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
+               }
        }
 
        minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active);
@@ -4780,36 +4792,20 @@ skl_compute_wm_levels(const struct drm_i915_private 
*dev_priv,
                      struct skl_ddb_allocation *ddb,
                      struct intel_crtc_state *cstate,
                      const struct intel_plane_state *intel_pstate,
+                     uint16_t ddb_blocks,
                      const struct skl_wm_params *wm_params,
                      struct skl_plane_wm *wm,
-                     int plane_id)
+                     struct skl_wm_level *levels)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
-       struct drm_plane *plane = intel_pstate->base.plane;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-       uint16_t ddb_blocks;
-       enum pipe pipe = intel_crtc->pipe;
        int level, max_level = ilk_wm_max_level(dev_priv);
-       enum plane_id intel_plane_id = intel_plane->id;
+       struct skl_wm_level *result_prev = &levels[0];
        int ret;
 
        if (WARN_ON(!intel_pstate->base.fb))
                return -EINVAL;
 
-       ddb_blocks = plane_id ?
-                    skl_ddb_entry_size(&ddb->uv_plane[pipe][intel_plane_id]) :
-                    skl_ddb_entry_size(&ddb->plane[pipe][intel_plane_id]);
-
        for (level = 0; level <= max_level; level++) {
-               struct skl_wm_level *result = plane_id ? &wm->uv_wm[level] :
-                                                         &wm->wm[level];
-               struct skl_wm_level *result_prev;
-
-               if (level)
-                       result_prev = plane_id ? &wm->uv_wm[level - 1] :
-                                                 &wm->wm[level - 1];
-               else
-                       result_prev = plane_id ? &wm->uv_wm[0] : &wm->wm[0];
+               struct skl_wm_level *result = &levels[level];
 
                ret = skl_compute_plane_wm(dev_priv,
                                           cstate,
@@ -4821,6 +4817,8 @@ skl_compute_wm_levels(const struct drm_i915_private 
*dev_priv,
                                           result);
                if (ret)
                        return ret;
+
+               result_prev = result;
        }
 
        if (intel_pstate->base.fb->format->format == DRM_FORMAT_NV12)
@@ -4929,20 +4927,29 @@ static int skl_build_pipe_wm(struct intel_crtc_state 
*cstate,
                const struct intel_plane_state *intel_pstate =
                                                to_intel_plane_state(pstate);
                enum plane_id plane_id = to_intel_plane(plane)->id;
+               enum plane_id plane0_id =
+                       intel_pstate->linked_plane ?
+                       intel_pstate->linked_plane->id : plane_id;
                struct skl_wm_params wm_params;
                enum pipe pipe = to_intel_crtc(cstate->base.crtc)->pipe;
                uint16_t ddb_blocks;
 
-               wm = &pipe_wm->planes[plane_id];
-               ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]);
+               /* Watermarks calculated in master */
+               if (intel_pstate->slave)
+                       continue;
+
+               wm = &pipe_wm->planes[plane0_id];
+               ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane0_id]);
 
                ret = skl_compute_plane_wm_params(dev_priv, cstate,
-                                                 intel_pstate, &wm_params, 0);
+                                                 intel_pstate,
+                                                 &wm_params, 0);
                if (ret)
                        return ret;
 
                ret = skl_compute_wm_levels(dev_priv, ddb, cstate,
-                                           intel_pstate, &wm_params, wm, 0);
+                                           intel_pstate, ddb_blocks,
+                                           &wm_params, wm, wm->wm);
                if (ret)
                        return ret;
 
@@ -4960,11 +4967,32 @@ static int skl_build_pipe_wm(struct intel_crtc_state 
*cstate,
                        if (ret)
                                return ret;
 
-                       ret = skl_compute_wm_levels(dev_priv, ddb, cstate,
-                                                   intel_pstate, &wm_params,
-                                                   wm, 1);
-                       if (ret)
-                               return ret;
+                       if (intel_pstate->linked_plane) {
+                               ddb_blocks =
+                                       
skl_ddb_entry_size(&ddb->plane[pipe][plane_id]);
+
+                               /* write out wm on the UV plane */
+                               wm = &pipe_wm->planes[plane_id];
+                               wm->is_planar = true;
+
+                               ret = skl_compute_wm_levels(dev_priv, ddb, 
cstate,
+                                                           intel_pstate, 
ddb_blocks,
+                                                           &wm_params, wm, 
wm->wm);
+                               if (ret)
+                                       return ret;
+
+                               skl_compute_transition_wm(cstate, &wm_params, 
&wm->wm[0],
+                                                         ddb_blocks, 
&wm->trans_wm);
+                       } else {
+                               ddb_blocks =
+                                       
skl_ddb_entry_size(&ddb->uv_plane[pipe][plane_id]);
+
+                               ret = skl_compute_wm_levels(dev_priv, ddb, 
cstate,
+                                                           intel_pstate, 
ddb_blocks,
+                                                           &wm_params, wm, 
wm->uv_wm);
+                               if (ret)
+                                       return ret;
+                       }
                }
        }
 
@@ -5016,14 +5044,7 @@ static void skl_write_plane_wm(struct intel_crtc 
*intel_crtc,
        skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane_id),
                           &wm->trans_wm);
 
-       skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
-                           &ddb->plane[pipe][plane_id]);
-       /* FIXME: add proper NV12 support for ICL. */
-       if (INTEL_GEN(dev_priv) >= 11)
-               return skl_ddb_entry_write(dev_priv,
-                                          PLANE_BUF_CFG(pipe, plane_id),
-                                          &ddb->plane[pipe][plane_id]);
-       if (wm->is_planar) {
+       if (wm->is_planar && INTEL_GEN(dev_priv) < 11) {
                skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
                                    &ddb->uv_plane[pipe][plane_id]);
                skl_ddb_entry_write(dev_priv,
@@ -5032,7 +5053,8 @@ static void skl_write_plane_wm(struct intel_crtc 
*intel_crtc,
        } else {
                skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
                                    &ddb->plane[pipe][plane_id]);
-               I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0);
+               if (INTEL_GEN(dev_priv) < 11)
+                       I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0);
        }
 }
 
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to