Commit 2ab97921 authored by Joonyoung Shim's avatar Joonyoung Shim Committed by Inki Dae
Browse files

drm/exynos: fix to calculate CRTC shown via screen



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: default avatarJoonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 58f6aad7
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -32,6 +32,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,
@@ -64,8 +100,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;