Lines Matching +full:iommu +full:- +full:ctx

1 // SPDX-License-Identifier: GPL-2.0-or-later
30 #include "regs-decon7.h"
62 {.compatible = "samsung,exynos7-decon"},
86 struct decon_context *ctx = crtc->ctx; in decon_wait_for_vblank() local
88 if (ctx->suspended) in decon_wait_for_vblank()
91 atomic_set(&ctx->wait_vsync_event, 1); in decon_wait_for_vblank()
97 if (!wait_event_timeout(ctx->wait_vsync_queue, in decon_wait_for_vblank()
98 !atomic_read(&ctx->wait_vsync_event), in decon_wait_for_vblank()
100 DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n"); in decon_wait_for_vblank()
105 struct decon_context *ctx = crtc->ctx; in decon_clear_channels() local
110 u32 val = readl(ctx->regs + WINCON(win)); in decon_clear_channels()
114 writel(val, ctx->regs + WINCON(win)); in decon_clear_channels()
121 decon_wait_for_vblank(ctx->crtc); in decon_clear_channels()
124 static int decon_ctx_initialize(struct decon_context *ctx, in decon_ctx_initialize() argument
127 ctx->drm_dev = drm_dev; in decon_ctx_initialize()
129 decon_clear_channels(ctx->crtc); in decon_ctx_initialize()
131 return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv); in decon_ctx_initialize()
134 static void decon_ctx_remove(struct decon_context *ctx) in decon_ctx_remove() argument
136 /* detach this sub driver from iommu mapping if supported. */ in decon_ctx_remove()
137 exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv); in decon_ctx_remove()
140 static u32 decon_calc_clkdiv(struct decon_context *ctx, in decon_calc_clkdiv() argument
143 unsigned long ideal_clk = mode->clock; in decon_calc_clkdiv()
147 clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->vclk), ideal_clk); in decon_calc_clkdiv()
154 struct decon_context *ctx = crtc->ctx; in decon_commit() local
155 struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; in decon_commit()
158 if (ctx->suspended) in decon_commit()
162 if (mode->htotal == 0 || mode->vtotal == 0) in decon_commit()
165 if (!ctx->i80_if) { in decon_commit()
168 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; in decon_commit()
169 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end; in decon_commit()
170 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay; in decon_commit()
172 val = VIDTCON0_VBPD(vbpd - 1) | VIDTCON0_VFPD(vfpd - 1); in decon_commit()
173 writel(val, ctx->regs + VIDTCON0); in decon_commit()
175 val = VIDTCON1_VSPW(vsync_len - 1); in decon_commit()
176 writel(val, ctx->regs + VIDTCON1); in decon_commit()
179 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in decon_commit()
180 hbpd = mode->crtc_htotal - mode->crtc_hsync_end; in decon_commit()
181 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay; in decon_commit()
184 val = VIDTCON2_HBPD(hbpd - 1) | VIDTCON2_HFPD(hfpd - 1); in decon_commit()
185 writel(val, ctx->regs + VIDTCON2); in decon_commit()
187 val = VIDTCON3_HSPW(hsync_len - 1); in decon_commit()
188 writel(val, ctx->regs + VIDTCON3); in decon_commit()
192 val = VIDTCON4_LINEVAL(mode->vdisplay - 1) | in decon_commit()
193 VIDTCON4_HOZVAL(mode->hdisplay - 1); in decon_commit()
194 writel(val, ctx->regs + VIDTCON4); in decon_commit()
196 writel(mode->vdisplay - 1, ctx->regs + LINECNT_OP_THRESHOLD); in decon_commit()
203 writel(val, ctx->regs + VIDCON0); in decon_commit()
205 clkdiv = decon_calc_clkdiv(ctx, mode); in decon_commit()
207 val = VCLKCON1_CLKVAL_NUM_VCLK(clkdiv - 1); in decon_commit()
208 writel(val, ctx->regs + VCLKCON1); in decon_commit()
209 writel(val, ctx->regs + VCLKCON2); in decon_commit()
212 val = readl(ctx->regs + DECON_UPDATE); in decon_commit()
214 writel(val, ctx->regs + DECON_UPDATE); in decon_commit()
219 struct decon_context *ctx = crtc->ctx; in decon_enable_vblank() local
222 if (ctx->suspended) in decon_enable_vblank()
223 return -EPERM; in decon_enable_vblank()
225 if (!test_and_set_bit(0, &ctx->irq_flags)) { in decon_enable_vblank()
226 val = readl(ctx->regs + VIDINTCON0); in decon_enable_vblank()
230 if (!ctx->i80_if) { in decon_enable_vblank()
236 writel(val, ctx->regs + VIDINTCON0); in decon_enable_vblank()
244 struct decon_context *ctx = crtc->ctx; in decon_disable_vblank() local
247 if (ctx->suspended) in decon_disable_vblank()
250 if (test_and_clear_bit(0, &ctx->irq_flags)) { in decon_disable_vblank()
251 val = readl(ctx->regs + VIDINTCON0); in decon_disable_vblank()
254 if (!ctx->i80_if) in decon_disable_vblank()
257 writel(val, ctx->regs + VIDINTCON0); in decon_disable_vblank()
261 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, in decon_win_set_pixfmt() argument
267 val = readl(ctx->regs + WINCON(win)); in decon_win_set_pixfmt()
270 switch (fb->format->format) { in decon_win_set_pixfmt()
314 DRM_DEV_DEBUG_KMS(ctx->dev, "cpp = %d\n", fb->format->cpp[0]); in decon_win_set_pixfmt()
317 * In case of exynos, setting dma-burst to 16Word causes permanent in decon_win_set_pixfmt()
321 * movement causes unstable DMA which results into iommu crash/tear. in decon_win_set_pixfmt()
324 padding = (fb->pitches[0] / fb->format->cpp[0]) - fb->width; in decon_win_set_pixfmt()
325 if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { in decon_win_set_pixfmt()
330 writel(val, ctx->regs + WINCON(win)); in decon_win_set_pixfmt()
333 static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win) in decon_win_set_colkey() argument
342 writel(keycon0, ctx->regs + WKEYCON0_BASE(win)); in decon_win_set_colkey()
343 writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); in decon_win_set_colkey()
347 * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
349 * @ctx: display and enhancement controller context
353 static void decon_shadow_protect_win(struct decon_context *ctx, in decon_shadow_protect_win() argument
360 val = readl(ctx->regs + SHADOWCON); in decon_shadow_protect_win()
365 writel(val, ctx->regs + SHADOWCON); in decon_shadow_protect_win()
370 struct decon_context *ctx = crtc->ctx; in decon_atomic_begin() local
373 if (ctx->suspended) in decon_atomic_begin()
377 decon_shadow_protect_win(ctx, i, true); in decon_atomic_begin()
384 to_exynos_plane_state(plane->base.state); in decon_update_plane()
385 struct decon_context *ctx = crtc->ctx; in decon_update_plane() local
386 struct drm_framebuffer *fb = state->base.fb; in decon_update_plane()
391 unsigned int win = plane->index; in decon_update_plane()
392 unsigned int cpp = fb->format->cpp[0]; in decon_update_plane()
393 unsigned int pitch = fb->pitches[0]; in decon_update_plane()
395 if (ctx->suspended) in decon_update_plane()
410 writel(val, ctx->regs + VIDW_BUF_START(win)); in decon_update_plane()
412 padding = (pitch / cpp) - fb->width; in decon_update_plane()
415 writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win)); in decon_update_plane()
416 writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win)); in decon_update_plane()
419 writel(state->src.x, ctx->regs + VIDW_OFFSET_X(win)); in decon_update_plane()
420 writel(state->src.y, ctx->regs + VIDW_OFFSET_Y(win)); in decon_update_plane()
422 DRM_DEV_DEBUG_KMS(ctx->dev, "start addr = 0x%lx\n", in decon_update_plane()
424 DRM_DEV_DEBUG_KMS(ctx->dev, "ovl_width = %d, ovl_height = %d\n", in decon_update_plane()
425 state->crtc.w, state->crtc.h); in decon_update_plane()
427 val = VIDOSDxA_TOPLEFT_X(state->crtc.x) | in decon_update_plane()
428 VIDOSDxA_TOPLEFT_Y(state->crtc.y); in decon_update_plane()
429 writel(val, ctx->regs + VIDOSD_A(win)); in decon_update_plane()
431 last_x = state->crtc.x + state->crtc.w; in decon_update_plane()
433 last_x--; in decon_update_plane()
434 last_y = state->crtc.y + state->crtc.h; in decon_update_plane()
436 last_y--; in decon_update_plane()
440 writel(val, ctx->regs + VIDOSD_B(win)); in decon_update_plane()
442 DRM_DEV_DEBUG_KMS(ctx->dev, "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", in decon_update_plane()
443 state->crtc.x, state->crtc.y, last_x, last_y); in decon_update_plane()
450 writel(alpha, ctx->regs + VIDOSD_C(win)); in decon_update_plane()
456 writel(alpha, ctx->regs + VIDOSD_D(win)); in decon_update_plane()
458 decon_win_set_pixfmt(ctx, win, fb); in decon_update_plane()
462 decon_win_set_colkey(ctx, win); in decon_update_plane()
465 val = readl(ctx->regs + WINCON(win)); in decon_update_plane()
468 writel(val, ctx->regs + WINCON(win)); in decon_update_plane()
471 decon_shadow_protect_win(ctx, win, false); in decon_update_plane()
473 val = readl(ctx->regs + DECON_UPDATE); in decon_update_plane()
475 writel(val, ctx->regs + DECON_UPDATE); in decon_update_plane()
481 struct decon_context *ctx = crtc->ctx; in decon_disable_plane() local
482 unsigned int win = plane->index; in decon_disable_plane()
485 if (ctx->suspended) in decon_disable_plane()
489 decon_shadow_protect_win(ctx, win, true); in decon_disable_plane()
492 val = readl(ctx->regs + WINCON(win)); in decon_disable_plane()
494 writel(val, ctx->regs + WINCON(win)); in decon_disable_plane()
496 val = readl(ctx->regs + DECON_UPDATE); in decon_disable_plane()
498 writel(val, ctx->regs + DECON_UPDATE); in decon_disable_plane()
503 struct decon_context *ctx = crtc->ctx; in decon_atomic_flush() local
506 if (ctx->suspended) in decon_atomic_flush()
510 decon_shadow_protect_win(ctx, i, false); in decon_atomic_flush()
514 static void decon_init(struct decon_context *ctx) in decon_init() argument
518 writel(VIDCON0_SWRESET, ctx->regs + VIDCON0); in decon_init()
521 if (!ctx->i80_if) in decon_init()
523 writel(val, ctx->regs + VIDOUTCON0); in decon_init()
525 writel(VCLKCON0_CLKVALUP | VCLKCON0_VCLKFREE, ctx->regs + VCLKCON0); in decon_init()
527 if (!ctx->i80_if) in decon_init()
528 writel(VIDCON1_VCLK_HOLD, ctx->regs + VIDCON1(0)); in decon_init()
533 struct decon_context *ctx = crtc->ctx; in decon_atomic_enable() local
536 if (!ctx->suspended) in decon_atomic_enable()
539 ret = pm_runtime_resume_and_get(ctx->dev); in decon_atomic_enable()
541 DRM_DEV_ERROR(ctx->dev, "failed to enable DECON device.\n"); in decon_atomic_enable()
545 decon_init(ctx); in decon_atomic_enable()
548 if (test_and_clear_bit(0, &ctx->irq_flags)) in decon_atomic_enable()
549 decon_enable_vblank(ctx->crtc); in decon_atomic_enable()
551 decon_commit(ctx->crtc); in decon_atomic_enable()
553 ctx->suspended = false; in decon_atomic_enable()
558 struct decon_context *ctx = crtc->ctx; in decon_atomic_disable() local
561 if (ctx->suspended) in decon_atomic_disable()
570 decon_disable_plane(crtc, &ctx->planes[i]); in decon_atomic_disable()
572 pm_runtime_put_sync(ctx->dev); in decon_atomic_disable()
574 ctx->suspended = true; in decon_atomic_disable()
591 struct decon_context *ctx = (struct decon_context *)dev_id; in decon_irq_handler() local
594 val = readl(ctx->regs + VIDINTCON1); in decon_irq_handler()
596 clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME; in decon_irq_handler()
598 writel(clear_bit, ctx->regs + VIDINTCON1); in decon_irq_handler()
601 if (!ctx->drm_dev) in decon_irq_handler()
604 if (!ctx->i80_if) { in decon_irq_handler()
605 drm_crtc_handle_vblank(&ctx->crtc->base); in decon_irq_handler()
608 if (atomic_read(&ctx->wait_vsync_event)) { in decon_irq_handler()
609 atomic_set(&ctx->wait_vsync_event, 0); in decon_irq_handler()
610 wake_up(&ctx->wait_vsync_queue); in decon_irq_handler()
619 struct decon_context *ctx = dev_get_drvdata(dev); in decon_bind() local
625 ret = decon_ctx_initialize(ctx, drm_dev); in decon_bind()
632 ctx->configs[i].pixel_formats = decon_formats; in decon_bind()
633 ctx->configs[i].num_pixel_formats = ARRAY_SIZE(decon_formats); in decon_bind()
634 ctx->configs[i].zpos = i; in decon_bind()
635 ctx->configs[i].type = decon_win_types[i]; in decon_bind()
637 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, in decon_bind()
638 &ctx->configs[i]); in decon_bind()
643 exynos_plane = &ctx->planes[DEFAULT_WIN]; in decon_bind()
644 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, in decon_bind()
645 EXYNOS_DISPLAY_TYPE_LCD, &decon_crtc_ops, ctx); in decon_bind()
646 if (IS_ERR(ctx->crtc)) { in decon_bind()
647 decon_ctx_remove(ctx); in decon_bind()
648 return PTR_ERR(ctx->crtc); in decon_bind()
651 if (ctx->encoder) in decon_bind()
652 exynos_dpi_bind(drm_dev, ctx->encoder); in decon_bind()
661 struct decon_context *ctx = dev_get_drvdata(dev); in decon_unbind() local
663 decon_atomic_disable(ctx->crtc); in decon_unbind()
665 if (ctx->encoder) in decon_unbind()
666 exynos_dpi_remove(ctx->encoder); in decon_unbind()
668 decon_ctx_remove(ctx); in decon_unbind()
678 struct device *dev = &pdev->dev; in decon_probe()
679 struct decon_context *ctx; in decon_probe() local
683 if (!dev->of_node) in decon_probe()
684 return -ENODEV; in decon_probe()
686 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); in decon_probe()
687 if (!ctx) in decon_probe()
688 return -ENOMEM; in decon_probe()
690 ctx->dev = dev; in decon_probe()
691 ctx->suspended = true; in decon_probe()
693 i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings"); in decon_probe()
695 ctx->i80_if = true; in decon_probe()
698 ctx->regs = of_iomap(dev->of_node, 0); in decon_probe()
699 if (!ctx->regs) in decon_probe()
700 return -ENOMEM; in decon_probe()
702 ctx->pclk = devm_clk_get(dev, "pclk_decon0"); in decon_probe()
703 if (IS_ERR(ctx->pclk)) { in decon_probe()
705 ret = PTR_ERR(ctx->pclk); in decon_probe()
709 ctx->aclk = devm_clk_get(dev, "aclk_decon0"); in decon_probe()
710 if (IS_ERR(ctx->aclk)) { in decon_probe()
712 ret = PTR_ERR(ctx->aclk); in decon_probe()
716 ctx->eclk = devm_clk_get(dev, "decon0_eclk"); in decon_probe()
717 if (IS_ERR(ctx->eclk)) { in decon_probe()
719 ret = PTR_ERR(ctx->eclk); in decon_probe()
723 ctx->vclk = devm_clk_get(dev, "decon0_vclk"); in decon_probe()
724 if (IS_ERR(ctx->vclk)) { in decon_probe()
726 ret = PTR_ERR(ctx->vclk); in decon_probe()
730 ret = platform_get_irq_byname(pdev, ctx->i80_if ? "lcd_sys" : "vsync"); in decon_probe()
734 ret = devm_request_irq(dev, ret, decon_irq_handler, 0, "drm_decon", ctx); in decon_probe()
740 init_waitqueue_head(&ctx->wait_vsync_queue); in decon_probe()
741 atomic_set(&ctx->wait_vsync_event, 0); in decon_probe()
743 platform_set_drvdata(pdev, ctx); in decon_probe()
745 ctx->encoder = exynos_dpi_probe(dev); in decon_probe()
746 if (IS_ERR(ctx->encoder)) { in decon_probe()
747 ret = PTR_ERR(ctx->encoder); in decon_probe()
763 iounmap(ctx->regs); in decon_probe()
770 struct decon_context *ctx = dev_get_drvdata(&pdev->dev); in decon_remove() local
772 pm_runtime_disable(&pdev->dev); in decon_remove()
774 iounmap(ctx->regs); in decon_remove()
776 component_del(&pdev->dev, &decon_component_ops); in decon_remove()
781 struct decon_context *ctx = dev_get_drvdata(dev); in exynos7_decon_suspend() local
783 clk_disable_unprepare(ctx->vclk); in exynos7_decon_suspend()
784 clk_disable_unprepare(ctx->eclk); in exynos7_decon_suspend()
785 clk_disable_unprepare(ctx->aclk); in exynos7_decon_suspend()
786 clk_disable_unprepare(ctx->pclk); in exynos7_decon_suspend()
793 struct decon_context *ctx = dev_get_drvdata(dev); in exynos7_decon_resume() local
796 ret = clk_prepare_enable(ctx->pclk); in exynos7_decon_resume()
803 ret = clk_prepare_enable(ctx->aclk); in exynos7_decon_resume()
810 ret = clk_prepare_enable(ctx->eclk); in exynos7_decon_resume()
817 ret = clk_prepare_enable(ctx->vclk); in exynos7_decon_resume()
827 clk_disable_unprepare(ctx->eclk); in exynos7_decon_resume()
829 clk_disable_unprepare(ctx->aclk); in exynos7_decon_resume()
831 clk_disable_unprepare(ctx->pclk); in exynos7_decon_resume()
843 .name = "exynos-decon",