]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
drm/armada: convert overlay to use drm_plane_helper_check_update()
authorRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 15 Jun 2015 09:17:57 +0000 (10:17 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 15 Jul 2015 15:45:29 +0000 (16:45 +0100)
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>
drivers/gpu/drm/armada/armada_overlay.c

index f026ba062456ea9eee953fd452bd0e927fdb56a7..d7df34f3d5042099caba8e197a52b068f987a58a 100644 (file)
@@ -7,6 +7,7 @@
  * published by the Free Software Foundation.
  */
 #include <drm/drmP.h>
+#include <drm/drm_plane_helper.h>
 #include "armada_crtc.h"
 #include "armada_drm.h"
 #include "armada_fb.h"
@@ -89,16 +90,6 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
        wake_up(&dplane->vbl.wait);
 }
 
-static unsigned armada_limit(int start, unsigned size, unsigned max)
-{
-       int end = start + size;
-       if (end < 0)
-               return 0;
-       if (start < 0)
-               start = 0;
-       return (unsigned)end > max ? max - start : end - start;
-}
-
 static int
 armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
        struct drm_framebuffer *fb,
@@ -107,26 +98,39 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 {
        struct armada_plane *dplane = drm_to_armada_plane(plane);
        struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+       struct drm_rect src = {
+               .x1 = src_x,
+               .y1 = src_y,
+               .x2 = src_x + src_w,
+               .y2 = src_y + src_h,
+       };
+       struct drm_rect dest = {
+               .x1 = crtc_x,
+               .y1 = crtc_y,
+               .x2 = crtc_x + crtc_w,
+               .y2 = crtc_y + crtc_h,
+       };
+       const struct drm_rect clip = {
+               .x2 = crtc->mode.hdisplay,
+               .y2 = crtc->mode.vdisplay,
+       };
        uint32_t val, ctrl0;
        unsigned idx = 0;
+       bool visible;
        int ret;
 
-       crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay);
-       crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay);
+       ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip,
+                                           0, INT_MAX, true, false, &visible);
+       if (ret)
+               return ret;
+
        ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
                CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
                CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA;
 
        /* Does the position/size result in nothing to display? */
-       if (crtc_w == 0 || crtc_h == 0) {
+       if (!visible)
                ctrl0 &= ~CFG_DMA_ENA;
-       }
-
-       /*
-        * FIXME: if the starting point is off screen, we need to
-        * adjust src_x, src_y, src_w, src_h appropriately, and
-        * according to the scale.
-        */
 
        if (!dcrtc->plane) {
                dcrtc->plane = plane;
@@ -136,15 +140,19 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
        /* FIXME: overlay on an interlaced display */
        /* Just updating the position/size? */
        if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
-               val = (src_h & 0xffff0000) | src_w >> 16;
+               val = (drm_rect_height(&src) & 0xffff0000) |
+                     drm_rect_width(&src) >> 16;
                dplane->src_hw = val;
                writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
-               val = crtc_h << 16 | crtc_w;
+
+               val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
                dplane->dst_hw = val;
                writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
-               val = crtc_y << 16 | crtc_x;
+
+               val = dest.y1 << 16 | dest.x1;
                dplane->dst_yx = val;
                writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
+
                return 0;
        } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
                /* 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,
                                                            older_fb);
                }
 
-               src_y >>= 16;
-               src_x >>= 16;
+               src_y = src.y1 >> 16;
+               src_x = src.x1 >> 16;
                sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] +
                        src_x * fb->bits_per_pixel / 8;
                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,
                                     LCD_SPU_DMA_PITCH_UV);
        }
 
-       val = (src_h & 0xffff0000) | src_w >> 16;
+       val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16;
        if (dplane->src_hw != val) {
                dplane->src_hw = val;
                armada_reg_queue_set(dplane->vbl.regs, idx, val,
                                     LCD_SPU_DMA_HPXL_VLN);
        }
-       val = crtc_h << 16 | crtc_w;
+
+       val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
        if (dplane->dst_hw != val) {
                dplane->dst_hw = val;
                armada_reg_queue_set(dplane->vbl.regs, idx, val,
                                     LCD_SPU_DZM_HPXL_VLN);
        }
-       val = crtc_y << 16 | crtc_x;
+
+       val = dest.y1 << 16 | dest.x1;
        if (dplane->dst_yx != val) {
                dplane->dst_yx = val;
                armada_reg_queue_set(dplane->vbl.regs, idx, val,
                                     LCD_SPU_DMA_OVSA_HPXL_VLN);
        }
+
        if (dplane->ctrl0 != ctrl0) {
                dplane->ctrl0 = ctrl0;
                armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,