diff mbox

[5/7] drm/i915: Add pipe scaler co-ordinate and size property for Gen9

Message ID 1472533261-30306-6-git-send-email-nabendu.bikash.maiti@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Nabendu Maiti Aug. 30, 2016, 5 a.m. UTC
Adding pipe destination co-ordinate and size property as crtc atomic drm
property to dynamically change pipe destination attributes on GEN9.

Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti@intel.com>
---
 drivers/gpu/drm/drm_atomic.c         | 20 +++++++++++
 drivers/gpu/drm/drm_crtc.c           | 32 +++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c | 70 +++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 include/drm/drm_crtc.h               |  5 +++
 include/uapi/drm/drm_mode.h          |  1 +
 6 files changed, 126 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3fddfa4..3df78c0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -502,6 +502,18 @@  int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 	} else if (property == config->prop_fitting_mode) {
 		state->fitting_mode = val;
 		state->pipescaler_changed = true;
+	} else if (property == config->prop_pipe_dst_x) {
+		state->dst_x = val;
+		state->pipescaler_changed = true;
+	} else if (property == config->prop_pipe_dst_y) {
+		state->dst_y = val;
+		state->pipescaler_changed = true;
+	} else if (property == config->prop_pipe_dst_w) {
+		state->dst_w = val;
+		state->pipescaler_changed = true;
+	} else if (property == config->prop_pipe_dst_h) {
+		state->dst_h = val;
+		state->pipescaler_changed = true;
 	} else if (crtc->funcs->atomic_set_property)
 		return crtc->funcs->atomic_set_property(crtc, state, property, val);
 	else
@@ -550,6 +562,14 @@  drm_atomic_crtc_get_property(struct drm_crtc *crtc,
 		*val =  state->src_h;
 	else if (property == config->prop_fitting_mode)
 		*val = state->fitting_mode;
+	else if (property == config->prop_pipe_dst_x)
+		*val = state->dst_x;
+	else if (property == config->prop_pipe_dst_y)
+		*val = state->dst_y;
+	else if (property == config->prop_pipe_dst_w)
+		*val = state->dst_w;
+	else if (property == config->prop_pipe_dst_h)
+		*val = state->dst_h;
 	else if (crtc->funcs->atomic_get_property)
 		return crtc->funcs->atomic_get_property(crtc, state, property, val);
 	else
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index b24e839..c941f58 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -383,6 +383,14 @@  int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
 					   config->prop_pipe_src_h, 0);
 		drm_object_attach_property(&crtc->base,
 					   config->prop_fitting_mode, 0);
+		drm_object_attach_property(&crtc->base,
+					   config->prop_pipe_dst_x, 0);
+		drm_object_attach_property(&crtc->base,
+					   config->prop_pipe_dst_y, 0);
+		drm_object_attach_property(&crtc->base,
+					   config->prop_pipe_dst_w, 0);
+		drm_object_attach_property(&crtc->base,
+					   config->prop_pipe_dst_h, 0);
 	}
 
 	return 0;
@@ -967,6 +975,30 @@  static int drm_mode_create_standard_properties(struct drm_device *dev)
 		return -ENOMEM;
 	dev->mode_config.prop_fitting_mode = prop;
 
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"PIPE_DST_X", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_pipe_dst_x = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"PIPE_DST_Y", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_pipe_dst_y = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"PIPE_DST_W", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_pipe_dst_w = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"PIPE_DST_H", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_pipe_dst_h = prop;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e3ecb8b..9c7434f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12548,6 +12548,35 @@  static bool check_single_encoder_cloning(struct drm_atomic_state *state,
 	return true;
 }
 
+void
+intel_gen9_pipe_scale(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *pipe_config,
+			int fitting_mode)
+{
+	const struct drm_display_mode *adjusted_mode =
+		&pipe_config->base.adjusted_mode;
+	int x = 0, y = 0, width = 0, height = 0;
+
+	/* Native modes don't need fitting */
+	if ((adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
+	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) &&
+	   ((pipe_config->pipe_dst_x + pipe_config->pipe_dst_w) ==
+	    pipe_config->pipe_src_w) &&
+	   ((pipe_config->pipe_dst_y + pipe_config->pipe_dst_h) ==
+	    pipe_config->pipe_src_w))
+		goto done;
+
+	x = pipe_config->pipe_dst_x;
+	y = pipe_config->pipe_dst_y;
+	width = pipe_config->pipe_dst_w;
+	height = pipe_config->pipe_dst_h;
+
+done:
+	pipe_config->pch_pfit.pos = (x << 16) | y;
+	pipe_config->pch_pfit.size = (width << 16) | height;
+	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
+}
+
 static int skylake_pfiter_calculate(struct drm_crtc *crtc,
 				   struct drm_crtc_state *crtc_state)
 {
@@ -12560,16 +12589,36 @@  static int skylake_pfiter_calculate(struct drm_crtc *crtc,
 	if (((pipe_config->pipe_scaling_mode !=
 	      intel_crtc->config->pipe_scaling_mode) ||
 	     (pipe_config->pipe_src_w != intel_crtc->config->pipe_src_w) ||
-	     (pipe_config->pipe_src_h != intel_crtc->config->pipe_src_h)) &&
+	     (pipe_config->pipe_src_h != intel_crtc->config->pipe_src_h) ||
+	     (pipe_config->pipe_dst_x != intel_crtc->config->pipe_dst_x) ||
+	     (pipe_config->pipe_dst_y != intel_crtc->config->pipe_dst_y) ||
+	     (pipe_config->pipe_dst_w != intel_crtc->config->pipe_dst_w) ||
+	     (pipe_config->pipe_dst_h != intel_crtc->config->pipe_dst_h)) &&
 	    (!mode_changed)) {
 		pipe_config->update_pipe = true;
 	}
 
 	if ((mode_changed) || (pipe_config->update_pipe)) {
 		ret = skl_update_scaler_crtc(pipe_config);
-		if (!ret)
-			intel_pch_panel_fitting(intel_crtc, pipe_config,
-						pipe_config->pipe_scaling_mode);
+		if (!ret) {
+			if (pipe_config->pipe_scaling_mode ==
+			    DRM_MODE_SCALE_CUSTOM) {
+				intel_gen9_pipe_scale(intel_crtc, pipe_config,
+					pipe_config->pipe_scaling_mode);
+			} else {
+				intel_pch_panel_fitting(intel_crtc,
+							pipe_config,
+					pipe_config->pipe_scaling_mode);
+				pipe_config->pipe_dst_x =
+					(pipe_config->pch_pfit.pos >> 16);
+				pipe_config->pipe_dst_y =
+					(pipe_config->pch_pfit.pos & 0xffff);
+				pipe_config->pipe_dst_w =
+					(pipe_config->pch_pfit.size >> 16);
+				pipe_config->pipe_dst_h =
+					(pipe_config->pch_pfit.size & 0xffff);
+			}
+		}
 	}
 	return ret;
 }
@@ -13045,6 +13094,10 @@  intel_modeset_pipe_config(struct drm_crtc *crtc,
 		pipe_config->output_types |= 1 << encoder->type;
 	}
 
+	pipe_config->pipe_dst_w = pipe_config->pipe_src_w;
+	pipe_config->pipe_dst_h = pipe_config->pipe_src_h;
+
+
 encoder_retry:
 	/* Ensure the port clock defaults are reset when retrying. */
 	pipe_config->port_clock = 0;
@@ -14028,11 +14081,20 @@  static int intel_atomic_check(struct drm_device *dev,
 
 				crtc_state->src_w = adjusted_mode->hdisplay;
 				crtc_state->src_h = adjusted_mode->vdisplay;
+				crtc_state->dst_w = adjusted_mode->hdisplay;
+				crtc_state->dst_h = adjusted_mode->vdisplay;
+				crtc_state->dst_x =  0;
+				crtc_state->dst_y =  0;
+				crtc_state->fitting_mode = 0;
 			}
 			pipe_config->pipe_src_w = crtc_state->src_w;
 			pipe_config->pipe_src_h = crtc_state->src_h;
 			pipe_config->pipe_scaling_mode =
 				crtc_state->fitting_mode;
+			pipe_config->pipe_dst_x = crtc_state->dst_x;
+			pipe_config->pipe_dst_y = crtc_state->dst_y;
+			pipe_config->pipe_dst_w = crtc_state->dst_w;
+			pipe_config->pipe_dst_h = crtc_state->dst_h;
 			crtc_state->pipescaler_changed = false;
 		}
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 189856c..eab05d5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -533,6 +533,8 @@  struct intel_crtc_state {
 	 * and get clipped at the edges. */
 	int pipe_src_w, pipe_src_h;
 	u32 pipe_scaling_mode;
+	int pipe_dst_x, pipe_dst_y;
+	int pipe_dst_w, pipe_dst_h;
 
 	/* Whether to set up the PCH/FDI. Note that we never allow sharing
 	 * between pch encoders and cpu encoders. */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e245746..99ff789 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -201,6 +201,7 @@  struct drm_crtc_state {
 	bool pipescaler_changed;
 	u32 src_w, src_h;
 	u32 fitting_mode;
+	u32 dst_x, dst_y, dst_w, dst_h;
 };
 
 /**
@@ -1950,6 +1951,10 @@  struct drm_mode_config {
 	struct drm_property *prop_pipe_src_w;
 	struct drm_property *prop_pipe_src_h;
 	struct drm_property *prop_fitting_mode;
+	struct drm_property *prop_pipe_dst_x;
+	struct drm_property *prop_pipe_dst_y;
+	struct drm_property *prop_pipe_dst_w;
+	struct drm_property *prop_pipe_dst_h;
 
 	/**
 	 * @dvi_i_subconnector_property: Optional DVI-I property to
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 49a7265..91bd0f7 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -91,6 +91,7 @@  extern "C" {
 #define DRM_MODE_SCALE_FULLSCREEN	1 /* Full screen, ignore aspect */
 #define DRM_MODE_SCALE_CENTER		2 /* Centered, no scaling */
 #define DRM_MODE_SCALE_ASPECT		3 /* Full screen, preserve aspect */
+#define DRM_MODE_SCALE_CUSTOM		4 /* Custom pipe scaling */
 
 /* Picture aspect ratio options */
 #define DRM_MODE_PICTURE_ASPECT_NONE	0