From 2ab97921786f614bc9296722d8a2e2ce32d1760b Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 27 Sep 2012 19:25:21 +0900 Subject: 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: Joonyoung Shim Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 56 +++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8c3036dd512b..2a27b5678893 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -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; -- cgit v1.2.3