aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fimd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c71
1 files changed, 53 insertions, 18 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 4659c88cdd9..db3b3d9e731 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -64,7 +64,7 @@ struct fimd_win_data {
64 unsigned int fb_width; 64 unsigned int fb_width;
65 unsigned int fb_height; 65 unsigned int fb_height;
66 unsigned int bpp; 66 unsigned int bpp;
67 dma_addr_t paddr; 67 dma_addr_t dma_addr;
68 void __iomem *vaddr; 68 void __iomem *vaddr;
69 unsigned int buf_offsize; 69 unsigned int buf_offsize;
70 unsigned int line_size; /* bytes */ 70 unsigned int line_size; /* bytes */
@@ -124,7 +124,7 @@ static int fimd_display_power_on(struct device *dev, int mode)
124 return 0; 124 return 0;
125} 125}
126 126
127static struct exynos_drm_display fimd_display = { 127static struct exynos_drm_display_ops fimd_display_ops = {
128 .type = EXYNOS_DISPLAY_TYPE_LCD, 128 .type = EXYNOS_DISPLAY_TYPE_LCD,
129 .is_connected = fimd_display_is_connected, 129 .is_connected = fimd_display_is_connected,
130 .get_timing = fimd_get_timing, 130 .get_timing = fimd_get_timing,
@@ -177,6 +177,40 @@ static void fimd_commit(struct device *dev)
177 writel(val, ctx->regs + VIDCON0); 177 writel(val, ctx->regs + VIDCON0);
178} 178}
179 179
180static void fimd_disable(struct device *dev)
181{
182 struct fimd_context *ctx = get_fimd_context(dev);
183 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
184 struct drm_device *drm_dev = subdrv->drm_dev;
185 struct exynos_drm_manager *manager = &subdrv->manager;
186 u32 val;
187
188 DRM_DEBUG_KMS("%s\n", __FILE__);
189
190 /* fimd dma off */
191 val = readl(ctx->regs + VIDCON0);
192 val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
193 writel(val, ctx->regs + VIDCON0);
194
195 /*
196 * if vblank is enabled status with dma off then
197 * it disables vsync interrupt.
198 */
199 if (drm_dev->vblank_enabled[manager->pipe] &&
200 atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
201 drm_vblank_put(drm_dev, manager->pipe);
202
203 /*
204 * if vblank_disable_allowed is 0 then disable
205 * vsync interrupt right now else the vsync interrupt
206 * would be disabled by drm timer once a current process
207 * gives up ownershop of vblank event.
208 */
209 if (!drm_dev->vblank_disable_allowed)
210 drm_vblank_off(drm_dev, manager->pipe);
211 }
212}
213
180static int fimd_enable_vblank(struct device *dev) 214static int fimd_enable_vblank(struct device *dev)
181{ 215{
182 struct fimd_context *ctx = get_fimd_context(dev); 216 struct fimd_context *ctx = get_fimd_context(dev);
@@ -220,6 +254,7 @@ static void fimd_disable_vblank(struct device *dev)
220 254
221static struct exynos_drm_manager_ops fimd_manager_ops = { 255static struct exynos_drm_manager_ops fimd_manager_ops = {
222 .commit = fimd_commit, 256 .commit = fimd_commit,
257 .disable = fimd_disable,
223 .enable_vblank = fimd_enable_vblank, 258 .enable_vblank = fimd_enable_vblank,
224 .disable_vblank = fimd_disable_vblank, 259 .disable_vblank = fimd_disable_vblank,
225}; 260};
@@ -251,7 +286,7 @@ static void fimd_win_mode_set(struct device *dev,
251 win_data->ovl_height = overlay->crtc_height; 286 win_data->ovl_height = overlay->crtc_height;
252 win_data->fb_width = overlay->fb_width; 287 win_data->fb_width = overlay->fb_width;
253 win_data->fb_height = overlay->fb_height; 288 win_data->fb_height = overlay->fb_height;
254 win_data->paddr = overlay->paddr + offset; 289 win_data->dma_addr = overlay->dma_addr + offset;
255 win_data->vaddr = overlay->vaddr + offset; 290 win_data->vaddr = overlay->vaddr + offset;
256 win_data->bpp = overlay->bpp; 291 win_data->bpp = overlay->bpp;
257 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 292 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
@@ -263,7 +298,7 @@ static void fimd_win_mode_set(struct device *dev,
263 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 298 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
264 win_data->ovl_width, win_data->ovl_height); 299 win_data->ovl_width, win_data->ovl_height);
265 DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", 300 DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
266 (unsigned long)win_data->paddr, 301 (unsigned long)win_data->dma_addr,
267 (unsigned long)win_data->vaddr); 302 (unsigned long)win_data->vaddr);
268 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", 303 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
269 overlay->fb_width, overlay->crtc_width); 304 overlay->fb_width, overlay->crtc_width);
@@ -376,16 +411,16 @@ static void fimd_win_commit(struct device *dev)
376 writel(val, ctx->regs + SHADOWCON); 411 writel(val, ctx->regs + SHADOWCON);
377 412
378 /* buffer start address */ 413 /* buffer start address */
379 val = win_data->paddr; 414 val = (unsigned long)win_data->dma_addr;
380 writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); 415 writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
381 416
382 /* buffer end address */ 417 /* buffer end address */
383 size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3); 418 size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
384 val = win_data->paddr + size; 419 val = (unsigned long)(win_data->dma_addr + size);
385 writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); 420 writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
386 421
387 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", 422 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
388 (unsigned long)win_data->paddr, val, size); 423 (unsigned long)win_data->dma_addr, val, size);
389 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 424 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
390 win_data->ovl_width, win_data->ovl_height); 425 win_data->ovl_width, win_data->ovl_height);
391 426
@@ -447,7 +482,6 @@ static void fimd_win_commit(struct device *dev)
447static void fimd_win_disable(struct device *dev) 482static void fimd_win_disable(struct device *dev)
448{ 483{
449 struct fimd_context *ctx = get_fimd_context(dev); 484 struct fimd_context *ctx = get_fimd_context(dev);
450 struct fimd_win_data *win_data;
451 int win = ctx->default_win; 485 int win = ctx->default_win;
452 u32 val; 486 u32 val;
453 487
@@ -456,8 +490,6 @@ static void fimd_win_disable(struct device *dev)
456 if (win < 0 || win > WINDOWS_NR) 490 if (win < 0 || win > WINDOWS_NR)
457 return; 491 return;
458 492
459 win_data = &ctx->win_data[win];
460
461 /* protect windows */ 493 /* protect windows */
462 val = readl(ctx->regs + SHADOWCON); 494 val = readl(ctx->regs + SHADOWCON);
463 val |= SHADOWCON_WINx_PROTECT(win); 495 val |= SHADOWCON_WINx_PROTECT(win);
@@ -528,6 +560,16 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
528 /* VSYNC interrupt */ 560 /* VSYNC interrupt */
529 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); 561 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
530 562
563 /*
564 * in case that vblank_disable_allowed is 1, it could induce
565 * the problem that manager->pipe could be -1 because with
566 * disable callback, vsync interrupt isn't disabled and at this moment,
567 * vsync interrupt could occur. the vsync interrupt would be disabled
568 * by timer handler later.
569 */
570 if (manager->pipe == -1)
571 return IRQ_HANDLED;
572
531 drm_handle_vblank(drm_dev, manager->pipe); 573 drm_handle_vblank(drm_dev, manager->pipe);
532 fimd_finish_pageflip(drm_dev, manager->pipe); 574 fimd_finish_pageflip(drm_dev, manager->pipe);
533 575
@@ -548,13 +590,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
548 */ 590 */
549 drm_dev->irq_enabled = 1; 591 drm_dev->irq_enabled = 1;
550 592
551 /*
552 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
553 * by drm timer once a current process gives up ownership of
554 * vblank event.(drm_vblank_put function was called)
555 */
556 drm_dev->vblank_disable_allowed = 1;
557
558 return 0; 593 return 0;
559} 594}
560 595
@@ -731,7 +766,7 @@ static int __devinit fimd_probe(struct platform_device *pdev)
731 subdrv->manager.pipe = -1; 766 subdrv->manager.pipe = -1;
732 subdrv->manager.ops = &fimd_manager_ops; 767 subdrv->manager.ops = &fimd_manager_ops;
733 subdrv->manager.overlay_ops = &fimd_overlay_ops; 768 subdrv->manager.overlay_ops = &fimd_overlay_ops;
734 subdrv->manager.display = &fimd_display; 769 subdrv->manager.display_ops = &fimd_display_ops;
735 subdrv->manager.dev = dev; 770 subdrv->manager.dev = dev;
736 771
737 platform_set_drvdata(pdev, ctx); 772 platform_set_drvdata(pdev, ctx);