diff options
| -rw-r--r-- | drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index e4fcbb65b969..24b1f0c1432e 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c | |||
| @@ -193,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr) | |||
| 193 | return clear_poll_bit(reset_addr, MODULE_CLKGATE); | 193 | return clear_poll_bit(reset_addr, MODULE_CLKGATE); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static 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 | |||
| 196 | static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) | 211 | static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) |
| 197 | { | 212 | { |
| 198 | struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; | 213 | struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; |
| @@ -269,8 +284,18 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) | |||
| 269 | 284 | ||
| 270 | void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) | 285 | void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) |
| 271 | { | 286 | { |
| 287 | dma_addr_t paddr; | ||
| 288 | |||
| 272 | mxsfb_enable_axi_clk(mxsfb); | 289 | mxsfb_enable_axi_clk(mxsfb); |
| 273 | 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 | |||
| 274 | mxsfb_enable_controller(mxsfb); | 299 | mxsfb_enable_controller(mxsfb); |
| 275 | } | 300 | } |
| 276 | 301 | ||
| @@ -285,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, | |||
| 285 | { | 310 | { |
| 286 | struct drm_simple_display_pipe *pipe = &mxsfb->pipe; | 311 | struct drm_simple_display_pipe *pipe = &mxsfb->pipe; |
| 287 | struct drm_crtc *crtc = &pipe->crtc; | 312 | struct drm_crtc *crtc = &pipe->crtc; |
| 288 | struct drm_framebuffer *fb = pipe->plane.state->fb; | ||
| 289 | struct drm_pending_vblank_event *event; | 313 | struct drm_pending_vblank_event *event; |
| 290 | struct drm_gem_cma_object *gem; | 314 | dma_addr_t paddr; |
| 291 | |||
| 292 | if (!crtc) | ||
| 293 | return; | ||
| 294 | 315 | ||
| 295 | spin_lock_irq(&crtc->dev->event_lock); | 316 | spin_lock_irq(&crtc->dev->event_lock); |
| 296 | event = crtc->state->event; | 317 | event = crtc->state->event; |
| @@ -305,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, | |||
| 305 | } | 326 | } |
| 306 | spin_unlock_irq(&crtc->dev->event_lock); | 327 | spin_unlock_irq(&crtc->dev->event_lock); |
| 307 | 328 | ||
| 308 | if (!fb) | 329 | paddr = mxsfb_get_fb_paddr(mxsfb); |
| 309 | return; | 330 | if (paddr) { |
| 310 | 331 | mxsfb_enable_axi_clk(mxsfb); | |
| 311 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 332 | writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); |
| 312 | 333 | mxsfb_disable_axi_clk(mxsfb); | |
| 313 | mxsfb_enable_axi_clk(mxsfb); | 334 | } |
| 314 | writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf); | ||
| 315 | mxsfb_disable_axi_clk(mxsfb); | ||
| 316 | } | 335 | } |
