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
38 #include "regs-mixer.h"
39 #include "regs-vp.h"
45 * Mixer color space conversion coefficient triplet.
47 * Each coefficient is a 10-bit fixed point number with
57 /* YCbCr value, used for mixer background color configuration. */
60 /* The pixelformats that are natively supported by the mixer. */
108 struct clk *mixer; member
156 0, -1, -1, -1, -1, -1, -1, -1,
157 -1, -1, -1, -1, -1, 0, 0, 0,
160 0, -6, -12, -16, -18, -20, -21, -20,
161 -20, -18, -16, -13, -10, -8, -5, -2,
167 0, -3, -6, -8, -8, -8, -8, -7,
168 -6, -5, -4, -3, -2, -1, -1, 0,
173 0, 0, -1, -1, -2, -3, -4, -5,
174 -6, -7, -8, -8, -8, -8, -6, -3,
178 0, -3, -6, -8, -8, -8, -8, -7,
179 -6, -5, -4, -3, -2, -1, -1, 0,
186 return readl(ctx->vp_regs + reg_id); in vp_reg_read()
192 writel(val, ctx->vp_regs + reg_id); in vp_reg_write()
201 writel(val, ctx->vp_regs + reg_id); in vp_reg_writemask()
206 return readl(ctx->mixer_regs + reg_id); in mixer_reg_read()
212 writel(val, ctx->mixer_regs + reg_id); in mixer_reg_write()
221 writel(val, ctx->mixer_regs + reg_id); in mixer_reg_writemask()
228 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \ in mixer_regs_dump()
229 (u32)readl(ctx->mixer_regs + reg_id)); \ in mixer_regs_dump()
260 DRM_DEV_DEBUG_KMS(ctx->dev, #reg_id " = %08x\n", \ in vp_regs_dump()
261 (u32) readl(ctx->vp_regs + reg_id)); \ in vp_regs_dump()
294 /* assure 4-byte align */ in vp_filter_set()
296 for (; size; size -= 4, reg_id += 4, data += 4) { in vp_filter_set()
357 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || in mixer_is_synced()
358 ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_is_synced()
362 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && in mixer_is_synced()
391 return -ETIMEDOUT; in mixer_wait_for_sync()
403 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || in mixer_enable_sync()
404 ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_enable_sync()
407 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) in mixer_enable_sync()
416 val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? in mixer_cfg_scan()
419 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_cfg_scan()
423 val |= ctx->scan_value; in mixer_cfg_scan()
433 if (mode->vdisplay < 720) { in mixer_cfg_rgb_fmt()
443 MXR_CSC_CT(-0.102, -0.338, 0.440)); in mixer_cfg_rgb_fmt()
445 MXR_CSC_CT( 0.440, -0.399, -0.040)); in mixer_cfg_rgb_fmt()
476 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in mixer_cfg_layer()
500 --timeout) in mixer_stop()
506 struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode; in mixer_commit()
508 mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay); in mixer_commit()
517 to_exynos_plane_state(plane->base.state); in vp_video_buffer()
518 struct drm_framebuffer *fb = state->base.fb; in vp_video_buffer()
519 unsigned int priority = state->base.normalized_zpos + 1; in vp_video_buffer()
525 is_nv21 = (fb->format->format == DRM_FORMAT_NV21); in vp_video_buffer()
526 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE); in vp_video_buffer()
531 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { in vp_video_buffer()
536 luma_addr[1] = luma_addr[0] + fb->pitches[0]; in vp_video_buffer()
537 chroma_addr[1] = chroma_addr[0] + fb->pitches[1]; in vp_video_buffer()
544 spin_lock_irqsave(&ctx->reg_slock, flags); in vp_video_buffer()
547 val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); in vp_video_buffer()
556 vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | in vp_video_buffer()
557 VP_IMG_VSIZE(fb->height)); in vp_video_buffer()
559 vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) | in vp_video_buffer()
560 VP_IMG_VSIZE(fb->height / 2)); in vp_video_buffer()
562 vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w); in vp_video_buffer()
564 VP_SRC_H_POSITION_VAL(state->src.x)); in vp_video_buffer()
565 vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w); in vp_video_buffer()
566 vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x); in vp_video_buffer()
568 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { in vp_video_buffer()
569 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2); in vp_video_buffer()
570 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2); in vp_video_buffer()
571 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2); in vp_video_buffer()
572 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2); in vp_video_buffer()
574 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h); in vp_video_buffer()
575 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y); in vp_video_buffer()
576 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h); in vp_video_buffer()
577 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y); in vp_video_buffer()
580 vp_reg_write(ctx, VP_H_RATIO, state->h_ratio); in vp_video_buffer()
581 vp_reg_write(ctx, VP_V_RATIO, state->v_ratio); in vp_video_buffer()
591 mixer_cfg_layer(ctx, plane->index, priority, true); in vp_video_buffer()
592 mixer_cfg_vp_blend(ctx, state->base.alpha); in vp_video_buffer()
594 spin_unlock_irqrestore(&ctx->reg_slock, flags); in vp_video_buffer()
604 to_exynos_plane_state(plane->base.state); in mixer_graph_buffer()
605 struct drm_framebuffer *fb = state->base.fb; in mixer_graph_buffer()
606 unsigned int priority = state->base.normalized_zpos + 1; in mixer_graph_buffer()
608 unsigned int win = plane->index; in mixer_graph_buffer()
616 if (fb->format->has_alpha) in mixer_graph_buffer()
617 pixel_alpha = state->base.pixel_blend_mode; in mixer_graph_buffer()
621 switch (fb->format->format) { in mixer_graph_buffer()
644 x_ratio = state->h_ratio == (1 << 15); in mixer_graph_buffer()
645 y_ratio = state->v_ratio == (1 << 15); in mixer_graph_buffer()
647 dst_x_offset = state->crtc.x; in mixer_graph_buffer()
648 dst_y_offset = state->crtc.y; in mixer_graph_buffer()
652 + (state->src.x * fb->format->cpp[0]) in mixer_graph_buffer()
653 + (state->src.y * fb->pitches[0]); in mixer_graph_buffer()
655 spin_lock_irqsave(&ctx->reg_slock, flags); in mixer_graph_buffer()
663 fb->pitches[0] / fb->format->cpp[0]); in mixer_graph_buffer()
665 val = MXR_GRP_WH_WIDTH(state->src.w); in mixer_graph_buffer()
666 val |= MXR_GRP_WH_HEIGHT(state->src.h); in mixer_graph_buffer()
676 /* set buffer address to mixer */ in mixer_graph_buffer()
680 mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha); in mixer_graph_buffer()
682 spin_unlock_irqrestore(&ctx->reg_slock, flags); in mixer_graph_buffer()
692 while (--tries) { in vp_win_reset()
705 spin_lock_irqsave(&ctx->reg_slock, flags); in mixer_win_reset()
724 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in mixer_win_reset()
733 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) in mixer_win_reset()
740 spin_unlock_irqrestore(&ctx->reg_slock, flags); in mixer_win_reset()
748 spin_lock(&ctx->reg_slock); in mixer_irq_handler()
760 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags) in mixer_irq_handler()
764 drm_crtc_handle_vblank(&ctx->crtc->base); in mixer_irq_handler()
771 spin_unlock(&ctx->reg_slock); in mixer_irq_handler()
778 struct device *dev = &mixer_ctx->pdev->dev; in mixer_resources_init()
782 spin_lock_init(&mixer_ctx->reg_slock); in mixer_resources_init()
784 mixer_ctx->mixer = devm_clk_get(dev, "mixer"); in mixer_resources_init()
785 if (IS_ERR(mixer_ctx->mixer)) { in mixer_resources_init()
786 dev_err(dev, "failed to get clock 'mixer'\n"); in mixer_resources_init()
787 return -ENODEV; in mixer_resources_init()
790 mixer_ctx->hdmi = devm_clk_get(dev, "hdmi"); in mixer_resources_init()
791 if (IS_ERR(mixer_ctx->hdmi)) { in mixer_resources_init()
793 return PTR_ERR(mixer_ctx->hdmi); in mixer_resources_init()
796 mixer_ctx->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); in mixer_resources_init()
797 if (IS_ERR(mixer_ctx->sclk_hdmi)) { in mixer_resources_init()
799 return -ENODEV; in mixer_resources_init()
801 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0); in mixer_resources_init()
804 return -ENXIO; in mixer_resources_init()
807 mixer_ctx->mixer_regs = devm_ioremap(dev, res->start, in mixer_resources_init()
809 if (mixer_ctx->mixer_regs == NULL) { in mixer_resources_init()
811 return -ENXIO; in mixer_resources_init()
814 ret = platform_get_irq(mixer_ctx->pdev, 0); in mixer_resources_init()
817 mixer_ctx->irq = ret; in mixer_resources_init()
819 ret = devm_request_irq(dev, mixer_ctx->irq, mixer_irq_handler, in mixer_resources_init()
831 struct device *dev = &mixer_ctx->pdev->dev; in vp_resources_init()
834 mixer_ctx->vp = devm_clk_get(dev, "vp"); in vp_resources_init()
835 if (IS_ERR(mixer_ctx->vp)) { in vp_resources_init()
837 return -ENODEV; in vp_resources_init()
840 if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) { in vp_resources_init()
841 mixer_ctx->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); in vp_resources_init()
842 if (IS_ERR(mixer_ctx->sclk_mixer)) { in vp_resources_init()
844 return -ENODEV; in vp_resources_init()
846 mixer_ctx->mout_mixer = devm_clk_get(dev, "mout_mixer"); in vp_resources_init()
847 if (IS_ERR(mixer_ctx->mout_mixer)) { in vp_resources_init()
849 return -ENODEV; in vp_resources_init()
852 if (mixer_ctx->sclk_hdmi && mixer_ctx->mout_mixer) in vp_resources_init()
853 clk_set_parent(mixer_ctx->mout_mixer, in vp_resources_init()
854 mixer_ctx->sclk_hdmi); in vp_resources_init()
857 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); in vp_resources_init()
860 return -ENXIO; in vp_resources_init()
863 mixer_ctx->vp_regs = devm_ioremap(dev, res->start, in vp_resources_init()
865 if (mixer_ctx->vp_regs == NULL) { in vp_resources_init()
867 return -ENXIO; in vp_resources_init()
878 mixer_ctx->drm_dev = drm_dev; in mixer_initialize()
883 DRM_DEV_ERROR(mixer_ctx->dev, in mixer_initialize()
888 if (test_bit(MXR_BIT_VP_ENABLED, &mixer_ctx->flags)) { in mixer_initialize()
892 DRM_DEV_ERROR(mixer_ctx->dev, in mixer_initialize()
898 return exynos_drm_register_dma(drm_dev, mixer_ctx->dev, in mixer_initialize()
899 &mixer_ctx->dma_priv); in mixer_initialize()
904 exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev, in mixer_ctx_remove()
905 &mixer_ctx->dma_priv); in mixer_ctx_remove()
910 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_enable_vblank()
912 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); in mixer_enable_vblank()
913 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_enable_vblank()
925 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_disable_vblank()
927 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); in mixer_disable_vblank()
929 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_disable_vblank()
939 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_begin()
941 if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_begin()
945 dev_err(ctx->dev, "timeout waiting for VSYNC\n"); in mixer_atomic_begin()
952 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_update_plane()
954 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index); in mixer_update_plane()
956 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_update_plane()
959 if (plane->index == VP_DEFAULT_WIN) in mixer_update_plane()
968 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_disable_plane()
971 DRM_DEV_DEBUG_KMS(mixer_ctx->dev, "win: %d\n", plane->index); in mixer_disable_plane()
973 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_disable_plane()
976 spin_lock_irqsave(&mixer_ctx->reg_slock, flags); in mixer_disable_plane()
977 mixer_cfg_layer(mixer_ctx, plane->index, 0, false); in mixer_disable_plane()
978 spin_unlock_irqrestore(&mixer_ctx->reg_slock, flags); in mixer_disable_plane()
983 struct mixer_context *mixer_ctx = crtc->ctx; in mixer_atomic_flush()
985 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) in mixer_atomic_flush()
994 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_enable()
997 if (test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_enable()
1000 ret = pm_runtime_resume_and_get(ctx->dev); in mixer_atomic_enable()
1002 dev_err(ctx->dev, "failed to enable MIXER device.\n"); in mixer_atomic_enable()
1012 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) { in mixer_atomic_enable()
1023 set_bit(MXR_BIT_POWERED, &ctx->flags); in mixer_atomic_enable()
1028 struct mixer_context *ctx = crtc->ctx; in mixer_atomic_disable()
1031 if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) in mixer_atomic_disable()
1038 mixer_disable_plane(crtc, &ctx->planes[i]); in mixer_atomic_disable()
1042 pm_runtime_put(ctx->dev); in mixer_atomic_disable()
1044 clear_bit(MXR_BIT_POWERED, &ctx->flags); in mixer_atomic_disable()
1050 struct mixer_context *ctx = crtc->ctx; in mixer_mode_valid()
1051 u32 w = mode->hdisplay, h = mode->vdisplay; in mixer_mode_valid()
1053 DRM_DEV_DEBUG_KMS(ctx->dev, "xres=%d, yres=%d, refresh=%d, intl=%d\n", in mixer_mode_valid()
1055 !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); in mixer_mode_valid()
1057 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_mode_valid()
1077 struct mixer_context *ctx = crtc->ctx; in mixer_mode_fixup()
1078 int width = mode->hdisplay, height = mode->vdisplay, i; in mixer_mode_fixup()
1090 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in mixer_mode_fixup()
1091 __set_bit(MXR_BIT_INTERLACE, &ctx->flags); in mixer_mode_fixup()
1093 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); in mixer_mode_fixup()
1095 if (ctx->mxr_ver == MXR_VER_128_0_0_184) in mixer_mode_fixup()
1100 ctx->scan_value = modes[i].scan_val; in mixer_mode_fixup()
1103 adjusted_mode->hdisplay = modes[i].hdisplay; in mixer_mode_fixup()
1104 adjusted_mode->hsync_start = modes[i].hdisplay; in mixer_mode_fixup()
1105 adjusted_mode->hsync_end = modes[i].htotal; in mixer_mode_fixup()
1106 adjusted_mode->htotal = modes[i].htotal; in mixer_mode_fixup()
1107 adjusted_mode->vdisplay = modes[i].vdisplay; in mixer_mode_fixup()
1108 adjusted_mode->vsync_start = modes[i].vdisplay; in mixer_mode_fixup()
1109 adjusted_mode->vsync_end = modes[i].vtotal; in mixer_mode_fixup()
1110 adjusted_mode->vtotal = modes[i].vtotal; in mixer_mode_fixup()
1155 .compatible = "samsung,exynos4210-mixer",
1158 .compatible = "samsung,exynos4212-mixer",
1161 .compatible = "samsung,exynos5-mixer",
1164 .compatible = "samsung,exynos5250-mixer",
1167 .compatible = "samsung,exynos5420-mixer",
1189 &ctx->flags)) in mixer_bind()
1192 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, in mixer_bind()
1198 exynos_plane = &ctx->planes[DEFAULT_WIN]; in mixer_bind()
1199 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, in mixer_bind()
1201 if (IS_ERR(ctx->crtc)) { in mixer_bind()
1203 ret = PTR_ERR(ctx->crtc); in mixer_bind()
1228 struct device *dev = &pdev->dev; in mixer_probe()
1233 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); in mixer_probe()
1235 DRM_DEV_ERROR(dev, "failed to alloc mixer context.\n"); in mixer_probe()
1236 return -ENOMEM; in mixer_probe()
1241 ctx->pdev = pdev; in mixer_probe()
1242 ctx->dev = dev; in mixer_probe()
1243 ctx->mxr_ver = drv->version; in mixer_probe()
1245 if (drv->is_vp_enabled) in mixer_probe()
1246 __set_bit(MXR_BIT_VP_ENABLED, &ctx->flags); in mixer_probe()
1247 if (drv->has_sclk) in mixer_probe()
1248 __set_bit(MXR_BIT_HAS_SCLK, &ctx->flags); in mixer_probe()
1254 ret = component_add(&pdev->dev, &mixer_component_ops); in mixer_probe()
1263 pm_runtime_disable(&pdev->dev); in mixer_remove()
1265 component_del(&pdev->dev, &mixer_component_ops); in mixer_remove()
1274 clk_disable_unprepare(ctx->hdmi); in exynos_mixer_suspend()
1275 clk_disable_unprepare(ctx->mixer); in exynos_mixer_suspend()
1276 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in exynos_mixer_suspend()
1277 clk_disable_unprepare(ctx->vp); in exynos_mixer_suspend()
1278 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) in exynos_mixer_suspend()
1279 clk_disable_unprepare(ctx->sclk_mixer); in exynos_mixer_suspend()
1290 ret = clk_prepare_enable(ctx->mixer); in exynos_mixer_resume()
1292 DRM_DEV_ERROR(ctx->dev, in exynos_mixer_resume()
1293 "Failed to prepare_enable the mixer clk [%d]\n", in exynos_mixer_resume()
1297 ret = clk_prepare_enable(ctx->hdmi); in exynos_mixer_resume()
1304 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { in exynos_mixer_resume()
1305 ret = clk_prepare_enable(ctx->vp); in exynos_mixer_resume()
1312 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) { in exynos_mixer_resume()
1313 ret = clk_prepare_enable(ctx->sclk_mixer); in exynos_mixer_resume()
1335 .name = "exynos-mixer",