diff options
author | Neil Armstrong <narmstrong@baylibre.com> | 2018-11-06 04:40:01 -0500 |
---|---|---|
committer | Neil Armstrong <narmstrong@baylibre.com> | 2018-11-13 07:27:51 -0500 |
commit | 20d7fe034a2fda304dd9a8d2eb876f0fcaaef928 (patch) | |
tree | e496c023c8b47f1447b6d5ddfb48068f1321fdea | |
parent | f9a2348196d1ab92e155bdba705db95d8177e886 (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.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/meson/meson_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/meson/meson_plane.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/meson/meson_vpp.c | 46 |
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 | */ | ||
61 | void 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 | |||
93 | void 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 | |||
100 | static unsigned int vpp_filter_coefs_4point_bspline[] = { | 54 | static 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, |