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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

Signed-off-by: Damien Lespiau <damien.lespiau@xxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_pm.c | 150 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e69a833..716af24 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2957,6 +2957,155 @@ 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,
+				   struct intel_wm_config *config,
+				   struct skl_pipe_wm_parameters *params,
+				   uint16_t *available,
+				   uint16_t *start,
+				   uint16_t *end)
+{
+	struct drm_crtc *crtc;
+	unsigned int ddb_size;
+	int nth_active_pipe;
+
+	if (!params->active) {
+		*available = 0;
+		*start = 0;
+		*end = 0;
+		return;
+	}
+
+	ddb_size = SKL_DDB_SIZE;
+
+	ddb_size -= 4; /* 4 blocks for bypass path allocation */
+
+	nth_active_pipe = 1;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (!intel_crtc_active(crtc))
+			continue;
+
+		if (crtc == for_crtc)
+			break;
+
+		nth_active_pipe++;
+	}
+
+	*available = ddb_size / config->num_pipes_active;
+	*start = (nth_active_pipe - 1) * ddb_size / config->num_pipes_active;
+	*end = *start + *available - 1;
+}
+
+static unsigned int skl_cursor_allocation(struct intel_wm_config *config)
+{
+	if (config->num_pipes_active == 1)
+		return 32;
+
+	return 8;
+}
+
+static unsigned int
+skl_plane_relative_data_rate(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,
+				 struct skl_pipe_wm_parameters *params)
+{
+	unsigned int total_data_rate = 0;
+	int plane;
+
+	for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
+		struct intel_plane_wm_parameters *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,
+		      struct intel_wm_config *config,
+		      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;
+	uint16_t available, start, end, cursor_blocks;
+	unsigned int total_data_rate;
+	int plane;
+
+	skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params,
+					   &available, &start, &end);
+	if (available == 0) {
+		const size_t size = ARRAY_SIZE(ddb->plane[pipe]) *
+				    sizeof(struct skl_ddb_entry);
+
+		memset(ddb->plane[pipe], 0, size);
+		memset(&ddb->cursor[pipe], 0, sizeof(struct skl_ddb_entry));
+		return;
+	}
+
+	cursor_blocks = skl_cursor_allocation(config);
+	ddb->cursor[pipe].start = end - cursor_blocks + 1;
+	ddb->cursor[pipe].end = end;
+
+	available -= cursor_blocks;
+	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 don't always allocate every single block here.
+	 */
+	total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
+
+	for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
+		struct intel_plane_wm_parameters *p = &params->plane[plane];
+		unsigned int data_rate;
+		uint16_t plane_blocks;
+
+		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)available * 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 */
@@ -3278,6 +3427,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




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux