]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/armada: fix plane location and size for interlace
authorRussell King <rmk+kernel@armlinux.org.uk>
Fri, 25 Jan 2019 10:56:54 +0000 (10:56 +0000)
committerRussell King <rmk+kernel@armlinux.org.uk>
Fri, 17 May 2019 11:16:32 +0000 (12:16 +0100)
When the CRTC is programmed for interlace, we have to halve the Y
parameters for the plane.  Rather than doing this in the update
function (which would need the calculation repeated for the old
state as well as the new state), arrange to do the calculation in
atomic_check and save it in our private plane state structure.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
drivers/gpu/drm/armada/armada_hw.h
drivers/gpu/drm/armada/armada_overlay.c
drivers/gpu/drm/armada/armada_plane.c
drivers/gpu/drm/armada/armada_plane.h

index 277580b367586889080b15a59a6c1a2c45658cce..345dc4d0851ef43bd73069679c3ec7fef8bfa073 100644 (file)
@@ -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
index 8a3d2815cb58eda34420d4093af42b23cd8f7c98..589cdb6a9dae802197ca68121c58534be486f083 100644 (file)
@@ -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,
index 6c098d379ae21862f954cdc47791b11ffd7c96f3..09218c1d8a4b161101e9ea3a70f9bb11401de5f3 100644 (file)
@@ -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,
 };
 
index 049c593342eb28897fa705bbba80ff1240b07879..396c45a4ea5e19315d833a307b92ad5f708c8066 100644 (file)
@@ -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);