diff options
-rw-r--r-- | drivers/gpu/drm/armada/armada_hw.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_overlay.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_plane.c | 80 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_plane.h | 20 |
4 files changed, 91 insertions, 39 deletions
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h index 277580b36758..345dc4d0851e 100644 --- a/drivers/gpu/drm/armada/armada_hw.h +++ b/drivers/gpu/drm/armada/armada_hw.h @@ -316,19 +316,4 @@ enum { PWRDN_IRQ_LEVEL = 1 << 0, }; -static inline u32 armada_rect_hw_fp(struct drm_rect *r) -{ - return (drm_rect_height(r) & 0xffff0000) | drm_rect_width(r) >> 16; -} - -static inline u32 armada_rect_hw(struct drm_rect *r) -{ - return drm_rect_height(r) << 16 | (drm_rect_width(r) & 0x0000ffff); -} - -static inline u32 armada_rect_yx(struct drm_rect *r) -{ - return (r)->y1 << 16 | ((r)->x1 & 0x0000ffff); -} - #endif diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 8a3d2815cb58..589cdb6a9dae 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -27,7 +27,7 @@ #define DEFAULT_ENCODING DRM_COLOR_YCBCR_BT601 struct armada_overlay_state { - struct drm_plane_state base; + struct armada_plane_state base; u32 colorkey_yr; u32 colorkey_ug; u32 colorkey_vb; @@ -38,7 +38,7 @@ struct armada_overlay_state { u16 saturation; }; #define drm_to_overlay_state(s) \ - container_of(s, struct armada_overlay_state, base) + container_of(s, struct armada_overlay_state, base.base) static inline u32 armada_spu_contrast(struct drm_plane_state *state) { @@ -320,9 +320,9 @@ static void armada_overlay_reset(struct drm_plane *plane) state->brightness = DEFAULT_BRIGHTNESS; state->contrast = DEFAULT_CONTRAST; state->saturation = DEFAULT_SATURATION; - __drm_atomic_helper_plane_reset(plane, &state->base); - state->base.color_encoding = DEFAULT_ENCODING; - state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; + __drm_atomic_helper_plane_reset(plane, &state->base.base); + state->base.base.color_encoding = DEFAULT_ENCODING; + state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; } } @@ -336,8 +336,9 @@ armada_overlay_duplicate_state(struct drm_plane *plane) state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL); if (state) - __drm_atomic_helper_plane_duplicate_state(plane, &state->base); - return &state->base; + __drm_atomic_helper_plane_duplicate_state(plane, + &state->base.base); + return &state->base.base; } static int armada_overlay_set_property(struct drm_plane *plane, diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c index 6c098d379ae2..09218c1d8a4b 100644 --- a/drivers/gpu/drm/armada/armada_plane.c +++ b/drivers/gpu/drm/armada/armada_plane.c @@ -126,20 +126,47 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane, int armada_drm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - if (state->fb && !WARN_ON(!state->crtc)) { - struct drm_crtc *crtc = state->crtc; - struct drm_crtc_state *crtc_state; - - if (state->state) - crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); - else - crtc_state = crtc->state; - return drm_atomic_helper_check_plane_state(state, crtc_state, - 0, INT_MAX, - true, false); - } else { + struct armada_plane_state *st = to_armada_plane_state(state); + struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state; + bool interlace; + int ret; + + if (!state->fb || WARN_ON(!state->crtc)) { state->visible = false; + return 0; } + + if (state->state) + crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); + else + crtc_state = crtc->state; + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, 0, + INT_MAX, true, false); + if (ret) + return ret; + + interlace = crtc_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE; + if (interlace) { + if ((state->dst.y1 | state->dst.y2) & 1) + return -EINVAL; + st->src_hw = drm_rect_height(&state->src) >> 17; + st->dst_yx = state->dst.y1 >> 1; + st->dst_hw = drm_rect_height(&state->dst) >> 1; + } else { + st->src_hw = drm_rect_height(&state->src) >> 16; + st->dst_yx = state->dst.y1; + st->dst_hw = drm_rect_height(&state->dst); + } + + st->src_hw <<= 16; + st->src_hw |= drm_rect_width(&state->src) >> 16; + st->dst_yx <<= 16; + st->dst_yx |= state->dst.x1 & 0x0000ffff; + st->dst_hw <<= 16; + st->dst_hw |= drm_rect_width(&state->dst) & 0x0000ffff; + return 0; } @@ -262,12 +289,37 @@ static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = { .atomic_disable = armada_drm_primary_plane_atomic_disable, }; +void armada_plane_reset(struct drm_plane *plane) +{ + struct armada_plane_state *st; + if (plane->state) + __drm_atomic_helper_plane_destroy_state(plane->state); + kfree(plane->state); + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st) + __drm_atomic_helper_plane_reset(plane, &st->base); +} + +struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane) +{ + struct armada_plane_state *st; + + if (WARN_ON(!plane->state)) + return NULL; + + st = kmemdup(plane->state, sizeof(*st), GFP_KERNEL); + if (st) + __drm_atomic_helper_plane_duplicate_state(plane, &st->base); + + return &st->base; +} + static const struct drm_plane_funcs armada_primary_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = drm_primary_helper_destroy, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .reset = armada_plane_reset, + .atomic_duplicate_state = armada_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, }; diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h index 049c593342eb..396c45a4ea5e 100644 --- a/drivers/gpu/drm/armada/armada_plane.h +++ b/drivers/gpu/drm/armada/armada_plane.h @@ -1,9 +1,18 @@ #ifndef ARMADA_PLANE_H #define ARMADA_PLANE_H -#define armada_src_hw(state) armada_rect_hw_fp(&(state)->src) -#define armada_dst_yx(state) armada_rect_yx(&(state)->dst) -#define armada_dst_hw(state) armada_rect_hw(&(state)->dst) +struct armada_plane_state { + struct drm_plane_state base; + u32 src_hw; + u32 dst_yx; + u32 dst_hw; +}; + +#define to_armada_plane_state(st) \ + container_of(st, struct armada_plane_state, base) +#define armada_src_hw(state) to_armada_plane_state(state)->src_hw +#define armada_dst_yx(state) to_armada_plane_state(state)->dst_yx +#define armada_dst_hw(state) to_armada_plane_state(state)->dst_hw void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3], u16 pitches[3], bool interlaced); @@ -13,6 +22,11 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state); int armada_drm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state); +void armada_plane_reset(struct drm_plane *plane); +struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane); +void armada_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); + int armada_drm_primary_plane_init(struct drm_device *drm, struct drm_plane *primary); |