drm/rockchip: vop: support CRTC_STEREO_DOUBLE mode
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / rockchip_drm_vop.c
index 017304927979951b94518c4edc62e8ac8559d727..1670584706751d476658d0f835c0ea8a8eb2fa50 100644 (file)
@@ -825,7 +825,9 @@ static void vop_initial(struct drm_crtc *crtc)
         */
        for (i = 0; i < vop->num_wins; i++) {
                struct vop_win *win = &vop->win[i];
+               int channel = i * 2 + 1;
 
+               VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel);
                if (win->phy->scl && win->phy->scl->ext) {
                        VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE);
                        VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE);
@@ -924,6 +926,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                                        DRM_PLANE_HELPER_NO_SCALING;
        unsigned long offset;
        dma_addr_t dma_addr;
+       u16 vdisplay;
 
        crtc = crtc ? crtc : plane->state->crtc;
        /*
@@ -945,10 +948,14 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        dest->x2 = state->crtc_x + state->crtc_w;
        dest->y2 = state->crtc_y + state->crtc_h;
 
+       vdisplay = crtc_state->adjusted_mode.crtc_vdisplay;
+       if (crtc_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+               vdisplay *= 2;
+
        clip.x1 = 0;
        clip.y1 = 0;
-       clip.x2 = crtc_state->mode.hdisplay;
-       clip.y2 = crtc_state->mode.vdisplay;
+       clip.x2 = crtc_state->adjusted_mode.crtc_hdisplay;
+       clip.y2 = vdisplay;
 
        ret = drm_plane_helper_check_update(plane, crtc, state->fb,
                                            src, dest, &clip,
@@ -1458,20 +1465,23 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = {
 
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
                                const struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
+                               struct drm_display_mode *adj_mode)
 {
        struct vop *vop = to_vop(crtc);
        const struct vop_data *vop_data = vop->data;
-       int request_clock = mode->clock;
 
        if (mode->hdisplay > vop_data->max_output.width ||
            mode->vdisplay > vop_data->max_output.height)
                return false;
 
+       drm_mode_set_crtcinfo(adj_mode,
+                             CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
+
        if (mode->flags & DRM_MODE_FLAG_DBLCLK)
-               request_clock *= 2;
-       adjusted_mode->crtc_clock =
-               clk_round_rate(vop->dclk, request_clock * 1000) / 1000;
+               adj_mode->crtc_clock *= 2;
+
+       adj_mode->crtc_clock =
+               clk_round_rate(vop->dclk, adj_mode->crtc_clock * 1000) / 1000;
 
        return true;
 }
@@ -1494,11 +1504,6 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        u16 vact_end = vact_st + vdisplay;
        uint32_t val;
 
-       if (vop->loader_protect) {
-               vop->loader_protect = false;
-               return;
-       }
-
        vop_initial(crtc);
 
        val = BIT(DCLK_INVERT);
@@ -1577,7 +1582,6 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        VOP_CTRL_SET(vop, hact_st_end, val);
        VOP_CTRL_SET(vop, hpost_st_end, val);
 
-       VOP_CTRL_SET(vop, vtotal_pw, (adjusted_mode->vtotal << 16) | vsync_len);
        val = vact_st << 16;
        val |= vact_end;
        VOP_CTRL_SET(vop, vact_st_end, val);
@@ -1594,10 +1598,12 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
                VOP_CTRL_SET(vop, vs_st_end_f1, val);
                VOP_CTRL_SET(vop, dsp_interlace, 1);
                VOP_CTRL_SET(vop, p2i_en, 1);
+               vtotal = vtotal + 1;
        } else {
                VOP_CTRL_SET(vop, dsp_interlace, 0);
                VOP_CTRL_SET(vop, p2i_en, 0);
        }
+       VOP_CTRL_SET(vop, vtotal_pw, vtotal << 16 | vsync_len);
 
        VOP_CTRL_SET(vop, core_dclk_div,
                     !!(adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK));