aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-09-27 19:31:03 -0400
committerDave Airlie <airlied@redhat.com>2018-09-27 19:36:48 -0400
commit156e60bc71aa31a3b42b1d66a822c2999bd0994c (patch)
treedbc2fa3c30c78b1465aa29ca37fefbb8a16bde8e /drivers/gpu/drm/mxsfb/mxsfb_crtc.c
parentbf78296ab1cb215d0609ac6cff4e43e941e51265 (diff)
parentc2b70ffcd34eca60013d90bd6cd56e60b07adef8 (diff)
Merge tag 'drm-misc-next-2018-09-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.20: UAPI Changes: - None Cross-subsystem Changes: - MAINTAINERS: Move udl, mxsfb, and fsl-dcu into drm-misc (Stefan, Sean) Core Changes: - syncobj: Check condition before returning timeout in schedule() (Chris) Driver Changes: - various: First wave of drm_fbdev_generic_setup() conversions (Noralf) - bochs/virtio: More format byte-order improvements (Gerd) - mxsfb: A couple fixes + add runtime pm support (Leonard) - virtio: Add vmap support for prime objects (Ezequiel) Cc: Stefan Agner <stefan@agner.ch> Cc: Sean Paul <sean@poorly.run> Cc: Noralf Trønnes <noralf@tronnes.org> Cc: Gerd Hoffman <kraxel@redhat.com> Cc: Leonard Crestez <leonard.crestez@nxp.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ezequiel Garcia <ezequiel@collabora.com> Signed-off-by: Dave Airlie <airlied@redhat.com> From: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20180927093950.GA180365@art_vandelay
Diffstat (limited to 'drivers/gpu/drm/mxsfb/mxsfb_crtc.c')
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 0abe77675b76..24b1f0c1432e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -129,7 +129,6 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
129 if (mxsfb->clk_disp_axi) 129 if (mxsfb->clk_disp_axi)
130 clk_prepare_enable(mxsfb->clk_disp_axi); 130 clk_prepare_enable(mxsfb->clk_disp_axi);
131 clk_prepare_enable(mxsfb->clk); 131 clk_prepare_enable(mxsfb->clk);
132 mxsfb_enable_axi_clk(mxsfb);
133 132
134 /* If it was disabled, re-enable the mode again */ 133 /* If it was disabled, re-enable the mode again */
135 writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET); 134 writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -159,8 +158,6 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
159 reg &= ~VDCTRL4_SYNC_SIGNALS_ON; 158 reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
160 writel(reg, mxsfb->base + LCDC_VDCTRL4); 159 writel(reg, mxsfb->base + LCDC_VDCTRL4);
161 160
162 mxsfb_disable_axi_clk(mxsfb);
163
164 clk_disable_unprepare(mxsfb->clk); 161 clk_disable_unprepare(mxsfb->clk);
165 if (mxsfb->clk_disp_axi) 162 if (mxsfb->clk_disp_axi)
166 clk_disable_unprepare(mxsfb->clk_disp_axi); 163 clk_disable_unprepare(mxsfb->clk_disp_axi);
@@ -196,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr)
196 return clear_poll_bit(reset_addr, MODULE_CLKGATE); 193 return clear_poll_bit(reset_addr, MODULE_CLKGATE);
197} 194}
198 195
196static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
197{
198 struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb;
199 struct drm_gem_cma_object *gem;
200
201 if (!fb)
202 return 0;
203
204 gem = drm_fb_cma_get_gem_obj(fb, 0);
205 if (!gem)
206 return 0;
207
208 return gem->paddr;
209}
210
199static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) 211static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
200{ 212{
201 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; 213 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
@@ -208,7 +220,6 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
208 * running. This may lead to shifted pictures (FIFO issue?), so 220 * running. This may lead to shifted pictures (FIFO issue?), so
209 * first stop the controller and drain its FIFOs. 221 * first stop the controller and drain its FIFOs.
210 */ 222 */
211 mxsfb_enable_axi_clk(mxsfb);
212 223
213 /* Mandatory eLCDIF reset as per the Reference Manual */ 224 /* Mandatory eLCDIF reset as per the Reference Manual */
214 err = mxsfb_reset_block(mxsfb->base); 225 err = mxsfb_reset_block(mxsfb->base);
@@ -269,19 +280,29 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
269 280
270 writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay), 281 writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
271 mxsfb->base + LCDC_VDCTRL4); 282 mxsfb->base + LCDC_VDCTRL4);
272
273 mxsfb_disable_axi_clk(mxsfb);
274} 283}
275 284
276void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) 285void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
277{ 286{
287 dma_addr_t paddr;
288
289 mxsfb_enable_axi_clk(mxsfb);
278 mxsfb_crtc_mode_set_nofb(mxsfb); 290 mxsfb_crtc_mode_set_nofb(mxsfb);
291
292 /* Write cur_buf as well to avoid an initial corrupt frame */
293 paddr = mxsfb_get_fb_paddr(mxsfb);
294 if (paddr) {
295 writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
296 writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
297 }
298
279 mxsfb_enable_controller(mxsfb); 299 mxsfb_enable_controller(mxsfb);
280} 300}
281 301
282void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb) 302void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
283{ 303{
284 mxsfb_disable_controller(mxsfb); 304 mxsfb_disable_controller(mxsfb);
305 mxsfb_disable_axi_clk(mxsfb);
285} 306}
286 307
287void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, 308void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
@@ -289,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
289{ 310{
290 struct drm_simple_display_pipe *pipe = &mxsfb->pipe; 311 struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
291 struct drm_crtc *crtc = &pipe->crtc; 312 struct drm_crtc *crtc = &pipe->crtc;
292 struct drm_framebuffer *fb = pipe->plane.state->fb;
293 struct drm_pending_vblank_event *event; 313 struct drm_pending_vblank_event *event;
294 struct drm_gem_cma_object *gem; 314 dma_addr_t paddr;
295
296 if (!crtc)
297 return;
298 315
299 spin_lock_irq(&crtc->dev->event_lock); 316 spin_lock_irq(&crtc->dev->event_lock);
300 event = crtc->state->event; 317 event = crtc->state->event;
@@ -309,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
309 } 326 }
310 spin_unlock_irq(&crtc->dev->event_lock); 327 spin_unlock_irq(&crtc->dev->event_lock);
311 328
312 if (!fb) 329 paddr = mxsfb_get_fb_paddr(mxsfb);
313 return; 330 if (paddr) {
314 331 mxsfb_enable_axi_clk(mxsfb);
315 gem = drm_fb_cma_get_gem_obj(fb, 0); 332 writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
316 333 mxsfb_disable_axi_clk(mxsfb);
317 mxsfb_enable_axi_clk(mxsfb); 334 }
318 writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
319 mxsfb_disable_axi_clk(mxsfb);
320} 335}