Re: [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state

Matt Roper
2015-03-25T05:15:05Z

On Fri, Mar 20, 2015 at 05:04:29PM -0700, Chandra Konduru wrote:
> 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.konduru@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.

I realize you're trying to re-use some logic here, but I find the
overloaded function that works on either planes or crtcs a bit harder to
follow. Personally I'd prefer if this were just two separate functions,
one focused on planes, one focused on CRTC's, even if it means
duplicating a little bit of the logic.

> + *
> + * 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
> + */

Probably want to put this in kerneldoc format.

> +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,

Might be a little easier to drop the intel_crtc and intel_plane
parameters and just pull them out of the state backpointers.

> + 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);

We're already calculating this in the plane check function; we should
probably just store the result in a plane_state field at that point so
we don't have to re-calculate it here.

> +
> + /*
> + * if plane is being disabled or scaler is no more required or force detach

Maybe it will become more clear later in the patch series, but I'm not
sure I understand what 'force_detach' does. Won't scalers that we don't
end up re-assigning automatically be cleared when we nobody makes use of
them in a new commit?

> + * - 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 &&

need_scaling is guaranteed to be true now (otherwise we would have
returned above), so we can drop this test.

> + (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)) {

Can drop 'need_scaling' test again.

> + 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) {

Ditto

> + 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);

Might want to add "...while scaling" to this message to avoid confusion.

> + 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

You should probably just squash this into the later patches where you
actually call it (e.g., patch 18) so it's more clear how/when/where it
is used.

Matt

>

--
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795