Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[cascardo/linux.git] / drivers / gpu / drm / rockchip / rockchip_drm_vop.c
index d3237f8..c7eba30 100644 (file)
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #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)
 
 enum vop_pending {
        VOP_PENDING_FB_UNREF,
 };
 
-struct vop_plane_state {
-       struct drm_plane_state base;
-       int format;
-       dma_addr_t yrgb_mst;
-       bool enable;
-};
-
 struct vop_win {
        struct drm_plane base;
        const struct vop_win_data *data;
        struct vop *vop;
-
-       /* protected by dev->event_lock */
-       bool enable;
-       dma_addr_t yrgb_mst;
 };
 
 struct vop {
@@ -651,7 +639,6 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        struct drm_crtc_state *crtc_state;
        struct drm_framebuffer *fb = state->fb;
        struct vop_win *vop_win = to_vop_win(plane);
-       struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
        const struct vop_win_data *win = vop_win->data;
        int ret;
        struct drm_rect clip;
@@ -661,7 +648,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                                        DRM_PLANE_HELPER_NO_SCALING;
 
        if (!crtc || !fb)
-               goto out_disable;
+               return 0;
 
        crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
        if (WARN_ON(!crtc_state))
@@ -679,11 +666,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                return ret;
 
        if (!state->visible)
-               goto out_disable;
+               return 0;
 
-       vop_plane_state->format = vop_convert_format(fb->pixel_format);
-       if (vop_plane_state->format < 0)
-               return vop_plane_state->format;
+       ret = vop_convert_format(fb->pixel_format);
+       if (ret < 0)
+               return ret;
 
        /*
         * Src.x1 can be odd when do clip, but yuv plane start point
@@ -692,19 +679,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2))
                return -EINVAL;
 
-       vop_plane_state->enable = true;
-
-       return 0;
-
-out_disable:
-       vop_plane_state->enable = false;
        return 0;
 }
 
 static void vop_plane_atomic_disable(struct drm_plane *plane,
                                     struct drm_plane_state *old_state)
 {
-       struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
        struct vop_win *vop_win = to_vop_win(plane);
        const struct vop_win_data *win = vop_win->data;
        struct vop *vop = to_vop(old_state->crtc);
@@ -712,18 +692,11 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
        if (!old_state->crtc)
                return;
 
-       spin_lock_irq(&plane->dev->event_lock);
-       vop_win->enable = false;
-       vop_win->yrgb_mst = 0;
-       spin_unlock_irq(&plane->dev->event_lock);
-
        spin_lock(&vop->reg_lock);
 
        VOP_WIN_SET(vop, win, enable, 0);
 
        spin_unlock(&vop->reg_lock);
-
-       vop_plane_state->enable = false;
 }
 
 static void vop_plane_atomic_update(struct drm_plane *plane,
@@ -732,7 +705,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        struct drm_plane_state *state = plane->state;
        struct drm_crtc *crtc = state->crtc;
        struct vop_win *vop_win = to_vop_win(plane);
-       struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
        const struct vop_win_data *win = vop_win->data;
        struct vop *vop = to_vop(state->crtc);
        struct drm_framebuffer *fb = state->fb;
@@ -747,6 +719,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        dma_addr_t dma_addr;
        uint32_t val;
        bool rb_swap;
+       int format;
 
        /*
         * can't update plane when vop is disabled.
@@ -757,7 +730,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        if (WARN_ON(!vop->is_enabled))
                return;
 
-       if (!vop_plane_state->enable) {
+       if (!state->visible) {
                vop_plane_atomic_disable(plane, old_state);
                return;
        }
@@ -778,18 +751,15 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 
        offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
        offset += (src->y1 >> 16) * fb->pitches[0];
-       vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+       dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
 
-       spin_lock_irq(&plane->dev->event_lock);
-       vop_win->enable = true;
-       vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
-       spin_unlock_irq(&plane->dev->event_lock);
+       format = vop_convert_format(fb->pixel_format);
 
        spin_lock(&vop->reg_lock);
 
-       VOP_WIN_SET(vop, win, format, vop_plane_state->format);
+       VOP_WIN_SET(vop, win, format, format);
        VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
-       VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
+       VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
        if (is_yuv_support(fb->pixel_format)) {
                int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
                int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
@@ -841,61 +811,13 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = {
        .atomic_disable = vop_plane_atomic_disable,
 };
 
-static void vop_atomic_plane_reset(struct drm_plane *plane)
-{
-       struct vop_plane_state *vop_plane_state =
-                                       to_vop_plane_state(plane->state);
-
-       if (plane->state && plane->state->fb)
-               drm_framebuffer_unreference(plane->state->fb);
-
-       kfree(vop_plane_state);
-       vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
-       if (!vop_plane_state)
-               return;
-
-       plane->state = &vop_plane_state->base;
-       plane->state->plane = plane;
-}
-
-static struct drm_plane_state *
-vop_atomic_plane_duplicate_state(struct drm_plane *plane)
-{
-       struct vop_plane_state *old_vop_plane_state;
-       struct vop_plane_state *vop_plane_state;
-
-       if (WARN_ON(!plane->state))
-               return NULL;
-
-       old_vop_plane_state = to_vop_plane_state(plane->state);
-       vop_plane_state = kmemdup(old_vop_plane_state,
-                                 sizeof(*vop_plane_state), GFP_KERNEL);
-       if (!vop_plane_state)
-               return NULL;
-
-       __drm_atomic_helper_plane_duplicate_state(plane,
-                                                 &vop_plane_state->base);
-
-       return &vop_plane_state->base;
-}
-
-static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
-                                          struct drm_plane_state *state)
-{
-       struct vop_plane_state *vop_state = to_vop_plane_state(state);
-
-       __drm_atomic_helper_plane_destroy_state(state);
-
-       kfree(vop_state);
-}
-
 static const struct drm_plane_funcs vop_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
        .destroy = vop_plane_destroy,
-       .reset = vop_atomic_plane_reset,
-       .atomic_duplicate_state = vop_atomic_plane_duplicate_state,
-       .atomic_destroy_state = vop_atomic_plane_destroy_state,
+       .reset = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
@@ -1108,6 +1030,16 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
         */
        vop_wait_for_irq_handler(vop);
 
+       spin_lock_irq(&crtc->dev->event_lock);
+       if (crtc->state->event) {
+               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+               WARN_ON(vop->event);
+
+               vop->event = crtc->state->event;
+               crtc->state->event = NULL;
+       }
+       spin_unlock_irq(&crtc->dev->event_lock);
+
        for_each_plane_in_state(old_state, plane, old_plane_state, i) {
                if (!old_plane_state->fb)
                        continue;
@@ -1125,19 +1057,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
                                  struct drm_crtc_state *old_crtc_state)
 {
-       struct vop *vop = to_vop(crtc);
-
        rockchip_drm_psr_flush(crtc);
-
-       spin_lock_irq(&crtc->dev->event_lock);
-       if (crtc->state->event) {
-               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-               WARN_ON(vop->event);
-
-               vop->event = crtc->state->event;
-               crtc->state->event = NULL;
-       }
-       spin_unlock_irq(&crtc->dev->event_lock);
 }
 
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
@@ -1203,29 +1123,11 @@ static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
        drm_framebuffer_unreference(fb);
 }
 
-static bool vop_win_pending_is_complete(struct vop_win *vop_win)
-{
-       dma_addr_t yrgb_mst;
-
-       if (!vop_win->enable)
-               return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
-
-       yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
-
-       return yrgb_mst == vop_win->yrgb_mst;
-}
-
 static void vop_handle_vblank(struct vop *vop)
 {
        struct drm_device *drm = vop->drm_dev;
        struct drm_crtc *crtc = &vop->crtc;
        unsigned long flags;
-       int i;
-
-       for (i = 0; i < vop->data->win_size; i++) {
-               if (!vop_win_pending_is_complete(&vop->win[i]))
-                       return;
-       }
 
        spin_lock_irqsave(&drm->event_lock, flags);
        if (vop->event) {
@@ -1645,11 +1547,15 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 
        ret = vop_create_crtc(vop);
        if (ret)
-               return ret;
+               goto err_enable_irq;
 
        pm_runtime_enable(&pdev->dev);
 
        return 0;
+
+err_enable_irq:
+       enable_irq(vop->irq); /* To balance out the disable_irq above */
+       return ret;
 }
 
 static void vop_unbind(struct device *dev, struct device *master, void *data)