aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Armstrong <narmstrong@baylibre.com>2018-11-06 04:40:01 -0500
committerNeil Armstrong <narmstrong@baylibre.com>2018-11-13 07:27:51 -0500
commit20d7fe034a2fda304dd9a8d2eb876f0fcaaef928 (patch)
treee496c023c8b47f1447b6d5ddfb48068f1321fdea
parentf9a2348196d1ab92e155bdba705db95d8177e886 (diff)
drm/meson: move OSD scaler management into plane atomic update
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
-rw-r--r--drivers/gpu/drm/meson/meson_crtc.c35
-rw-r--r--drivers/gpu/drm/meson/meson_drv.h10
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c39
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.c46
4 files changed, 68 insertions, 62 deletions
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 38686c9945e0..d78168f979db 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -189,21 +189,26 @@ void meson_crtc_irq(struct meson_drm *priv)
189 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3)); 189 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
190 writel_relaxed(priv->viu.osd1_blk0_cfg[4], 190 writel_relaxed(priv->viu.osd1_blk0_cfg[4],
191 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4)); 191 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
192 192 writel_relaxed(priv->viu.osd_sc_ctrl0,
193 /* If output is interlace, make use of the Scaler */ 193 priv->io_base + _REG(VPP_OSD_SC_CTRL0));
194 if (priv->viu.osd1_interlace) { 194 writel_relaxed(priv->viu.osd_sc_i_wh_m1,
195 struct drm_plane *plane = priv->primary_plane; 195 priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
196 struct drm_plane_state *state = plane->state; 196 writel_relaxed(priv->viu.osd_sc_o_h_start_end,
197 struct drm_rect dest = { 197 priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
198 .x1 = state->crtc_x, 198 writel_relaxed(priv->viu.osd_sc_o_v_start_end,
199 .y1 = state->crtc_y, 199 priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
200 .x2 = state->crtc_x + state->crtc_w, 200 writel_relaxed(priv->viu.osd_sc_v_ini_phase,
201 .y2 = state->crtc_y + state->crtc_h, 201 priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
202 }; 202 writel_relaxed(priv->viu.osd_sc_v_phase_step,
203 203 priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
204 meson_vpp_setup_interlace_vscaler_osd1(priv, &dest); 204 writel_relaxed(priv->viu.osd_sc_h_ini_phase,
205 } else 205 priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
206 meson_vpp_disable_interlace_vscaler_osd1(priv); 206 writel_relaxed(priv->viu.osd_sc_h_phase_step,
207 priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
208 writel_relaxed(priv->viu.osd_sc_h_ctrl0,
209 priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
210 writel_relaxed(priv->viu.osd_sc_v_ctrl0,
211 priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
207 212
208 if (priv->canvas) 213 if (priv->canvas)
209 meson_canvas_config(priv->canvas, priv->canvas_id_osd1, 214 meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index 83e73491039a..4dccf4cd042a 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -53,6 +53,16 @@ struct meson_drm {
53 uint32_t osd1_addr; 53 uint32_t osd1_addr;
54 uint32_t osd1_stride; 54 uint32_t osd1_stride;
55 uint32_t osd1_height; 55 uint32_t osd1_height;
56 uint32_t osd_sc_ctrl0;
57 uint32_t osd_sc_i_wh_m1;
58 uint32_t osd_sc_o_h_start_end;
59 uint32_t osd_sc_o_v_start_end;
60 uint32_t osd_sc_v_ini_phase;
61 uint32_t osd_sc_v_phase_step;
62 uint32_t osd_sc_h_ini_phase;
63 uint32_t osd_sc_h_phase_step;
64 uint32_t osd_sc_h_ctrl0;
65 uint32_t osd_sc_v_ctrl0;
56 66
57 bool vd1_enabled; 67 bool vd1_enabled;
58 bool vd1_commit; 68 bool vd1_commit;
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 51bec8e98a39..8712498f9e93 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -143,13 +143,50 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
143 break; 143 break;
144 }; 144 };
145 145
146 /*
147 * When the output is interlaced, the OSD must switch between
148 * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
149 * at each vsync.
150 * But the vertical scaler can provide such funtionnality if
151 * is configured for 2:1 scaling with interlace options enabled.
152 */
146 if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) { 153 if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
147 priv->viu.osd1_interlace = true; 154 priv->viu.osd1_interlace = true;
148 155
149 dest.y1 /= 2; 156 dest.y1 /= 2;
150 dest.y2 /= 2; 157 dest.y2 /= 2;
151 } else 158
159 priv->viu.osd_sc_ctrl0 = BIT(3) | /* Enable scaler */
160 BIT(2); /* Select OSD1 */
161
162 /* 2:1 scaling */
163 priv->viu.osd_sc_i_wh_m1 = ((drm_rect_width(&dest) - 1) << 16) |
164 (drm_rect_height(&dest) - 1);
165 priv->viu.osd_sc_o_h_start_end = (dest.x1 << 16) | dest.x2;
166 priv->viu.osd_sc_o_v_start_end = (dest.y1 << 16) | dest.y2;
167
168 /* 2:1 vertical scaling values */
169 priv->viu.osd_sc_v_ini_phase = BIT(16);
170 priv->viu.osd_sc_v_phase_step = BIT(25);
171 priv->viu.osd_sc_v_ctrl0 =
172 (4 << 0) | /* osd_vsc_bank_length */
173 (4 << 3) | /* osd_vsc_top_ini_rcv_num0 */
174 (1 << 8) | /* osd_vsc_top_rpt_p0_num0 */
175 (6 << 11) | /* osd_vsc_bot_ini_rcv_num0 */
176 (2 << 16) | /* osd_vsc_bot_rpt_p0_num0 */
177 BIT(23) | /* osd_prog_interlace */
178 BIT(24); /* Enable vertical scaler */
179
180 /* No horizontal scaling */
181 priv->viu.osd_sc_h_ini_phase = 0;
182 priv->viu.osd_sc_h_phase_step = 0;
183 priv->viu.osd_sc_h_ctrl0 = 0;
184 } else {
152 priv->viu.osd1_interlace = false; 185 priv->viu.osd1_interlace = false;
186 priv->viu.osd_sc_ctrl0 = 0;
187 priv->viu.osd_sc_h_ctrl0 = 0;
188 priv->viu.osd_sc_v_ctrl0 = 0;
189 }
153 190
154 /* 191 /*
155 * The format of these registers is (x2 << 16 | x1), 192 * The format of these registers is (x2 << 16 | x1),
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
index 5dc24a99e978..f9efb431e953 100644
--- a/drivers/gpu/drm/meson/meson_vpp.c
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -51,52 +51,6 @@ void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
51 writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL)); 51 writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
52} 52}
53 53
54/*
55 * When the output is interlaced, the OSD must switch between
56 * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
57 * at each vsync.
58 * But the vertical scaler can provide such funtionnality if
59 * is configured for 2:1 scaling with interlace options enabled.
60 */
61void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
62 struct drm_rect *input)
63{
64 writel_relaxed(BIT(3) /* Enable scaler */ |
65 BIT(2), /* Select OSD1 */
66 priv->io_base + _REG(VPP_OSD_SC_CTRL0));
67
68 writel_relaxed(((drm_rect_width(input) - 1) << 16) |
69 (drm_rect_height(input) - 1),
70 priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
71 /* 2:1 scaling */
72 writel_relaxed(((input->x1) << 16) | (input->x2),
73 priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
74 writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
75 priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
76
77 /* 2:1 scaling values */
78 writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
79 writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
80
81 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
82
83 writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
84 (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
85 (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
86 (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
87 (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
88 BIT(23) /* osd_prog_interlace */ |
89 BIT(24), /* Enable vertical scaler */
90 priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
91}
92
93void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
94{
95 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
96 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
97 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
98}
99
100static unsigned int vpp_filter_coefs_4point_bspline[] = { 54static unsigned int vpp_filter_coefs_4point_bspline[] = {
101 0x15561500, 0x14561600, 0x13561700, 0x12561800, 55 0x15561500, 0x14561600, 0x13561700, 0x12561800,
102 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00, 56 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,