This helper function stages a scaler request for a plane/crtc into
crtc_state->scaler_users (which is a bit field). It also performs
required checks before staging any change into scaler_state.

v2:
-updates to use single copy of scaler limits (Matt)
-added force detach parameter for pfit disable purpose (me)

Signed-off-by: Chandra Konduru <chandra.kond...@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  143 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    3 +
 2 files changed, 146 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 890d372..976bfb1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12387,6 +12387,149 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
        }
 }
 
+/*
+ * Update crtc_state->scaler_users for requested plane or crtc based on state.
+ *
+ * plane (in)
+ *     NULL - for crtc
+ *     not NULL - for plane
+ * force_detach (in)
+ *     unconditionally scaler will be staged for detachment from crtc/plane
+ * Return
+ *     0 - scaler_usage updated successfully
+ *    error - requested scaling cannot be supported or other error condition
+ */
+int
+skl_update_scaler_users(
+       struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
+       struct intel_plane *intel_plane, struct intel_plane_state *plane_state,
+       int force_detach)
+{
+       int need_scaling;
+       int idx;
+       int src_w, src_h, dst_w, dst_h;
+       int scaler_id;
+       struct drm_framebuffer *fb;
+       struct intel_crtc_scaler_state *scaler_state;
+
+       if (!intel_crtc || !crtc_state ||
+               (intel_plane && intel_plane->base.type == 
DRM_PLANE_TYPE_CURSOR))
+               return 0;
+
+       scaler_state = &crtc_state->scaler_state;
+
+       if (!scaler_state->num_scalers) {
+               DRM_DEBUG_KMS("crtc_state = %p, num_scalers = %d\n", crtc_state,
+                       scaler_state->num_scalers);
+               return 0;
+       }
+
+       idx = intel_plane ? drm_plane_index(&intel_plane->base) : 
SKL_CRTC_INDEX;
+       fb = intel_plane ? plane_state->base.fb : NULL;
+
+       if (intel_plane) {
+               src_w = drm_rect_width(&plane_state->src) >> 16;
+               src_h = drm_rect_height(&plane_state->src) >> 16;
+               dst_w = drm_rect_width(&plane_state->dst);
+               dst_h = drm_rect_height(&plane_state->dst);
+               scaler_id = plane_state->scaler_id;
+       } else {
+               struct drm_display_mode *adjusted_mode =
+                       &crtc_state->base.adjusted_mode;
+               src_w = crtc_state->pipe_src_w;
+               src_h = crtc_state->pipe_src_h;
+               dst_w = adjusted_mode->hdisplay;
+               dst_h = adjusted_mode->vdisplay;
+               scaler_id = scaler_state->scaler_id;
+       }
+       need_scaling = (src_w != dst_w || src_h != dst_h);
+
+       /*
+        * if plane is being disabled or scaler is no more required or force 
detach
+        *  - free scaler binded to this plane/crtc
+        *  - in order to do this, update crtc->scaler_usage
+        *
+        * Here scaler state in crtc_state is set free so that
+        * scaler can be assigned to other user. Actual register
+        * update to free the scaler is done in plane/panel-fit programming.
+        * For this purpose crtc/plane_state->scaler_id isn't reset here.
+        */
+       if (force_detach || !need_scaling || (intel_plane &&
+               (!fb || !plane_state->visible))) {
+               if (scaler_id >= 0) {
+                       scaler_state->scaler_users &= ~(1 << idx);
+                       scaler_state->scalers[scaler_id].in_use = 0;
+
+                       DRM_DEBUG_KMS("Staged freeing scaler id %u.%u from 
%s:%d "
+                               "crtc_state = %p scaler_users = 0x%x\n",
+                               intel_crtc->pipe, scaler_id, intel_plane ? 
"PLANE" : "CRTC",
+                               intel_plane ? intel_plane->base.base.id :
+                               intel_crtc->base.base.id, crtc_state,
+                               scaler_state->scaler_users);
+               }
+               return 0;
+       }
+
+       /*
+        * check for rect size:
+        *     min sizes in case of scaling involved
+        *     max sizes in all cases
+        */
+       if ((need_scaling &&
+               (src_w < scaler_state->min_src_w || src_h < 
scaler_state->min_src_h ||
+                dst_w < scaler_state->min_dst_w || dst_h < 
scaler_state->min_dst_h)) ||
+
+                src_w > scaler_state->max_src_w || src_h > 
scaler_state->max_src_h ||
+                dst_w > scaler_state->max_dst_w || dst_h > 
scaler_state->max_dst_h) {
+               DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst 
%ux%u "
+                       "size is out of scaler range\n",
+                       intel_plane ? "PLANE" : "CRTC",
+                       intel_plane ? intel_plane->base.base.id : 
intel_crtc->base.base.id,
+                       intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
+               return -EINVAL;
+       }
+
+       /* check colorkey */
+       if (intel_plane && need_scaling && intel_colorkey_enabled(intel_plane)) 
{
+               DRM_DEBUG_KMS("PLANE:%d scaling with color key not allowed",
+                       intel_plane->base.base.id);
+               return -EINVAL;
+       }
+
+       /* Check src format */
+       if (intel_plane && need_scaling) {
+               switch (fb->pixel_format) {
+               case DRM_FORMAT_RGB565:
+               case DRM_FORMAT_XBGR8888:
+               case DRM_FORMAT_XRGB8888:
+               case DRM_FORMAT_ABGR8888:
+               case DRM_FORMAT_ARGB8888:
+               case DRM_FORMAT_XRGB2101010:
+               case DRM_FORMAT_ARGB2101010:
+               case DRM_FORMAT_XBGR2101010:
+               case DRM_FORMAT_ABGR2101010:
+               case DRM_FORMAT_YUYV:
+               case DRM_FORMAT_YVYU:
+               case DRM_FORMAT_UYVY:
+               case DRM_FORMAT_VYUY:
+                       break;
+               default:
+                       DRM_DEBUG_KMS("PLANE:%d FB:%d format 0x%x not 
supported\n",
+                               intel_plane->base.base.id, fb->base.id, 
fb->pixel_format);
+                       return -EINVAL;
+               }
+       }
+
+       /* mark this plane as a scaler user in crtc_state */
+       scaler_state->scaler_users |= (1 << idx);
+       DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
+               "crtc_state = %p scaler_users = 0x%x\n",
+               intel_plane ? "PLANE" : "CRTC",
+               intel_plane ? intel_plane->base.base.id : 
intel_crtc->base.base.id,
+               src_w, src_h, dst_w, dst_h, crtc_state, 
scaler_state->scaler_users);
+       return 0;
+}
+
 static int
 intel_check_primary_plane(struct drm_plane *plane,
                          struct intel_plane_state *state)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1da5087..f5d53c9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1138,6 +1138,9 @@ void intel_mode_from_pipe_config(struct drm_display_mode 
*mode,
                                 struct intel_crtc_state *pipe_config);
 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_users(struct intel_crtc *intel_crtc,
+       struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
+       struct intel_plane_state *plane_state, int force_detach);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
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