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@xxxxxxxxx> Looks good. Reviewed-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > 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 = ¶ms->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 = ¶ms->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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Ville Syrjälä Intel OTC _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx