Commit b879d58f authored by Mahesh Kumar's avatar Mahesh Kumar Committed by Maarten Lankhorst
Browse files

drm/i915/skl+: refactor WM calculation for NV12



Current code calculates DDB for planar formats in such a way that we
store DDB of plane-0 in plane 1 & vice-versa.
In order to make this clean this patch refactors WM/DDB calculation for
NV12 planar formats.

v2: Addressed review comments by Maarten

v3: Rebased and addressed review comments by Maarten

v4: Fixed a compilation issue of string replacement is_nv12 to
is_planar

v5: Added reviewed by from Juha-Pekka Heikkila

v6: Rebased the series

Reviewed-by: default avatarJuha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarMahesh Kumar <mahesh1.kumar@intel.com>
Signed-off-by: default avatarVidya Srinivas <vidya.srinivas@intel.com>
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1523245273-30264-3-git-send-email-vidya.srinivas@intel.com
parent 60f8e873
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1182,8 +1182,9 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
}

struct skl_ddb_allocation {
	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */
	struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES];
	/* packed/y */
	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
	struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES];
};

struct skl_ddb_values {
+1 −0
Original line number Diff line number Diff line
@@ -603,6 +603,7 @@ struct intel_pipe_wm {
struct skl_plane_wm {
	struct skl_wm_level wm[8];
	struct skl_wm_level trans_wm;
	bool is_planar;
};

struct skl_pipe_wm {
+62 −59
Original line number Diff line number Diff line
@@ -4009,9 +4009,9 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc,
static unsigned int
skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
			     const struct drm_plane_state *pstate,
			     int y)
			     const int plane)
{
	struct intel_plane *plane = to_intel_plane(pstate->plane);
	struct intel_plane *intel_plane = to_intel_plane(pstate->plane);
	struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
	uint32_t data_rate;
	uint32_t width = 0, height = 0;
@@ -4025,9 +4025,9 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
	fb = pstate->fb;
	format = fb->format->format;

	if (plane->id == PLANE_CURSOR)
	if (intel_plane->id == PLANE_CURSOR)
		return 0;
	if (y && format != DRM_FORMAT_NV12)
	if (plane == 1 && format != DRM_FORMAT_NV12)
		return 0;

	/*
@@ -4038,19 +4038,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
	width = drm_rect_width(&intel_pstate->base.src) >> 16;
	height = drm_rect_height(&intel_pstate->base.src) >> 16;

	/* for planar format */
	if (format == DRM_FORMAT_NV12) {
		if (y)  /* y-plane data rate */
			data_rate = width * height *
				fb->format->cpp[0];
		else    /* uv-plane data rate */
			data_rate = (width / 2) * (height / 2) *
				fb->format->cpp[1];
	} else {
		/* for packed formats */
		data_rate = width * height * fb->format->cpp[0];
	/* UV plane does 1/2 pixel sub-sampling */
	if (plane == 1 && format == DRM_FORMAT_NV12) {
		width /= 2;
		height /= 2;
	}

	data_rate = width * height * fb->format->cpp[plane];

	down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate);

	return mul_round_up_u32_fixed16(data_rate, down_scale_amount);
@@ -4063,8 +4058,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
 */
static unsigned int
skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
				 unsigned *plane_data_rate,
				 unsigned *plane_y_data_rate)
				 unsigned int *plane_data_rate,
				 unsigned int *uv_plane_data_rate)
{
	struct drm_crtc_state *cstate = &intel_cstate->base;
	struct drm_atomic_state *state = cstate->state;
@@ -4080,17 +4075,17 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
		enum plane_id plane_id = to_intel_plane(plane)->id;
		unsigned int rate;

		/* packed/uv */
		/* packed/y */
		rate = skl_plane_relative_data_rate(intel_cstate,
						    pstate, 0);
		plane_data_rate[plane_id] = rate;

		total_data_rate += rate;

		/* y-plane */
		/* uv-plane */
		rate = skl_plane_relative_data_rate(intel_cstate,
						    pstate, 1);
		plane_y_data_rate[plane_id] = rate;
		uv_plane_data_rate[plane_id] = rate;

		total_data_rate += rate;
	}
@@ -4099,8 +4094,7 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
}

static uint16_t
skl_ddb_min_alloc(const struct drm_plane_state *pstate,
		  const int y)
skl_ddb_min_alloc(const struct drm_plane_state *pstate, const int plane)
{
	struct drm_framebuffer *fb = pstate->fb;
	struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
@@ -4111,8 +4105,8 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
	if (WARN_ON(!fb))
		return 0;

	/* For packed formats, no y-plane, return 0 */
	if (y && fb->format->format != DRM_FORMAT_NV12)
	/* For packed formats, and uv-plane, return 0 */
	if (plane == 1 && fb->format->format != DRM_FORMAT_NV12)
		return 0;

	/* For Non Y-tile return 8-blocks */
@@ -4131,15 +4125,12 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
	src_h = drm_rect_height(&intel_pstate->base.src) >> 16;

	/* Halve UV plane width and height for NV12 */
	if (fb->format->format == DRM_FORMAT_NV12 && !y) {
	if (plane == 1) {
		src_w /= 2;
		src_h /= 2;
	}

	if (fb->format->format == DRM_FORMAT_NV12 && !y)
		plane_bpp = fb->format->cpp[1];
	else
		plane_bpp = fb->format->cpp[0];
	plane_bpp = fb->format->cpp[plane];

	if (drm_rotation_90_or_270(pstate->rotation)) {
		switch (plane_bpp) {
@@ -4167,7 +4158,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,

static void
skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active,
		 uint16_t *minimum, uint16_t *y_minimum)
		 uint16_t *minimum, uint16_t *uv_minimum)
{
	const struct drm_plane_state *pstate;
	struct drm_plane *plane;
@@ -4182,7 +4173,7 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active,
			continue;

		minimum[plane_id] = skl_ddb_min_alloc(pstate, 0);
		y_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
		uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
	}

	minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active);
@@ -4200,17 +4191,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
	struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb;
	uint16_t alloc_size, start;
	uint16_t minimum[I915_MAX_PLANES] = {};
	uint16_t y_minimum[I915_MAX_PLANES] = {};
	uint16_t uv_minimum[I915_MAX_PLANES] = {};
	unsigned int total_data_rate;
	enum plane_id plane_id;
	int num_active;
	unsigned plane_data_rate[I915_MAX_PLANES] = {};
	unsigned plane_y_data_rate[I915_MAX_PLANES] = {};
	unsigned int plane_data_rate[I915_MAX_PLANES] = {};
	unsigned int uv_plane_data_rate[I915_MAX_PLANES] = {};
	uint16_t total_min_blocks = 0;

	/* Clear the partitioning for disabled planes. */
	memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
	memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
	memset(ddb->uv_plane[pipe], 0, sizeof(ddb->uv_plane[pipe]));

	if (WARN_ON(!state))
		return 0;
@@ -4225,7 +4216,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
	if (alloc_size == 0)
		return 0;

	skl_ddb_calc_min(cstate, num_active, minimum, y_minimum);
	skl_ddb_calc_min(cstate, num_active, minimum, uv_minimum);

	/*
	 * 1. Allocate the mininum required blocks for each active plane
@@ -4235,7 +4226,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,

	for_each_plane_id_on_crtc(intel_crtc, plane_id) {
		total_min_blocks += minimum[plane_id];
		total_min_blocks += y_minimum[plane_id];
		total_min_blocks += uv_minimum[plane_id];
	}

	if (total_min_blocks > alloc_size) {
@@ -4257,14 +4248,14 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
	 */
	total_data_rate = skl_get_total_relative_data_rate(cstate,
							   plane_data_rate,
							   plane_y_data_rate);
							   uv_plane_data_rate);
	if (total_data_rate == 0)
		return 0;

	start = alloc->start;
	for_each_plane_id_on_crtc(intel_crtc, plane_id) {
		unsigned int data_rate, y_data_rate;
		uint16_t plane_blocks, y_plane_blocks = 0;
		unsigned int data_rate, uv_data_rate;
		uint16_t plane_blocks, uv_plane_blocks;

		if (plane_id == PLANE_CURSOR)
			continue;
@@ -4288,21 +4279,20 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,

		start += plane_blocks;

		/*
		 * allocation for y_plane part of planar format:
		 */
		y_data_rate = plane_y_data_rate[plane_id];
		/* Allocate DDB for UV plane for planar format/NV12 */
		uv_data_rate = uv_plane_data_rate[plane_id];

		y_plane_blocks = y_minimum[plane_id];
		y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
		uv_plane_blocks = uv_minimum[plane_id];
		uv_plane_blocks += div_u64((uint64_t)alloc_size * uv_data_rate,
					   total_data_rate);

		if (y_data_rate) {
			ddb->y_plane[pipe][plane_id].start = start;
			ddb->y_plane[pipe][plane_id].end = start + y_plane_blocks;
		if (uv_data_rate) {
			ddb->uv_plane[pipe][plane_id].start = start;
			ddb->uv_plane[pipe][plane_id].end =
				start + uv_plane_blocks;
		}

		start += y_plane_blocks;
		start += uv_plane_blocks;
	}

	return 0;
@@ -4430,8 +4420,7 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv,
		wp->width = drm_rect_width(&intel_pstate->base.src) >> 16;
	}

	wp->cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] :
							    fb->format->cpp[0];
	wp->cpp = fb->format->cpp[0];
	wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate,
							     intel_pstate);

@@ -4660,6 +4649,9 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv,
			return ret;
	}

	if (intel_pstate->base.fb->format->format == DRM_FORMAT_NV12)
		wm->is_planar = true;

	return 0;
}

@@ -4833,10 +4825,21 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc,

	skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
			    &ddb->plane[pipe][plane_id]);
	if (INTEL_GEN(dev_priv) < 11)
	if (INTEL_GEN(dev_priv) >= 11)
		return skl_ddb_entry_write(dev_priv,
					   PLANE_BUF_CFG(pipe, plane_id),
					   &ddb->plane[pipe][plane_id]);
	if (wm->is_planar) {
		skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
				    &ddb->uv_plane[pipe][plane_id]);
		skl_ddb_entry_write(dev_priv,
				    PLANE_NV12_BUF_CFG(pipe, plane_id),
				    &ddb->y_plane[pipe][plane_id]);
				    &ddb->plane[pipe][plane_id]);
	} else {
		skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
				    &ddb->plane[pipe][plane_id]);
		I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0);
	}
}

static void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
@@ -4951,8 +4954,8 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)

		if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id],
					&new_ddb->plane[pipe][plane_id]) &&
		    skl_ddb_entry_equal(&cur_ddb->y_plane[pipe][plane_id],
					&new_ddb->y_plane[pipe][plane_id]))
		    skl_ddb_entry_equal(&cur_ddb->uv_plane[pipe][plane_id],
					&new_ddb->uv_plane[pipe][plane_id]))
			continue;

		plane_state = drm_atomic_get_plane_state(state, plane);
@@ -5046,8 +5049,8 @@ skl_copy_ddb_for_pipe(struct skl_ddb_values *dst,
		      struct skl_ddb_values *src,
		      enum pipe pipe)
{
	memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe],
	       sizeof(dst->ddb.y_plane[pipe]));
	memcpy(dst->ddb.uv_plane[pipe], src->ddb.uv_plane[pipe],
	       sizeof(dst->ddb.uv_plane[pipe]));
	memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe],
	       sizeof(dst->ddb.plane[pipe]));
}