aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_plane.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_plane.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c62
1 files changed, 57 insertions, 5 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index e1f94b746bd7..60b877a388c2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -9,9 +9,9 @@
*
*/
-#include "drmP.h"
+#include <drm/drmP.h>
-#include "exynos_drm.h"
+#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_fb.h"
@@ -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,
@@ -47,7 +83,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
- nr = exynos_drm_format_num_buffers(fb->pixel_format);
+ nr = exynos_drm_fb_get_buf_cnt(fb);
for (i = 0; i < nr; i++) {
struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
@@ -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;