diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_plane.c')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 03b472b43013..60b877a388c2 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[] = { | |||
| 32 | DRM_FORMAT_NV12MT, | 32 | DRM_FORMAT_NV12MT, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | /* | ||
| 36 | * This function is to get X or Y size shown via screen. This needs length and | ||
| 37 | * start position of CRTC. | ||
| 38 | * | ||
| 39 | * <--- length ---> | ||
| 40 | * CRTC ---------------- | ||
| 41 | * ^ start ^ end | ||
| 42 | * | ||
| 43 | * There are six cases from a to b. | ||
| 44 | * | ||
| 45 | * <----- SCREEN -----> | ||
| 46 | * 0 last | ||
| 47 | * ----------|------------------|---------- | ||
| 48 | * CRTCs | ||
| 49 | * a ------- | ||
| 50 | * b ------- | ||
| 51 | * c -------------------------- | ||
| 52 | * d -------- | ||
| 53 | * e ------- | ||
| 54 | * f ------- | ||
| 55 | */ | ||
| 56 | static int exynos_plane_get_size(int start, unsigned length, unsigned last) | ||
| 57 | { | ||
| 58 | int end = start + length; | ||
| 59 | int size = 0; | ||
| 60 | |||
| 61 | if (start <= 0) { | ||
| 62 | if (end > 0) | ||
| 63 | size = min_t(unsigned, end, last); | ||
| 64 | } else if (start <= last) { | ||
| 65 | size = min_t(unsigned, last - start, length); | ||
| 66 | } | ||
| 67 | |||
| 68 | return size; | ||
| 69 | } | ||
| 70 | |||
| 35 | int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, | 71 | int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, |
| 36 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 72 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
| 37 | unsigned int crtc_w, unsigned int crtc_h, | 73 | 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, | |||
| 47 | 83 | ||
| 48 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 84 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
| 49 | 85 | ||
| 50 | nr = exynos_drm_format_num_buffers(fb->pixel_format); | 86 | nr = exynos_drm_fb_get_buf_cnt(fb); |
| 51 | for (i = 0; i < nr; i++) { | 87 | for (i = 0; i < nr; i++) { |
| 52 | struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); | 88 | struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); |
| 53 | 89 | ||
| @@ -64,8 +100,24 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, | |||
| 64 | (unsigned long)overlay->dma_addr[i]); | 100 | (unsigned long)overlay->dma_addr[i]); |
| 65 | } | 101 | } |
| 66 | 102 | ||
| 67 | actual_w = min((unsigned)(crtc->mode.hdisplay - crtc_x), crtc_w); | 103 | actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); |
| 68 | actual_h = min((unsigned)(crtc->mode.vdisplay - crtc_y), crtc_h); | 104 | actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay); |
| 105 | |||
| 106 | if (crtc_x < 0) { | ||
| 107 | if (actual_w) | ||
| 108 | src_x -= crtc_x; | ||
| 109 | else | ||
| 110 | src_x += crtc_w; | ||
| 111 | crtc_x = 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (crtc_y < 0) { | ||
| 115 | if (actual_h) | ||
| 116 | src_y -= crtc_y; | ||
| 117 | else | ||
| 118 | src_y += crtc_h; | ||
| 119 | crtc_y = 0; | ||
| 120 | } | ||
| 69 | 121 | ||
| 70 | /* set drm framebuffer data. */ | 122 | /* set drm framebuffer data. */ |
| 71 | overlay->fb_x = src_x; | 123 | overlay->fb_x = src_x; |
