aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-06-15 05:17:57 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-07-15 11:45:29 -0400
commit98fb74f4ecb8a70c75d7cfcfec17432cb0db2f5d (patch)
treef56f9d8532acebc2e83b9f432ab9f5dc7dada067
parent0481c8c47f5e858bfc020a825fd178004c14702d (diff)
drm/armada: convert overlay to use drm_plane_helper_check_update()
Use drm_plane_helper_check_update() rather than our own code to validate and limit the size of the displayed image. As we are able to support scaling, permit the full scaling ability. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index f026ba062456..d7df34f3d504 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -7,6 +7,7 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 */ 8 */
9#include <drm/drmP.h> 9#include <drm/drmP.h>
10#include <drm/drm_plane_helper.h>
10#include "armada_crtc.h" 11#include "armada_crtc.h"
11#include "armada_drm.h" 12#include "armada_drm.h"
12#include "armada_fb.h" 13#include "armada_fb.h"
@@ -89,16 +90,6 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
89 wake_up(&dplane->vbl.wait); 90 wake_up(&dplane->vbl.wait);
90} 91}
91 92
92static unsigned armada_limit(int start, unsigned size, unsigned max)
93{
94 int end = start + size;
95 if (end < 0)
96 return 0;
97 if (start < 0)
98 start = 0;
99 return (unsigned)end > max ? max - start : end - start;
100}
101
102static int 93static int
103armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, 94armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
104 struct drm_framebuffer *fb, 95 struct drm_framebuffer *fb,
@@ -107,26 +98,39 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
107{ 98{
108 struct armada_plane *dplane = drm_to_armada_plane(plane); 99 struct armada_plane *dplane = drm_to_armada_plane(plane);
109 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 100 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
101 struct drm_rect src = {
102 .x1 = src_x,
103 .y1 = src_y,
104 .x2 = src_x + src_w,
105 .y2 = src_y + src_h,
106 };
107 struct drm_rect dest = {
108 .x1 = crtc_x,
109 .y1 = crtc_y,
110 .x2 = crtc_x + crtc_w,
111 .y2 = crtc_y + crtc_h,
112 };
113 const struct drm_rect clip = {
114 .x2 = crtc->mode.hdisplay,
115 .y2 = crtc->mode.vdisplay,
116 };
110 uint32_t val, ctrl0; 117 uint32_t val, ctrl0;
111 unsigned idx = 0; 118 unsigned idx = 0;
119 bool visible;
112 int ret; 120 int ret;
113 121
114 crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); 122 ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip,
115 crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); 123 0, INT_MAX, true, false, &visible);
124 if (ret)
125 return ret;
126
116 ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | 127 ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
117 CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | 128 CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
118 CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; 129 CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA;
119 130
120 /* Does the position/size result in nothing to display? */ 131 /* Does the position/size result in nothing to display? */
121 if (crtc_w == 0 || crtc_h == 0) { 132 if (!visible)
122 ctrl0 &= ~CFG_DMA_ENA; 133 ctrl0 &= ~CFG_DMA_ENA;
123 }
124
125 /*
126 * FIXME: if the starting point is off screen, we need to
127 * adjust src_x, src_y, src_w, src_h appropriately, and
128 * according to the scale.
129 */
130 134
131 if (!dcrtc->plane) { 135 if (!dcrtc->plane) {
132 dcrtc->plane = plane; 136 dcrtc->plane = plane;
@@ -136,15 +140,19 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
136 /* FIXME: overlay on an interlaced display */ 140 /* FIXME: overlay on an interlaced display */
137 /* Just updating the position/size? */ 141 /* Just updating the position/size? */
138 if (plane->fb == fb && dplane->ctrl0 == ctrl0) { 142 if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
139 val = (src_h & 0xffff0000) | src_w >> 16; 143 val = (drm_rect_height(&src) & 0xffff0000) |
144 drm_rect_width(&src) >> 16;
140 dplane->src_hw = val; 145 dplane->src_hw = val;
141 writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 146 writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
142 val = crtc_h << 16 | crtc_w; 147
148 val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
143 dplane->dst_hw = val; 149 dplane->dst_hw = val;
144 writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 150 writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
145 val = crtc_y << 16 | crtc_x; 151
152 val = dest.y1 << 16 | dest.x1;
146 dplane->dst_yx = val; 153 dplane->dst_yx = val;
147 writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); 154 writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
155
148 return 0; 156 return 0;
149 } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { 157 } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
150 /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ 158 /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
@@ -178,8 +186,8 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
178 older_fb); 186 older_fb);
179 } 187 }
180 188
181 src_y >>= 16; 189 src_y = src.y1 >> 16;
182 src_x >>= 16; 190 src_x = src.x1 >> 16;
183 sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] + 191 sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] +
184 src_x * fb->bits_per_pixel / 8; 192 src_x * fb->bits_per_pixel / 8;
185 su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] + 193 su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] +
@@ -208,24 +216,27 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
208 LCD_SPU_DMA_PITCH_UV); 216 LCD_SPU_DMA_PITCH_UV);
209 } 217 }
210 218
211 val = (src_h & 0xffff0000) | src_w >> 16; 219 val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16;
212 if (dplane->src_hw != val) { 220 if (dplane->src_hw != val) {
213 dplane->src_hw = val; 221 dplane->src_hw = val;
214 armada_reg_queue_set(dplane->vbl.regs, idx, val, 222 armada_reg_queue_set(dplane->vbl.regs, idx, val,
215 LCD_SPU_DMA_HPXL_VLN); 223 LCD_SPU_DMA_HPXL_VLN);
216 } 224 }
217 val = crtc_h << 16 | crtc_w; 225
226 val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
218 if (dplane->dst_hw != val) { 227 if (dplane->dst_hw != val) {
219 dplane->dst_hw = val; 228 dplane->dst_hw = val;
220 armada_reg_queue_set(dplane->vbl.regs, idx, val, 229 armada_reg_queue_set(dplane->vbl.regs, idx, val,
221 LCD_SPU_DZM_HPXL_VLN); 230 LCD_SPU_DZM_HPXL_VLN);
222 } 231 }
223 val = crtc_y << 16 | crtc_x; 232
233 val = dest.y1 << 16 | dest.x1;
224 if (dplane->dst_yx != val) { 234 if (dplane->dst_yx != val) {
225 dplane->dst_yx = val; 235 dplane->dst_yx = val;
226 armada_reg_queue_set(dplane->vbl.regs, idx, val, 236 armada_reg_queue_set(dplane->vbl.regs, idx, val,
227 LCD_SPU_DMA_OVSA_HPXL_VLN); 237 LCD_SPU_DMA_OVSA_HPXL_VLN);
228 } 238 }
239
229 if (dplane->ctrl0 != ctrl0) { 240 if (dplane->ctrl0 != ctrl0) {
230 dplane->ctrl0 = ctrl0; 241 dplane->ctrl0 = ctrl0;
231 armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, 242 armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,