[Intel-gfx] [PATCH 4/7] drm/i915/skl+: calculate plane pixel rate.
Matt Roper
matthew.d.roper at intel.com
Thu Jan 14 16:57:19 PST 2016
On Thu, Jan 14, 2016 at 05:32:45PM +0530, Shobhit Kumar wrote:
> From: "Kumar, Mahesh" <mahesh1.kumar at intel.com>
>
> Don't use pipe pixel rate for plane pixel rate.
> Calculate plane pixel according to formula
>
> adjusted plane_pixel_rate = adjusted pipe_pixel_rate * downscale ammount
>
> downscale amount = max[1, src_h/dst_h] * max[1, src_w/dst_w]
> if 90/270 rotation use rotated width & height
>
> Signed-off-by: Kumar, Mahesh <mahesh1.kumar at intel.com>
> ---
> drivers/gpu/drm/i915/intel_drv.h | 2 +
> drivers/gpu/drm/i915/intel_pm.c | 95 +++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 95 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 059b46e..49f237e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -661,6 +661,8 @@ struct intel_plane_wm_parameters {
> u64 tiling;
> unsigned int rotation;
> uint16_t fifo_size;
> + /* Stores the adjusted plane pixel rate for WM calculation */
> + uint32_t plane_pixel_rate;
> };
>
> struct intel_plane {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 64b39ec..ffcc56a 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2841,6 +2841,54 @@ skl_wm_plane_id(const struct intel_plane *plane)
> }
> }
>
> +/*
> + * This function takes drm_plane_state as input
> + * and decides the downscale amount according to the formula
> + *
> + * downscale amount = Max[1, Horizontal source size / Horizontal dest size]
> + *
> + * Return value is multiplied by 1000 to retain fractional part
> + * Caller should take care of dividing & Rounding off the value
Would it be simpler to just continue using 16.16 fixed point format?
Also, are there any helpers in drm_rect.c that we can use to simplify
this at all?
> + */
> +static uint32_t
> +skl_plane_downscale_amount(const struct intel_plane *intel_plane)
> +{
> + struct drm_plane_state *pstate = intel_plane->base.state;
> + struct intel_crtc *crtc = to_intel_crtc(pstate->crtc);
> + struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
> + uint32_t downscale_h, downscale_w;
> + uint32_t src_w, src_h, dst_w, dst_h, tmp;
> +
> + if (drm_rect_width(&intel_pstate->src)) {
> + src_w = drm_rect_width(&intel_pstate->src) >> 16;
> + src_h = drm_rect_height(&intel_pstate->src) >> 16;
> + } else {
> + src_w = crtc->config->pipe_src_w;
> + src_h = crtc->config->pipe_src_h;
> + }
> +
> + dst_w = drm_rect_width(&intel_pstate->dst);
> + dst_h = drm_rect_height(&intel_pstate->dst);
> +
> + if (intel_rotation_90_or_270(pstate->rotation))
> + swap(dst_w, dst_h);
> +
> + /* If destination height & wight are zero return amount as unity */
> + if (dst_w == 0 || dst_h == 0)
> + return 1000;
> +
> + /* Multiply by 1000 for precision */
> + tmp = (1000 * src_h) / dst_h;
> + downscale_h = max_t(uint32_t, 1000, tmp);
> +
> + tmp = (1000 * src_w) / dst_w;
> + downscale_w = max_t(uint32_t, 1000, tmp);
> +
> + /* Reducing precision to 3 decimal places */
> + return DIV_ROUND_UP(downscale_h * downscale_w, 1000);
> +}
> +
> +
> static void
> skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
> const struct intel_crtc_state *cstate,
> @@ -3265,10 +3313,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ?
> drm_format_plane_cpp(fb->pixel_format, 1) :
> drm_format_plane_cpp(fb->pixel_format, 0);
> - method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
> + method1 = skl_wm_method1(intel_plane->wm.plane_pixel_rate,
> bytes_per_pixel,
> latency);
> - method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
> + method2 = skl_wm_method2(intel_plane->wm.plane_pixel_rate,
> cstate->base.adjusted_mode.crtc_htotal,
> width,
> bytes_per_pixel,
> @@ -3709,6 +3757,46 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
> }
> }
>
> +static uint32_t
> +skl_plane_pixel_rate(struct intel_crtc_state *cstate, struct intel_plane *plane)
> +{
> + uint32_t adjusted_pixel_rate;
> + uint32_t downscale_amount;
> +
> + /*
> + * adjusted plane pixel rate = adjusted pipe pixel rate
> + * Plane pixel rate = adjusted plane pixel rate * plane down scale
> + * amount
> + */
> + adjusted_pixel_rate = skl_pipe_pixel_rate(cstate);
> + downscale_amount = skl_plane_downscale_amount(plane);
> +
> + return DIV_ROUND_UP(adjusted_pixel_rate * downscale_amount,
> + 1000);
> +}
> +
> +static void skl_set_plane_pixel_rate(struct drm_crtc *crtc)
> +{
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
> + struct intel_plane *intel_plane = NULL;
> + struct drm_device *dev = crtc->dev;
> +
> + if (!intel_crtc->active)
> + return;
> + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> + struct drm_plane *plane = &intel_plane->base;
> + struct drm_framebuffer *fb = plane->state->fb;
> +
> + if (fb == NULL)
> + continue;
Maybe change this to a test of intel_plane_state->visible instead so
that we're not bothering with this for planes that actually do have an
FB assigned but are fully clipped?
Then you'll also be able to eliminate the 'else' block of the non-zero
width test farther up.
Matt
> +
> + intel_plane->wm.plane_pixel_rate = skl_plane_pixel_rate(cstate,
> + intel_plane);
> + }
> +
> +}
> +
> static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
> {
> watermarks->wm_linetime[pipe] = 0;
> @@ -3744,6 +3832,9 @@ static void skl_update_wm(struct drm_crtc *crtc)
>
> skl_clear_wm(results, intel_crtc->pipe);
>
> + /* Calculate plane pixel rate for each plane in advance */
> + skl_set_plane_pixel_rate(crtc);
> +
> if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
> return;
>
> --
> 2.4.3
>
--
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
More information about the Intel-gfx
mailing list