From e6205bfe9b5ab0f331ebd81bfa4de2e870e192ad Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Mon, 5 Jun 2017 11:29:36 +0800 Subject: [PATCH] drm/rockchip: logo: use unique plane property logo mirror The logo framework use state->rotation may conflict to common drm update, cause display abnormal Change-Id: I09b6b898a7606cd05371af1f4b25254945923d0d Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 23 +++---------------- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 7 ++++++ drivers/gpu/drm/rockchip/rockchip_drm_fb.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 25 ++++++++++++++++++--- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index e7a6755b48f8..81cca3b6611e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -478,7 +478,7 @@ static int update_state(struct drm_device *drm_dev, struct rockchip_drm_mode_set *set, unsigned int *plane_mask) { - struct drm_mode_config *mode_config = &drm_dev->mode_config; + struct rockchip_drm_private *priv = drm_dev->dev_private; struct drm_crtc *crtc = set->crtc; struct drm_connector *connector = set->connector; struct drm_display_mode *mode = set->mode; @@ -507,7 +507,6 @@ static int update_state(struct drm_device *drm_dev, } else { const struct drm_encoder_helper_funcs *encoder_helper_funcs; const struct drm_connector_helper_funcs *connector_helper_funcs; - struct rockchip_drm_private *priv = drm_dev->dev_private; struct drm_encoder *encoder; int pipe = drm_crtc_index(crtc); @@ -549,8 +548,8 @@ static int update_state(struct drm_device *drm_dev, * some vop maybe not support ymirror, but force use it now. */ drm_atomic_plane_set_property(crtc->primary, primary_state, - mode_config->rotation_property, - BIT(DRM_REFLECT_Y)); + priv->logo_ymirror_prop, + true); return ret; } @@ -636,24 +635,8 @@ static void show_loader_logo(struct drm_device *drm_dev) drm_atomic_clean_old_fb(drm_dev, plane_mask, ret); list_for_each_entry_safe(set, tmp, &mode_set_list, head) { - struct drm_crtc *crtc = set->crtc; - list_del(&set->head); kfree(set); - - /* FIXME: - * primary plane state rotation is not BIT(0), but we only want - * it effect on logo display, userspace may not known to clean - * this property, would get unexpect display, so force set - * primary rotation to BIT(0). - */ - if (!crtc->primary || !crtc->primary->state) - continue; - - drm_atomic_plane_set_property(crtc->primary, - crtc->primary->state, - mode_config->rotation_property, - BIT(0)); } /* diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 0cb9d0962bc0..7c0f742f1a0a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -120,6 +120,7 @@ struct rockchip_logo { */ struct rockchip_drm_private { struct rockchip_logo *logo; + struct drm_property *logo_ymirror_prop; struct drm_fb_helper *fbdev_helper; struct drm_gem_object *fbdev_bo; const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index c261a166ca22..15fe607f2bc1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -33,6 +33,13 @@ struct rockchip_drm_fb { struct rockchip_logo *logo; }; +bool rockchip_fb_is_logo(struct drm_framebuffer *fb) +{ + struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb); + + return rk_fb && rk_fb->logo; +} + dma_addr_t rockchip_fb_get_dma_addr(struct drm_framebuffer *fb, unsigned int plane) { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h index fe702dfc27d9..60ce2efed3a7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h @@ -15,6 +15,7 @@ #ifndef _ROCKCHIP_DRM_FB_H #define _ROCKCHIP_DRM_FB_H +bool rockchip_fb_is_logo(struct drm_framebuffer *fb); struct drm_framebuffer * rockchip_drm_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2d08be86cad9..7273d3b55a89 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -133,6 +133,7 @@ struct vop_plane_state { struct drm_plane_state base; int format; int zpos; + unsigned int logo_ymirror; struct drm_rect src; struct drm_rect dest; dma_addr_t yrgb_mst; @@ -1108,7 +1109,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane, } offset = (src->x1 >> 16) * drm_format_plane_bpp(fb->pixel_format, 0) / 8; - if (state->rotation & BIT(DRM_REFLECT_Y)) + if (state->rotation & BIT(DRM_REFLECT_Y) || + (rockchip_fb_is_logo(fb) && vop_plane_state->logo_ymirror)) offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; else offset += (src->y1 >> 16) * fb->pitches[0]; @@ -1210,7 +1212,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); - ymirror = !!(state->rotation & BIT(DRM_REFLECT_Y)); + ymirror = state->rotation & BIT(DRM_REFLECT_Y) || + (rockchip_fb_is_logo(fb) && vop_plane_state->logo_ymirror); xmirror = !!(state->rotation & BIT(DRM_REFLECT_X)); vop = to_vop(state->crtc); @@ -1333,6 +1336,7 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { + struct rockchip_drm_private *private = plane->dev->dev_private; struct vop_win *win = to_vop_win(plane); struct vop_plane_state *plane_state = to_vop_plane_state(state); @@ -1346,6 +1350,12 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane, return 0; } + if (property == private->logo_ymirror_prop) { + WARN_ON(!rockchip_fb_is_logo(state->fb)); + plane_state->logo_ymirror = val; + return 0; + } + DRM_ERROR("failed to set vop plane property\n"); return -EINVAL; } @@ -2285,6 +2295,7 @@ static irqreturn_t vop_isr(int irq, void *data) static int vop_plane_init(struct vop *vop, struct vop_win *win, unsigned long possible_crtcs) { + struct rockchip_drm_private *private = vop->drm_dev->dev_private; struct drm_plane *share = NULL; unsigned int rotations = 0; struct drm_property *prop; @@ -2308,9 +2319,17 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win, if (VOP_WIN_SUPPORT(vop, win, xmirror)) rotations |= BIT(DRM_REFLECT_X); - if (VOP_WIN_SUPPORT(vop, win, ymirror)) + if (VOP_WIN_SUPPORT(vop, win, ymirror)) { rotations |= BIT(DRM_REFLECT_Y); + prop = drm_property_create_bool(vop->drm_dev, + DRM_MODE_PROP_ATOMIC, + "LOGO_YMIRROR"); + if (!prop) + return -ENOMEM; + private->logo_ymirror_prop = prop; + } + if (rotations) { rotations |= BIT(DRM_ROTATE_0); prop = drm_mode_create_rotation_property(vop->drm_dev, -- 2.34.1