Commit 3b6acf14 authored by Archit Taneja's avatar Archit Taneja Committed by Rob Clark

drm/msm/mdp5: Use plane helpers to configure src/dst rectangles

The MDP5 plane's atomic_check ops doesn't perform clipping tests.
This didn't hurt us much in the past, but clipping becomes important
with cursor planes.

Use drm_plane_helper_check_state, the way rockchip/intel/mtk drivers
already do. Use these drivers as reference.

Clipping requires knowledge of the crtc width and height. This requires
us to call drm_atomic_helper_check_modeset before
drm_atomic_helper_check_planes in the driver's atomic_check op, because
check_modetest will populate the mode for the crtc, needed to populate
the clip rectangle.

We update the plane_enabled(state) local helper to use state->visible,
since state->visible and 'state->fb && state->crtc' represent the same
thing.

One issue with the existing code is that we don't have a way to disable
the plane when it's completely clipped out. Until there isn't an update
on the crtc (which would de-stage the plane), we would still see the
plane in its last 'visible' configuration.
Signed-off-by: default avatarArchit Taneja <architt@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 106f9727
...@@ -29,10 +29,7 @@ struct mdp5_plane { ...@@ -29,10 +29,7 @@ struct mdp5_plane {
static int mdp5_plane_mode_set(struct drm_plane *plane, static int mdp5_plane_mode_set(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_crtc *crtc, struct drm_framebuffer *fb,
int crtc_x, int crtc_y, struct drm_rect *src, struct drm_rect *dest);
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
static void set_scanout_locked(struct drm_plane *plane, static void set_scanout_locked(struct drm_plane *plane,
struct drm_framebuffer *fb); struct drm_framebuffer *fb);
...@@ -45,7 +42,7 @@ static struct mdp5_kms *get_kms(struct drm_plane *plane) ...@@ -45,7 +42,7 @@ static struct mdp5_kms *get_kms(struct drm_plane *plane)
static bool plane_enabled(struct drm_plane_state *state) static bool plane_enabled(struct drm_plane_state *state)
{ {
return state->fb && state->crtc; return state->visible;
} }
static void mdp5_plane_destroy(struct drm_plane *plane) static void mdp5_plane_destroy(struct drm_plane *plane)
...@@ -272,6 +269,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane, ...@@ -272,6 +269,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
msm_framebuffer_cleanup(fb, mdp5_kms->id); msm_framebuffer_cleanup(fb, mdp5_kms->id);
} }
#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
static int mdp5_plane_atomic_check(struct drm_plane *plane, static int mdp5_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
...@@ -281,10 +279,19 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, ...@@ -281,10 +279,19 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
bool new_hwpipe = false; bool new_hwpipe = false;
uint32_t max_width, max_height; uint32_t max_width, max_height;
uint32_t caps = 0; uint32_t caps = 0;
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
struct drm_rect clip;
int min_scale, max_scale;
int ret;
DBG("%s: check (%d -> %d)", plane->name, DBG("%s: check (%d -> %d)", plane->name,
plane_enabled(old_state), plane_enabled(state)); plane_enabled(old_state), plane_enabled(state));
crtc = state->crtc ? state->crtc : plane->state->crtc;
if (!crtc)
return 0;
max_width = config->hw->lm.max_width << 16; max_width = config->hw->lm.max_width << 16;
max_height = config->hw->lm.max_height << 16; max_height = config->hw->lm.max_height << 16;
...@@ -296,6 +303,22 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, ...@@ -296,6 +303,22 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
return -ERANGE; return -ERANGE;
} }
crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
if (WARN_ON(!crtc_state))
return -EINVAL;
clip.x1 = 0;
clip.y1 = 0;
clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay;
min_scale = FRAC_16_16(1, 8);
max_scale = FRAC_16_16(8, 1);
ret = drm_plane_helper_check_state(state, &clip, min_scale,
max_scale, true, true);
if (ret)
return ret;
if (plane_enabled(state)) { if (plane_enabled(state)) {
unsigned int rotation; unsigned int rotation;
const struct mdp_format *format; const struct mdp_format *format;
...@@ -368,10 +391,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, ...@@ -368,10 +391,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
ret = mdp5_plane_mode_set(plane, ret = mdp5_plane_mode_set(plane,
state->crtc, state->fb, state->crtc, state->fb,
state->crtc_x, state->crtc_y, &state->src, &state->dst);
state->crtc_w, state->crtc_h,
state->src_x, state->src_y,
state->src_w, state->src_h);
/* atomic_check should have ensured that this doesn't fail */ /* atomic_check should have ensured that this doesn't fail */
WARN_ON(ret < 0); WARN_ON(ret < 0);
} }
...@@ -664,10 +684,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, ...@@ -664,10 +684,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
static int mdp5_plane_mode_set(struct drm_plane *plane, static int mdp5_plane_mode_set(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_crtc *crtc, struct drm_framebuffer *fb,
int crtc_x, int crtc_y, struct drm_rect *src, struct drm_rect *dest)
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{ {
struct drm_plane_state *pstate = plane->state; struct drm_plane_state *pstate = plane->state;
struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe; struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe;
...@@ -683,6 +700,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, ...@@ -683,6 +700,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
uint32_t pix_format; uint32_t pix_format;
unsigned int rotation; unsigned int rotation;
bool vflip, hflip; bool vflip, hflip;
int crtc_x, crtc_y;
unsigned int crtc_w, crtc_h;
uint32_t src_x, src_y;
uint32_t src_w, src_h;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -695,6 +716,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, ...@@ -695,6 +716,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
format = to_mdp_format(msm_framebuffer_format(fb)); format = to_mdp_format(msm_framebuffer_format(fb));
pix_format = format->base.pixel_format; pix_format = format->base.pixel_format;
src_x = src->x1;
src_y = src->y1;
src_w = drm_rect_width(src);
src_h = drm_rect_height(src);
crtc_x = dest->x1;
crtc_y = dest->y1;
crtc_w = drm_rect_width(dest);
crtc_h = drm_rect_height(dest);
/* src values are in Q16 fixed point, convert to integer: */ /* src values are in Q16 fixed point, convert to integer: */
src_x = src_x >> 16; src_x = src_x >> 16;
src_y = src_y >> 16; src_y = src_y >> 16;
......
...@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work) ...@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work)
complete_commit(container_of(work, struct msm_commit, work), true); complete_commit(container_of(work, struct msm_commit, work), true);
} }
/*
* this func is identical to the drm_atomic_helper_check, but we keep this
* because we might eventually need to have a more finegrained check
* sequence without using the atomic helpers.
*
* In the past, we first called drm_atomic_helper_check_planes, and then
* drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's
* ->atomic_check could update ->mode_changed for pixel format changes.
* This, however isn't needed now because if there is a pixel format change,
* we just assign a new hwpipe for it with a new SMP allocation. We might
* eventually hit a condition where we would need to do a full modeset if
* we run out of planes. There, we'd probably need to set mode_changed.
*/
int msm_atomic_check(struct drm_device *dev, int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
int ret; int ret;
/* ret = drm_atomic_helper_check_modeset(dev, state);
* msm ->atomic_check can update ->mode_changed for pixel format
* changes, hence must be run before we check the modeset changes.
*/
ret = drm_atomic_helper_check_planes(dev, state);
if (ret) if (ret)
return ret; return ret;
ret = drm_atomic_helper_check_modeset(dev, state); ret = drm_atomic_helper_check_planes(dev, state);
if (ret) if (ret)
return ret; return ret;
......
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