Commit 98fb74f4 authored by Russell King's avatar Russell King

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 0481c8c4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_plane_helper.h>
#include "armada_crtc.h" #include "armada_crtc.h"
#include "armada_drm.h" #include "armada_drm.h"
#include "armada_fb.h" #include "armada_fb.h"
...@@ -89,16 +90,6 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) ...@@ -89,16 +90,6 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
wake_up(&dplane->vbl.wait); 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 static int
armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
...@@ -107,26 +98,39 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -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_plane *dplane = drm_to_armada_plane(plane);
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 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; uint32_t val, ctrl0;
unsigned idx = 0; unsigned idx = 0;
bool visible;
int ret; int ret;
crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip,
crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); 0, INT_MAX, true, false, &visible);
if (ret)
return ret;
ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA;
/* Does the position/size result in nothing to display? */ /* Does the position/size result in nothing to display? */
if (crtc_w == 0 || crtc_h == 0) { if (!visible)
ctrl0 &= ~CFG_DMA_ENA; 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) { if (!dcrtc->plane) {
dcrtc->plane = plane; dcrtc->plane = plane;
...@@ -136,15 +140,19 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -136,15 +140,19 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
/* FIXME: overlay on an interlaced display */ /* FIXME: overlay on an interlaced display */
/* Just updating the position/size? */ /* Just updating the position/size? */
if (plane->fb == fb && dplane->ctrl0 == ctrl0) { 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; dplane->src_hw = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 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; dplane->dst_hw = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 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; dplane->dst_yx = val;
writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
return 0; return 0;
} else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ /* 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,8 +186,8 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
older_fb); older_fb);
} }
src_y >>= 16; src_y = src.y1 >> 16;
src_x >>= 16; src_x = src.x1 >> 16;
sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] + sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] +
src_x * fb->bits_per_pixel / 8; src_x * fb->bits_per_pixel / 8;
su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] + 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,24 +216,27 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
LCD_SPU_DMA_PITCH_UV); 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) { if (dplane->src_hw != val) {
dplane->src_hw = val; dplane->src_hw = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val, armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DMA_HPXL_VLN); 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) { if (dplane->dst_hw != val) {
dplane->dst_hw = val; dplane->dst_hw = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val, armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DZM_HPXL_VLN); LCD_SPU_DZM_HPXL_VLN);
} }
val = crtc_y << 16 | crtc_x;
val = dest.y1 << 16 | dest.x1;
if (dplane->dst_yx != val) { if (dplane->dst_yx != val) {
dplane->dst_yx = val; dplane->dst_yx = val;
armada_reg_queue_set(dplane->vbl.regs, idx, val, armada_reg_queue_set(dplane->vbl.regs, idx, val,
LCD_SPU_DMA_OVSA_HPXL_VLN); LCD_SPU_DMA_OVSA_HPXL_VLN);
} }
if (dplane->ctrl0 != ctrl0) { if (dplane->ctrl0 != ctrl0) {
dplane->ctrl0 = ctrl0; dplane->ctrl0 = ctrl0;
armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment