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.lesp...@intel.com>

Looks good.

Reviewed-by: Ville Syrjälä <ville.syrj...@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
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to