|
@@ -2973,6 +2973,153 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
|
|
return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
|
|
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)
|
|
static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_config *config)
|
|
{
|
|
{
|
|
/* TODO: Take into account the scalers once we support them */
|
|
/* TODO: Take into account the scalers once we support them */
|
|
@@ -3294,6 +3441,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
skl_compute_wm_pipe_parameters(crtc, params);
|
|
skl_compute_wm_pipe_parameters(crtc, params);
|
|
|
|
+ skl_allocate_pipe_ddb(crtc, config, params, ddb);
|
|
skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
|
|
skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
|
|
|
|
|
|
if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
|
|
if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
|