[PATCH v1 5/6] drm/i915: Do not do fb src adjustments for NV12

Vidya Srinivas vidya.srinivas at intel.com
Wed Apr 11 09:09:29 UTC 2018


We skip src trunction/adjustments for
NV12 case and handle the sizes directly.
Without this, pipe fifo underruns are seen on APL/KBL.

Credits-to: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Signed-off-by: Vidya Srinivas <vidya.srinivas at intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 88 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_sprite.c  | 10 +++-
 2 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ebb3f8e..e4cf7a6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12951,6 +12951,86 @@ skl_max_scale(struct intel_crtc *intel_crtc,
 }
 
 static int
+intel_primary_plane_state(struct drm_plane_state *plane_state,
+			  const struct drm_crtc_state *crtc_state,
+			  int min_scale, int max_scale,
+			  bool can_position, bool can_update_disabled)
+{
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_rect *src = &plane_state->src;
+	struct drm_rect *dst = &plane_state->dst;
+	unsigned int rotation = plane_state->rotation;
+	struct drm_rect clip = {};
+	int hscale, vscale;
+
+	WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
+
+	*src = drm_plane_state_src(plane_state);
+	*dst = drm_plane_state_dest(plane_state);
+
+	if (!fb) {
+		plane_state->visible = false;
+		return 0;
+	}
+
+	/* crtc should only be NULL when disabling (i.e., !fb) */
+	if (WARN_ON(!plane_state->crtc)) {
+		plane_state->visible = false;
+		return 0;
+	}
+
+	if (!crtc_state->enable && !can_update_disabled) {
+		DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
+		return -EINVAL;
+	}
+
+	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
+
+	/* Check scaling */
+	hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
+	vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
+	if (hscale < 0 || vscale < 0) {
+		DRM_DEBUG_KMS("Invalid scaling of plane\n");
+		drm_rect_debug_print("src: ", &plane_state->src, true);
+		drm_rect_debug_print("dst: ", &plane_state->dst, false);
+		return -ERANGE;
+	}
+
+	if (crtc_state->enable)
+		drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2);
+
+	if (fb->format->format == DRM_FORMAT_NV12) {
+		plane_state->visible = true;
+		goto skip_clip;
+	}
+
+	plane_state->visible =
+		drm_rect_clip_scaled(src, dst, &clip, hscale, vscale);
+
+skip_clip:
+	drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
+
+	if (!plane_state->visible)
+		/*
+		 * Plane isn't visible; some drivers can handle this
+		 * so we just return success here.  Drivers that can't
+		 * (including those that use the primary plane helper's
+		 * update function) will return an error from their
+		 * update_plane handler.
+		 */
+		return 0;
+
+	if (!can_position && !drm_rect_equals(dst, &clip)) {
+		DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
+		drm_rect_debug_print("dst: ", dst, false);
+		drm_rect_debug_print("clip: ", &clip, false);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
 intel_check_primary_plane(struct intel_plane *plane,
 			  struct intel_crtc_state *crtc_state,
 			  struct intel_plane_state *state)
@@ -12975,10 +13055,10 @@ intel_check_primary_plane(struct intel_plane *plane,
 		can_position = true;
 	}
 
-	ret = drm_atomic_helper_check_plane_state(&state->base,
-						  &crtc_state->base,
-						  min_scale, max_scale,
-						  can_position, true);
+	ret = intel_primary_plane_state(&state->base,
+					&crtc_state->base,
+					min_scale, max_scale,
+					can_position, true);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d5dad44..1e47b97 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1035,11 +1035,14 @@ intel_check_sprite_plane(struct intel_plane *plane,
 			return vscale;
 		}
 
+		if (state->base.fb && fb->format->format == DRM_FORMAT_NV12)
+			goto skip_adjust;
+
 		/* Make the source viewport size an exact multiple of the scaling factors. */
 		drm_rect_adjust_size(src,
 				     drm_rect_width(dst) * hscale - drm_rect_width(src),
 				     drm_rect_height(dst) * vscale - drm_rect_height(src));
-
+skip_adjust:
 		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
 				    state->base.rotation);
 
@@ -1100,6 +1103,9 @@ intel_check_sprite_plane(struct intel_plane *plane,
 		}
 	}
 
+	if (state->base.fb && fb->format->format == DRM_FORMAT_NV12)
+		goto out;
+
 	if (state->base.visible) {
 		src->x1 = src_x << 16;
 		src->x2 = (src_x + src_w) << 16;
@@ -1111,7 +1117,7 @@ intel_check_sprite_plane(struct intel_plane *plane,
 	dst->x2 = crtc_x + crtc_w;
 	dst->y1 = crtc_y;
 	dst->y2 = crtc_y + crtc_h;
-
+out:
 	if (INTEL_GEN(dev_priv) >= 9) {
 		ret = skl_check_plane_surface(crtc_state, state);
 		if (ret)
-- 
2.7.4



More information about the Intel-gfx-trybot mailing list