From: Mark Yao Date: Wed, 27 Apr 2016 08:18:07 +0000 (+0800) Subject: drm/rockchip: vop: support plane zpos property X-Git-Tag: firefly_0821_release~2694 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ed547bb16f27448033d0005c6ee3e282375a8f27;p=firefly-linux-kernel-4.4.55.git drm/rockchip: vop: support plane zpos property Change-Id: Idd0265020a591ce5b34d117442104f625e331119 Signed-off-by: Mark Yao --- diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index bfd5facfd36b..7eb8187c1dd5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -63,6 +63,7 @@ struct rockchip_atomic_commit { struct rockchip_crtc_state { struct drm_crtc_state base; + int dsp_layer_sel; int output_type; int output_mode; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2785bcf8a800..edb483eda66b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -30,6 +30,7 @@ #include #include +#include #include "rockchip_drm_drv.h" #include "rockchip_drm_gem.h" @@ -91,9 +92,15 @@ #define to_vop_win(x) container_of(x, struct vop_win, base) #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base) +struct vop_zpos { + int win_id; + int zpos; +}; + struct vop_plane_state { struct drm_plane_state base; int format; + int zpos; struct drm_rect src; struct drm_rect dest; dma_addr_t yrgb_mst; @@ -104,6 +111,8 @@ struct vop_win { struct vop_win *parent; struct drm_plane base; + int win_id; + int area_id; uint32_t offset; enum drm_plane_type type; const struct vop_win_phy *phy; @@ -118,6 +127,7 @@ struct vop { struct drm_crtc crtc; struct device *dev; struct drm_device *drm_dev; + struct drm_property *plane_zpos_prop; bool is_enabled; /* mutex vsync_ work */ @@ -780,6 +790,7 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { void vop_atomic_plane_reset(struct drm_plane *plane) { + struct vop_win *win = to_vop_win(plane); struct vop_plane_state *vop_plane_state = to_vop_plane_state(plane->state); @@ -791,6 +802,7 @@ void vop_atomic_plane_reset(struct drm_plane *plane) if (!vop_plane_state) return; + vop_plane_state->zpos = win->win_id; plane->state = &vop_plane_state->base; plane->state->plane = plane; } @@ -826,6 +838,40 @@ static void vop_atomic_plane_destroy_state(struct drm_plane *plane, kfree(vop_state); } +static int vop_atomic_plane_set_property(struct drm_plane *plane, + struct drm_plane_state *state, + struct drm_property *property, + uint64_t val) +{ + struct vop_win *win = to_vop_win(plane); + struct vop_plane_state *plane_state = to_vop_plane_state(state); + + if (property == win->vop->plane_zpos_prop) { + plane_state->zpos = val; + return 0; + } + + DRM_ERROR("failed to set vop plane property\n"); + return -EINVAL; +} + +static int vop_atomic_plane_get_property(struct drm_plane *plane, + const struct drm_plane_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct vop_win *win = to_vop_win(plane); + struct vop_plane_state *plane_state = to_vop_plane_state(state); + + if (property == win->vop->plane_zpos_prop) { + *val = plane_state->zpos; + return 0; + } + + DRM_ERROR("failed to get vop plane property\n"); + return -EINVAL; +} + static const struct drm_plane_funcs vop_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -833,6 +879,8 @@ static const struct drm_plane_funcs vop_plane_funcs = { .reset = vop_atomic_plane_reset, .atomic_duplicate_state = vop_atomic_plane_duplicate_state, .atomic_destroy_state = vop_atomic_plane_destroy_state, + .atomic_set_property = vop_atomic_plane_set_property, + .atomic_get_property = vop_atomic_plane_get_property, }; static int vop_crtc_enable_vblank(struct drm_crtc *crtc) @@ -1006,9 +1054,77 @@ static void vop_crtc_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, standby, 0); } +static int vop_zpos_cmp(const void *a, const void *b) +{ + struct vop_zpos *pa = (struct vop_zpos *)a; + struct vop_zpos *pb = (struct vop_zpos *)b; + + return pb->zpos - pa->zpos; +} + +static int vop_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct drm_device *dev = crtc->dev; + struct rockchip_crtc_state *s = to_rockchip_crtc_state(state); + struct vop *vop = to_vop(crtc); + struct drm_plane *plane; + struct vop_zpos *pzpos; + int dsp_layer_sel = 0; + int i, cnt = 0, ret = 0; + + pzpos = kmalloc_array(vop->num_wins, sizeof(*pzpos), GFP_KERNEL); + if (!pzpos) + return -ENOMEM; + + drm_atomic_crtc_state_for_each_plane(plane, state) { + struct drm_plane_state *pstate; + struct vop_plane_state *plane_state; + struct vop_win *win = to_vop_win(plane); + + if (plane->parent) + continue; + if (cnt >= vop->num_wins) { + dev_err(dev->dev, "too many planes!\n"); + ret = -EINVAL; + goto err_free_pzpos; + } + pstate = state->state->plane_states[drm_plane_index(plane)]; + + /* + * plane might not have changed, in which case take + * current state: + */ + if (!pstate) + pstate = plane->state; + plane_state = to_vop_plane_state(pstate); + pzpos[cnt].zpos = plane_state->zpos; + pzpos[cnt].win_id = win->win_id; + + cnt++; + } + + sort(pzpos, cnt, sizeof(pzpos[0]), vop_zpos_cmp, NULL); + + for (i = 0; i < cnt; i++) { + struct vop_zpos *zpos = &pzpos[i]; + + dsp_layer_sel <<= 2; + dsp_layer_sel |= zpos->win_id; + } + + s->dsp_layer_sel = dsp_layer_sel; + +err_free_pzpos: + kfree(pzpos); + return ret; +} + static void vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct rockchip_crtc_state *s = + to_rockchip_crtc_state(crtc->state); struct vop *vop = to_vop(crtc); if (WARN_ON(!vop->is_enabled)) @@ -1016,6 +1132,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock(&vop->reg_lock); + VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); @@ -1038,6 +1155,7 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { .enable = vop_crtc_enable, .disable = vop_crtc_disable, .mode_fixup = vop_crtc_mode_fixup, + .atomic_check = vop_crtc_atomic_check, .atomic_flush = vop_crtc_atomic_flush, .atomic_begin = vop_crtc_atomic_begin, }; @@ -1178,7 +1296,8 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win, return ret; } drm_plane_helper_add(&win->base, &plane_helper_funcs); - + drm_object_attach_property(&win->base.base, + vop->plane_zpos_prop, win->win_id); return 0; } @@ -1389,11 +1508,12 @@ err_unprepare_dclk: /* * Initialize the vop->win array elements. */ -static void vop_win_init(struct vop *vop) +static int vop_win_init(struct vop *vop) { const struct vop_data *vop_data = vop->data; unsigned int i, j; unsigned int num_wins = 0; + struct drm_property *prop; for (i = 0; i < vop_data->win_size; i++) { struct vop_win *vop_win = &vop->win[num_wins]; @@ -1405,6 +1525,8 @@ static void vop_win_init(struct vop *vop) vop_win->data_formats = win_data->phy->data_formats; vop_win->nformats = win_data->phy->nformats; vop_win->vop = vop; + vop_win->win_id = i; + vop_win->area_id = 0; num_wins++; for (j = 0; j < win_data->area_size; j++) { @@ -1418,9 +1540,20 @@ static void vop_win_init(struct vop *vop) vop_area->data_formats = vop_win->data_formats; vop_area->nformats = vop_win->nformats; vop_area->vop = vop; + vop_area->win_id = i; + vop_area->area_id = j; num_wins++; } } + prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_ATOMIC, + "ZPOS", 0, vop->data->win_size); + if (!prop) { + DRM_ERROR("failed to create zpos property\n"); + return -EINVAL; + } + vop->plane_zpos_prop = prop; + + return 0; } static int vop_bind(struct device *dev, struct device *master, void *data) @@ -1456,7 +1589,9 @@ static int vop_bind(struct device *dev, struct device *master, void *data) vop->num_wins = num_wins; dev_set_drvdata(dev, vop); - vop_win_init(vop); + ret = vop_win_init(vop); + if (ret) + return ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); vop->len = resource_size(res); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 679396451762..4b8f14207687 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -46,6 +46,7 @@ struct vop_ctrl { struct vop_reg hdmi_en; struct vop_reg mipi_en; struct vop_reg out_mode; + struct vop_reg dsp_layer_sel; struct vop_reg dither_down; struct vop_reg dither_up; struct vop_reg pin_pol; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 1b8ec6637328..9944d64b269d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -153,6 +153,7 @@ static const struct vop_win_phy *rk3288_area_data[] = { static const struct vop_ctrl rk3288_ctrl_data = { .standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22), + .dsp_layer_sel = VOP_REG(RK3288_DSP_CTRL1, 0xff, 8), .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), @@ -240,6 +241,7 @@ static const struct vop_ctrl rk3399_ctrl_data = { .hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13), .edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14), .mipi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 15), + .dsp_layer_sel = VOP_REG(RK3399_DSP_CTRL1, 0xff, 8), .dither_down = VOP_REG(RK3399_DSP_CTRL1, 0xf, 1), .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6), .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19), @@ -449,6 +451,7 @@ static const struct vop_ctrl rk3036_ctrl_data = { .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), + .dsp_layer_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 8), .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),