Commit 58560890 authored by Rob Clark's avatar Rob Clark

drm/msm/mdp5: fix cursor ROI

If cursor is set near the edge of the screen, it is not valid to use the
new cursor width/height as the ROI dimensions.  Split out the ROI calc
and use it both cursor_set and cursor_move.
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 5b2e2b6c
...@@ -62,8 +62,8 @@ struct mdp5_crtc { ...@@ -62,8 +62,8 @@ struct mdp5_crtc {
/* current cursor being scanned out: */ /* current cursor being scanned out: */
struct drm_gem_object *scanout_bo; struct drm_gem_object *scanout_bo;
uint32_t width; uint32_t width, height;
uint32_t height; uint32_t x, y;
} cursor; } cursor;
}; };
#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
...@@ -411,6 +411,32 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc, ...@@ -411,6 +411,32 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc,
return -EINVAL; return -EINVAL;
} }
static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
uint32_t xres = crtc->mode.hdisplay;
uint32_t yres = crtc->mode.vdisplay;
/*
* Cursor Region Of Interest (ROI) is a plane read from cursor
* buffer to render. The ROI region is determined by the visibility of
* the cursor point. In the default Cursor image the cursor point will
* be at the top left of the cursor image, unless it is specified
* otherwise using hotspot feature.
*
* If the cursor point reaches the right (xres - x < cursor.width) or
* bottom (yres - y < cursor.height) boundary of the screen, then ROI
* width and ROI height need to be evaluated to crop the cursor image
* accordingly.
* (xres-x) will be new cursor width when x > (xres - cursor.width)
* (yres-y) will be new cursor height when y > (yres - cursor.height)
*/
*roi_w = min(mdp5_crtc->cursor.width, xres -
mdp5_crtc->cursor.x);
*roi_h = min(mdp5_crtc->cursor.height, yres -
mdp5_crtc->cursor.y);
}
static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file, uint32_t handle, struct drm_file *file, uint32_t handle,
uint32_t width, uint32_t height) uint32_t width, uint32_t height)
...@@ -424,6 +450,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -424,6 +450,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
unsigned int depth; unsigned int depth;
enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
uint32_t roi_w, roi_h;
unsigned long flags; unsigned long flags;
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
...@@ -454,6 +481,12 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -454,6 +481,12 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
old_bo = mdp5_crtc->cursor.scanout_bo; old_bo = mdp5_crtc->cursor.scanout_bo;
mdp5_crtc->cursor.scanout_bo = cursor_bo;
mdp5_crtc->cursor.width = width;
mdp5_crtc->cursor.height = height;
get_roi(crtc, &roi_w, &roi_h);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
...@@ -461,19 +494,15 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -461,19 +494,15 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
MDP5_LM_CURSOR_SIZE_ROI_H(height) | MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
MDP5_LM_CURSOR_SIZE_ROI_W(width)); MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr);
blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN; blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN;
blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
mdp5_crtc->cursor.scanout_bo = cursor_bo;
mdp5_crtc->cursor.width = width;
mdp5_crtc->cursor.height = height;
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true); ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true);
...@@ -497,8 +526,6 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ...@@ -497,8 +526,6 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
struct mdp5_kms *mdp5_kms = get_kms(crtc); struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
uint32_t xres = crtc->mode.hdisplay;
uint32_t yres = crtc->mode.vdisplay;
uint32_t roi_w; uint32_t roi_w;
uint32_t roi_h; uint32_t roi_h;
unsigned long flags; unsigned long flags;
...@@ -507,25 +534,10 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ...@@ -507,25 +534,10 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
if (unlikely(!crtc->state->enable)) if (unlikely(!crtc->state->enable))
return 0; return 0;
x = (x > 0) ? x : 0; mdp5_crtc->cursor.x = x = max(x, 0);
y = (y > 0) ? y : 0; mdp5_crtc->cursor.y = y = max(y, 0);
/* get_roi(crtc, &roi_w, &roi_h);
* Cursor Region Of Interest (ROI) is a plane read from cursor
* buffer to render. The ROI region is determined by the visiblity of
* the cursor point. In the default Cursor image the cursor point will
* be at the top left of the cursor image, unless it is specified
* otherwise using hotspot feature.
*
* If the cursor point reaches the right (xres - x < cursor.width) or
* bottom (yres - y < cursor.height) boundary of the screen, then ROI
* width and ROI height need to be evaluated to crop the cursor image
* accordingly.
* (xres-x) will be new cursor width when x > (xres - cursor.width)
* (yres-y) will be new cursor height when y > (yres - cursor.height)
*/
roi_w = min(mdp5_crtc->cursor.width, xres - x);
roi_h = min(mdp5_crtc->cursor.height, yres - y);
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm),
......
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