Re: [PATCH 48/89 v6] drm/i915/skl: Allocate DDB portions for display planes

Ville Syrjälä
2014-10-29T17:13:15Z

On Sat, Sep 27, 2014 at 03:15:00PM +0100, Damien Lespiau wrote:
> v2: Fix the 3rd plane/cursor logic (Pradeep Bhat)
> v3: Fix one-by-one error in the DDB allocation code
> v4: Rebase on top of the skl_pipe_pixel_rate() argument change
> v5: Replace the available/start/end output parameters of
> skl_ddb_get_pipe_allocation_limits() by a single ddb entry constify
> a few arguments
> Make nth_active_pipe 0 indexed
> Use sizeof(variable) instead of sizeof(type)
> (Ville)
> v6: Use the for_each_crtc() macro instead of list_for_each_entry()
>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>

Looks good.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
> drivers/gpu/drm/i915/intel_pm.c | 148 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 148 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 1db4aa8..3dc689e 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2965,6 +2965,153 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
> return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> }
>
> +/*
> + * On gen9, we need to allocate Display Data Buffer (DDB) portions to the
> + * different active planes.
> + */
> +
> +#define SKL_DDB_SIZE 896 /* in blocks */
> +
> +static void
> +skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
> + struct drm_crtc *for_crtc,
> + const struct intel_wm_config *config,
> + const struct skl_pipe_wm_parameters *params,
> + struct skl_ddb_entry *alloc /* out */)
> +{
> + struct drm_crtc *crtc;
> + unsigned int pipe_size, ddb_size;
> + int nth_active_pipe;
> +
> + if (!params->active) {
> + alloc->start = 0;
> + alloc->end = 0;
> + return;
> + }
> +
> + ddb_size = SKL_DDB_SIZE;
> +
> + ddb_size -= 4; /* 4 blocks for bypass path allocation */
> +
> + nth_active_pipe = 0;
> + for_each_crtc(dev, crtc) {
> + if (!intel_crtc_active(crtc))
> + continue;
> +
> + if (crtc == for_crtc)
> + break;
> +
> + nth_active_pipe++;
> + }
> +
> + pipe_size = ddb_size / config->num_pipes_active;
> + alloc->start = nth_active_pipe * ddb_size / config->num_pipes_active;
> + alloc->end = alloc->start + pipe_size - 1;
> +}
> +
> +static unsigned int skl_cursor_allocation(const struct intel_wm_config *config)
> +{
> + if (config->num_pipes_active == 1)
> + return 32;
> +
> + return 8;
> +}
> +
> +static unsigned int
> +skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p)
> +{
> + return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel;
> +}
> +
> +/*
> + * We don't overflow 32 bits. Worst case is 3 planes enabled, each fetching
> + * a 8192x4096@32bpp framebuffer:
> + * 3 * 4096 * 8192 * 4 < 2^32
> + */
> +static unsigned int
> +skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc,
> + const struct skl_pipe_wm_parameters *params)
> +{
> + unsigned int total_data_rate = 0;
> + int plane;
> +
> + for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
> + const struct intel_plane_wm_parameters *p;
> +
> + p = &params->plane[plane];
> + if (!p->enabled)
> + continue;
> +
> + total_data_rate += skl_plane_relative_data_rate(p);
> + }
> +
> + return total_data_rate;
> +}
> +
> +static void
> +skl_allocate_pipe_ddb(struct drm_crtc *crtc,
> + const struct intel_wm_config *config,
> + const struct skl_pipe_wm_parameters *params,
> + struct skl_ddb_allocation *ddb /* out */)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + enum pipe pipe = intel_crtc->pipe;
> + struct skl_ddb_entry alloc;
> + uint16_t alloc_size, start, cursor_blocks;
> + unsigned int total_data_rate;
> + int plane;
> +
> + skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, &alloc);
> + alloc_size = skl_ddb_entry_size(&alloc);
> + if (alloc_size == 0) {
> + memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
> + memset(&ddb->cursor[pipe], 0, sizeof(ddb->cursor[pipe]));
> + return;
> + }
> +
> + cursor_blocks = skl_cursor_allocation(config);
> + ddb->cursor[pipe].start = alloc.end - cursor_blocks + 1;
> + ddb->cursor[pipe].end = alloc.end;
> +
> + alloc_size -= cursor_blocks;
> + alloc.end -= cursor_blocks;
> +
> + /*
> + * Each active plane get a portion of the remaining space, in
> + * proportion to the amount of data they need to fetch from memory.
> + *
> + * FIXME: we may not allocate every single block here.
> + */
> + total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
> +
> + start = alloc.start;
> + for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
> + const struct intel_plane_wm_parameters *p;
> + unsigned int data_rate;
> + uint16_t plane_blocks;
> +
> + p = &params->plane[plane];
> + if (!p->enabled)
> + continue;
> +
> + data_rate = skl_plane_relative_data_rate(p);
> +
> + /*
> + * promote the expression to 64 bits to avoid overflowing, the
> + * result is < available as data_rate / total_data_rate < 1
> + */
> + plane_blocks = div_u64((uint64_t)alloc_size * data_rate,
> + total_data_rate);
> +
> + ddb->plane[pipe][plane].start = start;
> + ddb->plane[pipe][plane].end = start + plane_blocks - 1;
> +
> + start += plane_blocks;
> + }
> +
> +}
> +
> static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_config *config)
> {
> /* TODO: Take into account the scalers once we support them */
> @@ -3286,6 +3433,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>
> skl_compute_wm_pipe_parameters(crtc, params);
> + skl_allocate_pipe_ddb(crtc, config, params, ddb);
> skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
>
> if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
> --
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org