[PATCH 9/9] drm/i915: Add windowing for primary planes on gen2/3 and chv

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

 



From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

Plane B and C (note that we don't actually expose plane C currently)
on gen2/3 have a window generator, as does the primary plane on CHV
pipe B. So let's allow positioning of these planes freely within the
pipe source area.

Plane A on gen2/3 seems to have some kind of partial window generator
which would allow you to cut the plane off midway through the scanout,
but it would still have to start at the top-left corner of the pipe,
and it would have to be full width. That's doesn't sound all that
useful, so for simplicity let's just keep to the idea that plane A
has to be fullscreen.

Gen4 removed the plane A/B windowing support entirely, and it wasn't
reintroduced until SKL (apart from the CHV pipe B special case).

Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_display.c | 43 ++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 622b487629d7..595b46255dd2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3236,6 +3236,10 @@ static void i9xx_update_plane(struct intel_plane *plane,
 	i915_reg_t reg = DSPCNTR(plane_id);
 	int x = plane_state->main.x;
 	int y = plane_state->main.y;
+	int crtc_x = plane_state->base.dst.x1;
+	int crtc_y = plane_state->base.dst.y1;
+	int crtc_w = drm_rect_width(&plane_state->base.dst);
+	int crtc_h = drm_rect_height(&plane_state->base.dst);
 	unsigned long irqflags;
 
 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -3251,18 +3255,18 @@ static void i9xx_update_plane(struct intel_plane *plane,
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
 	if (INTEL_GEN(dev_priv) < 4) {
-		/* pipesrc and dspsize control the size that is scaled from,
-		 * which should always be the user's requested size.
+		/*
+		 * PLANE_A doesn't actually have a full window
+		 * generator but let's assume we still need to
+		 * program whatever is there.
 		 */
+		I915_WRITE_FW(DSPPOS(plane_id), (crtc_y << 16) | crtc_x);
 		I915_WRITE_FW(DSPSIZE(plane_id),
-			      ((crtc_state->pipe_src_h - 1) << 16) |
-			      (crtc_state->pipe_src_w - 1));
-		I915_WRITE_FW(DSPPOS(plane_id), 0);
+			      ((crtc_h - 1) << 16) | (crtc_w - 1));
 	} else if (IS_CHERRYVIEW(dev_priv) && plane_id == PLANE_B) {
+		I915_WRITE_FW(PRIMPOS(plane_id), (crtc_y << 16) | crtc_x);
 		I915_WRITE_FW(PRIMSIZE(plane_id),
-			      ((crtc_state->pipe_src_h - 1) << 16) |
-			      (crtc_state->pipe_src_w - 1));
-		I915_WRITE_FW(PRIMPOS(plane_id), 0);
+			      ((crtc_h - 1) << 16) | (crtc_w - 1));
 		I915_WRITE_FW(PRIMCNSTALPHA(plane_id), 0);
 	}
 
@@ -12737,6 +12741,15 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
 	return max_scale;
 }
 
+static bool intel_primary_plane_has_windowing(struct intel_plane *plane)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+	return INTEL_GEN(dev_priv) >= 9 ||
+		(IS_CHERRYVIEW(dev_priv) && plane->plane == PLANE_B) ||
+		(INTEL_GEN(dev_priv) < 4 && plane->plane != PLANE_A);
+}
+
 static int
 intel_check_primary_plane(struct intel_plane *plane,
 			  struct intel_crtc_state *crtc_state,
@@ -12746,16 +12759,14 @@ intel_check_primary_plane(struct intel_plane *plane,
 	struct drm_crtc *crtc = state->base.crtc;
 	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
 	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
-	bool can_position = false;
+	bool can_position = intel_primary_plane_has_windowing(plane);
 	int ret;
 
-	if (INTEL_GEN(dev_priv) >= 9) {
-		/* use scaler when colorkey is not required */
-		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
-			min_scale = 1;
-			max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
-		}
-		can_position = true;
+	/* use scaler when colorkey is not required */
+	if (INTEL_GEN(dev_priv) >= 9 &&
+	    state->ckey.flags == I915_SET_COLORKEY_NONE) {
+		min_scale = 1;
+		max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
 	}
 
 	ret = drm_plane_helper_check_state(&state->base,
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://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