drm/meson: move OSD scaler management into plane atomic update
authorNeil Armstrong <narmstrong@baylibre.com>
Tue, 6 Nov 2018 09:40:01 +0000 (10:40 +0100)
committerNeil Armstrong <narmstrong@baylibre.com>
Tue, 13 Nov 2018 12:27:51 +0000 (13:27 +0100)
In preparation to support the Primary Plane scaling, move the basic
OSD Interlace-Only scaler setup code into the primary plane atomic
update callback and handle the vsync scaler update like the overlay
plane scaling registers update.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/1541497202-20570-3-git-send-email-narmstrong@baylibre.com
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_drv.h
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/meson/meson_vpp.c

index 38686c9945e0366f70e4320cb5937e54e2e5181d..d78168f979db3b46a3978eb9a7a3ff4dfb05334e 100644 (file)
@@ -189,21 +189,26 @@ void meson_crtc_irq(struct meson_drm *priv)
                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
                writel_relaxed(priv->viu.osd1_blk0_cfg[4],
                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
-
-               /* If output is interlace, make use of the Scaler */
-               if (priv->viu.osd1_interlace) {
-                       struct drm_plane *plane = priv->primary_plane;
-                       struct drm_plane_state *state = plane->state;
-                       struct drm_rect dest = {
-                               .x1 = state->crtc_x,
-                               .y1 = state->crtc_y,
-                               .x2 = state->crtc_x + state->crtc_w,
-                               .y2 = state->crtc_y + state->crtc_h,
-                       };
-
-                       meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
-               } else
-                       meson_vpp_disable_interlace_vscaler_osd1(priv);
+               writel_relaxed(priv->viu.osd_sc_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+               writel_relaxed(priv->viu.osd_sc_i_wh_m1,
+                               priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
+               writel_relaxed(priv->viu.osd_sc_o_h_start_end,
+                               priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
+               writel_relaxed(priv->viu.osd_sc_o_v_start_end,
+                               priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
+               writel_relaxed(priv->viu.osd_sc_v_ini_phase,
+                               priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
+               writel_relaxed(priv->viu.osd_sc_v_phase_step,
+                               priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
+               writel_relaxed(priv->viu.osd_sc_h_ini_phase,
+                               priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
+               writel_relaxed(priv->viu.osd_sc_h_phase_step,
+                               priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
+               writel_relaxed(priv->viu.osd_sc_h_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+               writel_relaxed(priv->viu.osd_sc_v_ctrl0,
+                               priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
 
                if (priv->canvas)
                        meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
index 83e73491039a4a91312a01b34eb9f1cc639e96af..4dccf4cd042a58010c78c2f3f0db1195501f22ff 100644 (file)
@@ -53,6 +53,16 @@ struct meson_drm {
                uint32_t osd1_addr;
                uint32_t osd1_stride;
                uint32_t osd1_height;
+               uint32_t osd_sc_ctrl0;
+               uint32_t osd_sc_i_wh_m1;
+               uint32_t osd_sc_o_h_start_end;
+               uint32_t osd_sc_o_v_start_end;
+               uint32_t osd_sc_v_ini_phase;
+               uint32_t osd_sc_v_phase_step;
+               uint32_t osd_sc_h_ini_phase;
+               uint32_t osd_sc_h_phase_step;
+               uint32_t osd_sc_h_ctrl0;
+               uint32_t osd_sc_v_ctrl0;
 
                bool vd1_enabled;
                bool vd1_commit;
index 51bec8e98a39741a295162524403202847a616d7..8712498f9e934ed40f013d324275fcf34f9bf8f3 100644 (file)
@@ -143,13 +143,50 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
                break;
        };
 
+       /*
+        * When the output is interlaced, the OSD must switch between
+        * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
+        * at each vsync.
+        * But the vertical scaler can provide such funtionnality if
+        * is configured for 2:1 scaling with interlace options enabled.
+        */
        if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
                priv->viu.osd1_interlace = true;
 
                dest.y1 /= 2;
                dest.y2 /= 2;
-       } else
+
+               priv->viu.osd_sc_ctrl0 = BIT(3) | /* Enable scaler */
+                                        BIT(2); /* Select OSD1 */
+
+               /* 2:1 scaling */
+               priv->viu.osd_sc_i_wh_m1 = ((drm_rect_width(&dest) - 1) << 16) |
+                                          (drm_rect_height(&dest) - 1);
+               priv->viu.osd_sc_o_h_start_end = (dest.x1 << 16) | dest.x2;
+               priv->viu.osd_sc_o_v_start_end = (dest.y1 << 16) | dest.y2;
+
+               /* 2:1 vertical scaling values */
+               priv->viu.osd_sc_v_ini_phase = BIT(16);
+               priv->viu.osd_sc_v_phase_step = BIT(25);
+               priv->viu.osd_sc_v_ctrl0 =
+                       (4 << 0) | /* osd_vsc_bank_length */
+                       (4 << 3) | /* osd_vsc_top_ini_rcv_num0 */
+                       (1 << 8) | /* osd_vsc_top_rpt_p0_num0 */
+                       (6 << 11) | /* osd_vsc_bot_ini_rcv_num0 */
+                       (2 << 16) | /* osd_vsc_bot_rpt_p0_num0 */
+                       BIT(23) | /* osd_prog_interlace */
+                       BIT(24); /* Enable vertical scaler */
+
+               /* No horizontal scaling */
+               priv->viu.osd_sc_h_ini_phase = 0;
+               priv->viu.osd_sc_h_phase_step = 0;
+               priv->viu.osd_sc_h_ctrl0 = 0;
+       } else {
                priv->viu.osd1_interlace = false;
+               priv->viu.osd_sc_ctrl0 = 0;
+               priv->viu.osd_sc_h_ctrl0 = 0;
+               priv->viu.osd_sc_v_ctrl0 = 0;
+       }
 
        /*
         * The format of these registers is (x2 << 16 | x1),
index 5dc24a99e978b0fcf3c2c293516ba2f77a881563..f9efb431e9535728f9bd11acc0e957d6ef2fa23b 100644 (file)
@@ -51,52 +51,6 @@ void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
        writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
 }
 
-/*
- * When the output is interlaced, the OSD must switch between
- * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
- * at each vsync.
- * But the vertical scaler can provide such funtionnality if
- * is configured for 2:1 scaling with interlace options enabled.
- */
-void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
-                                           struct drm_rect *input)
-{
-       writel_relaxed(BIT(3) /* Enable scaler */ |
-                      BIT(2), /* Select OSD1 */
-                       priv->io_base + _REG(VPP_OSD_SC_CTRL0));
-
-       writel_relaxed(((drm_rect_width(input) - 1) << 16) |
-                      (drm_rect_height(input) - 1),
-                       priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
-       /* 2:1 scaling */
-       writel_relaxed(((input->x1) << 16) | (input->x2),
-                       priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
-       writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
-                       priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
-
-       /* 2:1 scaling values */
-       writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
-       writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
-
-       writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
-
-       writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
-                      (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
-                      (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
-                      (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
-                      (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
-                      BIT(23)  /* osd_prog_interlace */ |
-                      BIT(24), /* Enable vertical scaler */
-                       priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
-}
-
-void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
-{
-       writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
-       writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
-       writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
-}
-
 static unsigned int vpp_filter_coefs_4point_bspline[] = {
        0x15561500, 0x14561600, 0x13561700, 0x12561800,
        0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,