summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/armada/armada_hw.h15
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c15
-rw-r--r--drivers/gpu/drm/armada/armada_plane.c80
-rw-r--r--drivers/gpu/drm/armada/armada_plane.h20
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);