mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
drm/armada: fix plane location and size for interlace
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>
This commit is contained in:
parent
9184ae8db3
commit
1d1547ec12
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
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->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 {
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user