Lines Matching +full:exynos5250 +full:- +full:mixer

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Seung-Woo Kim <sw0312.kim@samsung.com>
9 * Based on drivers/media/video/s5p-tv/mixer_reg.c
39 #include "regs-mixer.h"
40 #include "regs-vp.h"
46 * Mixer color space conversion coefficient triplet.
48 * Each coefficient is a 10-bit fixed point number with
58 /* YCbCr value, used for mixer background color configuration. */
61 /* The pixelformats that are natively supported by the mixer. */
109 struct clk *mixer; member
157 0, -1, -1, -1, -1, -1, -1, -1,
158 -1, -1, -1, -1, -1, 0, 0, 0,
161 0, -6, -12, -16, -18, -20, -21, -20,
162 -20, -18, -16, -13, -10, -8, -5, -2,
168 0, -3, -6, -8, -8, -8, -8, -7,
169 -6, -5, -4, -3, -2, -1, -1, 0,
174 0, 0, -1, -1, -2, -3, -4, -5,
175 -6, -7, -8, -8, -8, -8, -6, -3,
179 0, -3, -6, -8, -8, -8, -8, -7,
180 -6, -5, -4, -3, -2, -1, -1, 0,
187 return readl(ctx->vp_regs + reg_id); in vp_reg_read()
193 writel(val, ctx->vp_regs + reg_id); in vp_reg_write()
202 writel(val, ctx->vp_regs + reg_id); in vp_reg_writemask()
207 return readl(ctx->mixer_regs + reg_id); in mixer_reg_read()
213 writel(val, ctx->mixer_regs + reg_id); in mixer_reg_write()
222 writel(val, ctx->mixer_regs + reg_id); in mixer_reg_writemask()
229 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \ in mixer_regs_dump()
230 (u32)readl(ctx->mixer_regs + reg_id)); \ in mixer_regs_dump()
261 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \ in vp_regs_dump()
262 (u32) readl(ctx->vp_regs + reg_id)); \ in vp_regs_dump()
295 /* assure 4-byte align */ in vp_filter_set()
297 for (; size; size -= 4, reg_id += 4, data += 4) { in vp_filter_set()
358 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || in mixer_is_synced()
359 ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_is_synced()
363 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && in mixer_is_synced()
392 return -ETIMEDOUT; in mixer_wait_for_sync()
404 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || in mixer_enable_sync()
405 ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_enable_sync()
408 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) in mixer_enable_sync()
417 val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? in mixer_cfg_scan()
420 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_cfg_scan()
424 val |= ctx->scan_value; in mixer_cfg_scan()
434 if (mode->vdisplay < 720) { in mixer_cfg_rgb_fmt()
444 MXR_CSC_CT(-0.102, -0.338, 0.440)); in mixer_cfg_rgb_fmt()
446 MXR_CSC_CT( 0.440, -0.399, -0.040)); in mixer_cfg_rgb_fmt()
477 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in mixer_cfg_layer()
501 --timeout) in mixer_stop()
507 struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode; in mixer_commit()
509 mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay); in mixer_commit()
518 to_exynos_plane_state(plane->base.state); in vp_video_buffer()
519 struct drm_framebuffer *fb = state->base.fb; in vp_video_buffer()
520 unsigned int priority = state->base.normalized_zpos + 1; in vp_video_buffer()
526 is_nv21 = (fb->format->format == DRM_FORMAT_NV21); in vp_video_buffer()
527 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE); in vp_video_buffer()
532 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { in vp_video_buffer()
537 luma_addr[1] = luma_addr[0] + fb->pitches[0]; in vp_video_buffer()
538 chroma_addr[1] = chroma_addr[0] + fb->pitches[1]; in vp_video_buffer()
545 spin_lock_irqsave(&ctx->reg_slock, flags); in vp_video_buffer()
548 val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); in vp_video_buffer()
557 vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | in vp_video_buffer()
558 VP_IMG_VSIZE(fb->height)); in vp_video_buffer()
560 vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) | in vp_video_buffer()
561 VP_IMG_VSIZE(fb->height / 2)); in vp_video_buffer()
563 vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w); in vp_video_buffer()
565 VP_SRC_H_POSITION_VAL(state->src.x)); in vp_video_buffer()
566 vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w); in vp_video_buffer()
567 vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x); in vp_video_buffer()
569 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { in vp_video_buffer()
570 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2); in vp_video_buffer()
571 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2); in vp_video_buffer()
572 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2); in vp_video_buffer()
573 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2); in vp_video_buffer()
575 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h); in vp_video_buffer()
576 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y); in vp_video_buffer()
577 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h); in vp_video_buffer()
578 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y); in vp_video_buffer()
581 vp_reg_write(ctx, VP_H_RATIO, state->h_ratio); in vp_video_buffer()
582 vp_reg_write(ctx, VP_V_RATIO, state->v_ratio); in vp_video_buffer()
592 mixer_cfg_layer(ctx, plane->index, priority, true); in vp_video_buffer()
593 mixer_cfg_vp_blend(ctx, state->base.alpha); in vp_video_buffer()
595 spin_unlock_irqrestore(&ctx->reg_slock, flags); in vp_video_buffer()
605 to_exynos_plane_state(plane->base.state); in mixer_graph_buffer()
606 struct drm_framebuffer *fb = state->base.fb; in mixer_graph_buffer()
607 unsigned int priority = state->base.normalized_zpos + 1; in mixer_graph_buffer()
609 unsigned int win = plane->index; in mixer_graph_buffer()
617 if (fb->format->has_alpha) in mixer_graph_buffer()
618 pixel_alpha = state->base.pixel_blend_mode; in mixer_graph_buffer()
622 switch (fb->format->format) { in mixer_graph_buffer()
645 x_ratio = state->h_ratio == (1 << 15); in mixer_graph_buffer()
646 y_ratio = state->v_ratio == (1 << 15); in mixer_graph_buffer()
648 dst_x_offset = state->crtc.x; in mixer_graph_buffer()
649 dst_y_offset = state->crtc.y; in mixer_graph_buffer()
653 + (state->src.x * fb->format->cpp[0]) in mixer_graph_buffer()
654 + (state->src.y * fb->pitches[0]); in mixer_graph_buffer()
656 spin_lock_irqsave(&ctx->reg_slock, flags); in mixer_graph_buffer()
664 fb->pitches[0] / fb->format->cpp[0]); in mixer_graph_buffer()
666 val = MXR_GRP_WH_WIDTH(state->src.w); in mixer_graph_buffer()
667 val |= MXR_GRP_WH_HEIGHT(state->src.h); in mixer_graph_buffer()
677 /* set buffer address to mixer */ in mixer_graph_buffer()
681 mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha); in mixer_graph_buffer()
683 spin_unlock_irqrestore(&ctx->reg_slock, flags); in mixer_graph_buffer()
693 while (--tries) { in vp_win_reset()
706 spin_lock_irqsave(&ctx->reg_slock, flags); in mixer_win_reset()
725 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in mixer_win_reset()
734 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) in mixer_win_reset()
741 spin_unlock_irqrestore(&ctx->reg_slock, flags); in mixer_win_reset()
749 spin_lock(&ctx->reg_slock); in mixer_irq_handler()
761 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags) in mixer_irq_handler()
765 drm_crtc_handle_vblank(&ctx->crtc->base); in mixer_irq_handler()
772 spin_unlock(&ctx->reg_slock); in mixer_irq_handler()
779 struct device *dev = &mixer_ctx->pdev->dev; in mixer_resources_init()
783 spin_lock_init(&mixer_ctx->reg_slock); in mixer_resources_init()
785 mixer_ctx->mixer = devm_clk_get(dev, "mixer"); in mixer_resources_init()
786 if (IS_ERR(mixer_ctx->mixer)) { in mixer_resources_init()
787 dev_err(dev, "failed to get clock 'mixer'\n"); in mixer_resources_init()
788 return -ENODEV; in mixer_resources_init()
791 mixer_ctx->hdmi = devm_clk_get(dev, "hdmi"); in mixer_resources_init()
792 if (IS_ERR(mixer_ctx->hdmi)) { in mixer_resources_init()
794 return PTR_ERR(mixer_ctx->hdmi); in mixer_resources_init()
797 mixer_ctx->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); in mixer_resources_init()
798 if (IS_ERR(mixer_ctx->sclk_hdmi)) { in mixer_resources_init()
800 return -ENODEV; in mixer_resources_init()
802 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0); in mixer_resources_init()
805 return -ENXIO; in mixer_resources_init()
808 mixer_ctx->mixer_regs = devm_ioremap(dev, res->start, in mixer_resources_init()
810 if (mixer_ctx->mixer_regs == NULL) { in mixer_resources_init()
812 return -ENXIO; in mixer_resources_init()
815 ret = platform_get_irq(mixer_ctx->pdev, 0); in mixer_resources_init()
818 mixer_ctx->irq = ret; in mixer_resources_init()
820 ret = devm_request_irq(dev, mixer_ctx->irq, mixer_irq_handler, in mixer_resources_init()
832 struct device *dev = &mixer_ctx->pdev->dev; in vp_resources_init()
835 mixer_ctx->vp = devm_clk_get(dev, "vp"); in vp_resources_init()
836 if (IS_ERR(mixer_ctx->vp)) { in vp_resources_init()
838 return -ENODEV; in vp_resources_init()
841 if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) { in vp_resources_init()
842 mixer_ctx->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); in vp_resources_init()
843 if (IS_ERR(mixer_ctx->sclk_mixer)) { in vp_resources_init()
845 return -ENODEV; in vp_resources_init()
847 mixer_ctx->mout_mixer = devm_clk_get(dev, "mout_mixer"); in vp_resources_init()
848 if (IS_ERR(mixer_ctx->mout_mixer)) { in vp_resources_init()
850 return -ENODEV; in vp_resources_init()
853 if (mixer_ctx->sclk_hdmi && mixer_ctx->mout_mixer) in vp_resources_init()
854 clk_set_parent(mixer_ctx->mout_mixer, in vp_resources_init()
855 mixer_ctx->sclk_hdmi); in vp_resources_init()
858 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); in vp_resources_init()
861 return -ENXIO; in vp_resources_init()
864 mixer_ctx->vp_regs = devm_ioremap(dev, res->start, in vp_resources_init()
866 if (mixer_ctx->vp_regs == NULL) { in vp_resources_init()
868 return -ENXIO; in vp_resources_init()
879 mixer_ctx->drm_dev = drm_dev; in mixer_initialize()
884 DRM_DEV_ERROR(mixer_ctx->dev, in mixer_initialize()
889 if (test_bit(MXR_BIT_VP_ENABLED, &mixer_ctx->flags)) { in mixer_initialize()
893 DRM_DEV_ERROR(mixer_ctx->dev, in mixer_initialize()
899 return exynos_drm_register_dma(drm_dev, mixer_ctx->dev, in mixer_initialize()
900 &mixer_ctx->dma_priv); in mixer_initialize()
905 exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev, in mixer_ctx_remove()
906 &mixer_ctx->dma_priv); in mixer_ctx_remove()
911 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_enable_vblank()
913 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); in mixer_enable_vblank()
914 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_enable_vblank()
926 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_disable_vblank()
928 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); in mixer_disable_vblank()
930 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_disable_vblank()
940 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_begin()
942 if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_begin()
946 dev_err(ctx->dev, "timeout waiting for VSYNC\n"); in mixer_atomic_begin()
953 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_update_plane()
955 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index); in mixer_update_plane()
957 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_update_plane()
960 if (plane->index == VP_DEFAULT_WIN) in mixer_update_plane()
969 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_disable_plane()
972 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index); in mixer_disable_plane()
974 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_disable_plane()
977 spin_lock_irqsave(&mixer_ctx->reg_slock, flags); in mixer_disable_plane()
978 mixer_cfg_layer(mixer_ctx, plane->index, 0, false); in mixer_disable_plane()
979 spin_unlock_irqrestore(&mixer_ctx->reg_slock, flags); in mixer_disable_plane()
984 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_atomic_flush()
986 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_atomic_flush()
995 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_enable()
998 if (test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_enable()
1001 ret = pm_runtime_resume_and_get(ctx->dev); in mixer_atomic_enable()
1003 dev_err(ctx->dev, "failed to enable MIXER device.\n"); in mixer_atomic_enable()
1013 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) { in mixer_atomic_enable()
1024 set_bit(MXR_BIT_POWERED, &ctx->flags); in mixer_atomic_enable()
1029 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_disable()
1032 if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_disable()
1039 mixer_disable_plane(crtc, &ctx->planes[i]); in mixer_atomic_disable()
1043 pm_runtime_put(ctx->dev); in mixer_atomic_disable()
1045 clear_bit(MXR_BIT_POWERED, &ctx->flags); in mixer_atomic_disable()
1051 struct mixer_context *ctx = crtc->ctx; in mixer_mode_valid()
1052 u32 w = mode->hdisplay, h = mode->vdisplay; in mixer_mode_valid()
1054 DRM_DEV_DEBUG_KMS(ctx->dev, "xres=%d, yres=%d, refresh=%d, intl=%d\n", in mixer_mode_valid()
1056 !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); in mixer_mode_valid()
1058 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_mode_valid()
1078 struct mixer_context *ctx = crtc->ctx; in mixer_mode_fixup()
1079 int width = mode->hdisplay, height = mode->vdisplay, i; in mixer_mode_fixup()
1091 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in mixer_mode_fixup()
1092 __set_bit(MXR_BIT_INTERLACE, &ctx->flags); in mixer_mode_fixup()
1094 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); in mixer_mode_fixup()
1096 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_mode_fixup()
1101 ctx->scan_value = modes[i].scan_val; in mixer_mode_fixup()
1104 adjusted_mode->hdisplay = modes[i].hdisplay; in mixer_mode_fixup()
1105 adjusted_mode->hsync_start = modes[i].hdisplay; in mixer_mode_fixup()
1106 adjusted_mode->hsync_end = modes[i].htotal; in mixer_mode_fixup()
1107 adjusted_mode->htotal = modes[i].htotal; in mixer_mode_fixup()
1108 adjusted_mode->vdisplay = modes[i].vdisplay; in mixer_mode_fixup()
1109 adjusted_mode->vsync_start = modes[i].vdisplay; in mixer_mode_fixup()
1110 adjusted_mode->vsync_end = modes[i].vtotal; in mixer_mode_fixup()
1111 adjusted_mode->vtotal = modes[i].vtotal; in mixer_mode_fixup()
1156 .compatible = "samsung,exynos4210-mixer",
1159 .compatible = "samsung,exynos4212-mixer",
1162 .compatible = "samsung,exynos5-mixer",
1165 .compatible = "samsung,exynos5250-mixer",
1168 .compatible = "samsung,exynos5420-mixer",
1190 &ctx->flags)) in mixer_bind()
1193 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, in mixer_bind()
1199 exynos_plane = &ctx->planes[DEFAULT_WIN]; in mixer_bind()
1200 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, in mixer_bind()
1202 if (IS_ERR(ctx->crtc)) { in mixer_bind()
1204 ret = PTR_ERR(ctx->crtc); in mixer_bind()
1229 struct device *dev = &pdev->dev; in mixer_probe()
1234 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); in mixer_probe()
1236 DRM_DEV_ERROR(dev, "failed to alloc mixer context.\n"); in mixer_probe()
1237 return -ENOMEM; in mixer_probe()
1242 ctx->pdev = pdev; in mixer_probe()
1243 ctx->dev = dev; in mixer_probe()
1244 ctx->mxr_ver = drv->version; in mixer_probe()
1246 if (drv->is_vp_enabled) in mixer_probe()
1247 __set_bit(MXR_BIT_VP_ENABLED, &ctx->flags); in mixer_probe()
1248 if (drv->has_sclk) in mixer_probe()
1249 __set_bit(MXR_BIT_HAS_SCLK, &ctx->flags); in mixer_probe()
1255 ret = component_add(&pdev->dev, &mixer_component_ops); in mixer_probe()
1264 pm_runtime_disable(&pdev->dev); in mixer_remove()
1266 component_del(&pdev->dev, &mixer_component_ops); in mixer_remove()
1275 clk_disable_unprepare(ctx->hdmi); in exynos_mixer_suspend()
1276 clk_disable_unprepare(ctx->mixer); in exynos_mixer_suspend()
1277 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in exynos_mixer_suspend()
1278 clk_disable_unprepare(ctx->vp); in exynos_mixer_suspend()
1279 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) in exynos_mixer_suspend()
1280 clk_disable_unprepare(ctx->sclk_mixer); in exynos_mixer_suspend()
1291 ret = clk_prepare_enable(ctx->mixer); in exynos_mixer_resume()
1293 DRM_DEV_ERROR(ctx->dev, in exynos_mixer_resume()
1294 "Failed to prepare_enable the mixer clk [%d]\n", in exynos_mixer_resume()
1298 ret = clk_prepare_enable(ctx->hdmi); in exynos_mixer_resume()
1305 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in exynos_mixer_resume()
1306 ret = clk_prepare_enable(ctx->vp); in exynos_mixer_resume()
1313 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) { in exynos_mixer_resume()
1314 ret = clk_prepare_enable(ctx->sclk_mixer); in exynos_mixer_resume()
1336 .name = "exynos-mixer",