drm/rockchip: vop: fixup plane zpos
authorMark Yao <mark.yao@rock-chips.com>
Thu, 7 Jul 2016 00:45:23 +0000 (08:45 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 11 Jul 2016 03:00:02 +0000 (11:00 +0800)
Set unused plane with top zpos will cause a alpha problem.

if there are two planes use same zpos, hardware will do twice
alpha compute, that would cause display abnormal.

Change-Id: I3b5d15c5239412c670ad377edbcc66d7f6c59341
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.c

index 58fdb6d98629804312d4990b2376da622f64dad0..6de51ffda32dd487dead2e342809b2f896e73d69 100644 (file)
@@ -1095,39 +1095,47 @@ 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;
+       return pa->zpos - pb->zpos;
 }
 
 static int vop_crtc_atomic_check(struct drm_crtc *crtc,
-                                struct drm_crtc_state *state)
+                                struct drm_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->dev;
-       struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
+       struct drm_atomic_state *state = crtc_state->state;
+       struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
        struct vop *vop = to_vop(crtc);
        const struct vop_data *vop_data = vop->data;
        struct drm_plane *plane;
+       struct drm_plane_state *pstate;
+       struct vop_plane_state *plane_state;
        struct vop_zpos *pzpos;
        int dsp_layer_sel = 0;
-       int i, cnt = 0, ret = 0;
+       int i, j, cnt = 0, ret = 0;
 
-       pzpos = kmalloc_array(vop->num_wins, sizeof(*pzpos), GFP_KERNEL);
+       pzpos = kmalloc_array(vop_data->win_size, 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);
+       for (i = 0; i < vop_data->win_size; i++) {
+               const struct vop_win_data *win_data = &vop_data->win[i];
+               struct vop_win *win;
 
-               if (plane->parent)
+               if (!win_data->phy)
                        continue;
-               if (cnt >= vop->num_wins) {
-                       dev_err(dev->dev, "too many planes!\n");
+
+               for (j = 0; j < vop->num_wins; j++) {
+                       win = &vop->win[j];
+
+                       if (win->win_id == i && !win->area_id)
+                               break;
+               }
+               if (WARN_ON(j >= vop->num_wins)) {
                        ret = -EINVAL;
                        goto err_free_pzpos;
                }
-               pstate = state->state->plane_states[drm_plane_index(plane)];
 
+               plane = &win->base;
+               pstate = state->plane_states[drm_plane_index(plane)];
                /*
                 * plane might not have changed, in which case take
                 * current state:
@@ -1136,27 +1144,22 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc,
                        pstate = plane->state;
                plane_state = to_vop_plane_state(pstate);
                pzpos[cnt].zpos = plane_state->zpos;
-               pzpos[cnt].win_id = win->win_id;
-
-               cnt++;
+               pzpos[cnt++].win_id = win->win_id;
        }
 
        sort(pzpos, cnt, sizeof(pzpos[0]), vop_zpos_cmp, NULL);
 
-       WARN_ON(vop_data->win_size < cnt);
-       for (i = 0; i < (vop_data->win_size - cnt); i++) {
-               dsp_layer_sel <<= 2;
-               /*
-                * after sort, pzpos[0] is the top zpos layer.
-                */
-               dsp_layer_sel |= pzpos[0].win_id;
-       }
+       for (i = 0, cnt = 0; i < vop_data->win_size; i++) {
+               const struct vop_win_data *win_data = &vop_data->win[i];
+               int shift = i * 2;
 
-       for (i = 0; i < cnt; i++) {
-               struct vop_zpos *zpos = &pzpos[i];
+               if (win_data->phy) {
+                       struct vop_zpos *zpos = &pzpos[cnt++];
 
-               dsp_layer_sel <<= 2;
-               dsp_layer_sel |= zpos->win_id;
+                       dsp_layer_sel |= zpos->win_id << shift;
+               } else {
+                       dsp_layer_sel |= i << shift;
+               }
        }
 
        s->dsp_layer_sel = dsp_layer_sel;
@@ -1567,6 +1570,9 @@ static int vop_win_init(struct vop *vop)
                struct vop_win *vop_win = &vop->win[num_wins];
                const struct vop_win_data *win_data = &vop_data->win[i];
 
+               if (!win_data->phy)
+                       continue;
+
                vop_win->phy = win_data->phy;
                vop_win->offset = win_data->base;
                vop_win->type = win_data->type;
@@ -1593,6 +1599,9 @@ static int vop_win_init(struct vop *vop)
                        num_wins++;
                }
        }
+
+       vop->num_wins = num_wins;
+
        prop = drm_property_create_range(vop->drm_dev, DRM_MODE_PROP_ATOMIC,
                                         "ZPOS", 0, vop->data->win_size);
        if (!prop) {
index 13ce349be414296814f52265069d2288ed1d784b..48ec5706e0cfa8144eb973c60167da6b5ff66df5 100644 (file)
@@ -374,8 +374,10 @@ static const struct vop_data rk3399_vop_big = {
 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
        { .base = 0x00, .phy = &rk3288_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
+       { .phy = NULL },
        { .base = 0x00, .phy = &rk3288_win23_data,
          .type = DRM_PLANE_TYPE_CURSOR},
+       { .phy = NULL },
 };