diff mbox

[3/7] drm/i915: Panel fitting calculation for GEN9

Message ID 1472533261-30306-4-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
No boundary condition was checked while calculating pipe scaler size
in pch_panel_fitting(), which might result in blank out or
corruptions for invalid values. This patch fixes this by adding
appropriate checks and calculation for each fitting mode.

Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti@intel.com>
---
 drivers/gpu/drm/i915/intel_panel.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 96c65d7..b5ea1b6 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -107,18 +107,36 @@  intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 {
 	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	int x = 0, y = 0, width = 0, height = 0;
+	bool downscale = false;
 
 	/* 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)
 		goto done;
 
+	/* Downscale pfiter */
+	if (IS_GEN9(intel_crtc->base.dev) &&
+	     (adjusted_mode->hdisplay < pipe_config->pipe_src_w ||
+	    adjusted_mode->vdisplay < pipe_config->pipe_src_h))
+		downscale = true;
+
 	switch (fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
 		width = pipe_config->pipe_src_w;
 		height = pipe_config->pipe_src_h;
 		x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
 		y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
+
+		if (downscale) {
+			if (x < 0) {
+				x = 0;
+				width = adjusted_mode->hdisplay;
+			}
+			if (y < 0) {
+				y = 0;
+				height = adjusted_mode->vdisplay;
+			}
+		}
 		break;
 
 	case DRM_MODE_SCALE_ASPECT:
@@ -132,14 +150,26 @@  intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 				width = scaled_height / pipe_config->pipe_src_h;
 				if (width & 1)
 					width++;
-				x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
+				if (adjusted_mode->hdisplay > width) {
+					x = (adjusted_mode->hdisplay -
+					     width + 1) / 2;
+				} else if (downscale) {
+					width = adjusted_mode->hdisplay;
+					x = 0;
+				}
 				y = 0;
 				height = adjusted_mode->crtc_vdisplay;
 			} else if (scaled_width < scaled_height) { /* letter */
 				height = scaled_width / pipe_config->pipe_src_w;
 				if (height & 1)
 				    height++;
-				y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
+				if (adjusted_mode->vdisplay > height) {
+					y = (adjusted_mode->vdisplay -
+					     height + 1) / 2;
+				} else if (downscale) {
+					height = adjusted_mode->vdisplay;
+					y = 0;
+				}
 				x = 0;
 				width = adjusted_mode->crtc_hdisplay;
 			} else {