[PATCH] drm/exynos: fix to calculate CRTC shown via screen

Joonyoung Shim jy0922.shim at samsung.com
Thu Sep 27 03:25:21 PDT 2012


This patch is to exactly calculate CRTC shown via screen for all cases.
Refer exynos_plane_get_size() function for this. Also source position of
fb is fixed when start position of CRTC is negative number.

Signed-off-by: Joonyoung Shim <jy0922.shim at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_plane.c |   56 +++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 777e142..4a03d1c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -33,6 +33,42 @@ static const uint32_t formats[] = {
 	DRM_FORMAT_NV12MT,
 };
 
+/*
+ * This function is to get X or Y size shown via screen. This needs length and
+ * start position of CRTC.
+ *
+ *      <--- length --->
+ * CRTC ----------------
+ *      ^ start        ^ end
+ *
+ * There are six cases from a to b.
+ *
+ *             <----- SCREEN ----->
+ *             0                 last
+ *   ----------|------------------|----------
+ * CRTCs
+ * a -------
+ *        b -------
+ *        c --------------------------
+ *                 d --------
+ *                           e -------
+ *                                  f -------
+ */
+static int exynos_plane_get_size(int start, unsigned length, unsigned last)
+{
+	int end = start + length;
+	int size = 0;
+
+	if (start <= 0) {
+		if (end > 0)
+			size = min_t(unsigned, end, last);
+	} else if (start <= last) {
+		size = min_t(unsigned, last - start, length);
+	}
+
+	return size;
+}
+
 int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 			  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
 			  unsigned int crtc_w, unsigned int crtc_h,
@@ -65,8 +101,24 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 				(unsigned long)overlay->dma_addr[i]);
 	}
 
-	actual_w = min((unsigned)(crtc->mode.hdisplay - crtc_x), crtc_w);
-	actual_h = min((unsigned)(crtc->mode.vdisplay - crtc_y), crtc_h);
+	actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
+	actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
+
+	if (crtc_x < 0) {
+		if (actual_w)
+			src_x -= crtc_x;
+		else
+			src_x += crtc_w;
+		crtc_x = 0;
+	}
+
+	if (crtc_y < 0) {
+		if (actual_h)
+			src_y -= crtc_y;
+		else
+			src_y += crtc_h;
+		crtc_y = 0;
+	}
 
 	/* set drm framebuffer data. */
 	overlay->fb_x = src_x;
-- 
1.7.9.5



More information about the dri-devel mailing list