22 #include <linux/kernel.h>
24 #include <linux/wait.h>
25 #include <linux/i2c.h>
26 #include <linux/module.h>
35 #include <drm/exynos_drm.h>
40 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
100 static const u8 filter_y_horiz_tap8[] = {
101 0, -1, -1, -1, -1, -1, -1, -1,
102 -1, -1, -1, -1, -1, 0, 0, 0,
103 0, 2, 4, 5, 6, 6, 6, 6,
104 6, 5, 5, 4, 3, 2, 1, 1,
105 0, -6, -12, -16, -18, -20, -21, -20,
106 -20, -18, -16, -13, -10, -8, -5, -2,
107 127, 126, 125, 121, 114, 107, 99, 89,
108 79, 68, 57, 46, 35, 25, 16, 8,
111 static const u8 filter_y_vert_tap4[] = {
112 0, -3, -6, -8, -8, -8, -8, -7,
113 -6, -5, -4, -3, -2, -1, -1, 0,
114 127, 126, 124, 118, 111, 102, 92, 81,
115 70, 59, 48, 37, 27, 19, 11, 5,
116 0, 5, 11, 19, 27, 37, 48, 59,
117 70, 81, 92, 102, 111, 118, 124, 126,
118 0, 0, -1, -1, -2, -3, -4, -5,
119 -6, -7, -8, -8, -8, -8, -6, -3,
122 static const u8 filter_cr_horiz_tap4[] = {
123 0, -3, -6, -8, -8, -8, -8, -7,
124 -6, -5, -4, -3, -2, -1, -1, 0,
125 127, 126, 124, 118, 111, 102, 92, 81,
126 70, 59, 48, 37, 27, 19, 11, 5,
143 u32 old = vp_reg_read(res, reg_id);
145 val = (val &
mask) | (old & ~mask);
163 u32 old = mixer_reg_read(res, reg_id);
165 val = (val &
mask) | (old & ~mask);
171 #define DUMPREG(reg_id) \
173 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
174 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
203 #define DUMPREG(reg_id) \
205 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
206 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
237 int reg_id,
const u8 *
data,
unsigned int size)
241 for (;
size; size -= 4, reg_id += 4, data += 4) {
242 u32 val = (data[0] << 24) | (data[1] << 16) |
243 (data[2] << 8) | data[3];
244 vp_reg_write(res, reg_id, val);
251 filter_y_horiz_tap8,
sizeof(filter_y_horiz_tap8));
253 filter_y_vert_tap4,
sizeof(filter_y_vert_tap4));
255 filter_cr_horiz_tap4,
sizeof(filter_cr_horiz_tap4));
283 else if (height == 576)
285 else if (height == 720)
287 else if (height == 1080)
295 static void mixer_cfg_rgb_fmt(
struct mixer_context *ctx,
unsigned int height)
302 }
else if (height == 576) {
304 }
else if (height == 720) {
307 (1 << 30) | (94 << 20) | (314 << 10) |
310 (972 << 20) | (851 << 10) | (225 << 0));
312 (225 << 20) | (820 << 10) | (1004 << 0));
313 }
else if (height == 1080) {
316 (1 << 30) | (94 << 20) | (314 << 10) |
319 (972 << 20) | (851 << 10) | (225 << 0));
321 (225 << 20) | (820 << 10) | (1004 << 0));
325 (1 << 30) | (94 << 20) | (314 << 10) |
328 (972 << 20) | (851 << 10) | (225 << 0));
330 (225 << 20) | (820 << 10) | (1004 << 0));
336 static void mixer_cfg_layer(
struct mixer_context *ctx,
int win,
bool enable)
339 u32 val = enable ? ~0 : 0;
351 mixer_reg_writemask(res,
MXR_CFG, val,
364 mixer_regs_dump(ctx);
367 static void vp_video_buffer(
struct mixer_context *ctx,
int win)
372 unsigned int x_ratio, y_ratio;
373 unsigned int buf_num;
375 bool tiled_mode =
false;
376 bool crcb_mode =
false;
394 DRM_ERROR(
"pixel format for vp is wrong [%d].\n",
415 luma_addr[1] = luma_addr[0] + 0x40;
416 chroma_addr[1] = chroma_addr[0] + 0x40;
418 luma_addr[1] = luma_addr[0] + win_data->
fb_width;
419 chroma_addr[1] = chroma_addr[0] + win_data->
fb_width;
428 mixer_vsync_set_update(ctx,
false);
475 mixer_cfg_layer(ctx, win,
true);
478 mixer_vsync_set_update(ctx,
true);
479 spin_unlock_irqrestore(&res->
reg_slock, flags);
489 val = mixer_reg_read(res,
MXR_CFG);
496 static void mixer_graph_buffer(
struct mixer_context *ctx,
int win)
501 unsigned int x_ratio, y_ratio;
502 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
514 switch (win_data->
bpp) {
529 dst_x_offset = win_data->
crtc_x;
530 dst_y_offset = win_data->
crtc_y;
534 + (win_data->
fb_x * win_data->
bpp >> 3)
545 mixer_vsync_set_update(ctx,
false);
575 mixer_cfg_layer(ctx, win,
true);
579 mixer_layer_update(ctx);
583 mixer_vsync_set_update(ctx,
true);
584 spin_unlock_irqrestore(&res->
reg_slock, flags);
593 for (tries = 100; tries; --tries) {
599 WARN(tries == 0,
"failed to reset Video Processor\n");
609 mixer_vsync_set_update(ctx,
false);
655 vp_default_filter(res);
664 mixer_vsync_set_update(ctx,
true);
665 spin_unlock_irqrestore(&res->
reg_slock, flags);
672 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
682 pm_runtime_get_sync(ctx->
dev);
691 mixer_win_reset(ctx);
698 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
713 pm_runtime_put_sync(ctx->
dev);
722 static int mixer_enable_vblank(
void *ctx,
int pipe)
727 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
738 static void mixer_disable_vblank(
void *ctx)
743 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
749 static void mixer_dpms(
void *ctx,
int mode)
753 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
757 mixer_poweron(mixer_ctx);
762 mixer_poweroff(mixer_ctx);
765 DRM_DEBUG_KMS(
"unknown dpms mode: %d\n", mode);
770 static void mixer_wait_for_vblank(
void *ctx)
779 DRM_DEBUG_KMS(
"vblank wait timed out.\n");
782 static void mixer_win_mode_set(
void *ctx,
789 DRM_DEBUG_KMS(
"[%d] %s\n", __LINE__, __func__);
792 DRM_ERROR(
"overlay is NULL\n");
796 DRM_DEBUG_KMS(
"set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
807 DRM_ERROR(
"mixer window[%d] is wrong\n", win);
818 win_data->
bpp = overlay->
bpp;
838 static void mixer_win_commit(
void *ctx,
int win)
842 DRM_DEBUG_KMS(
"[%d] %s, win: %d\n", __LINE__, __func__, win);
845 vp_video_buffer(mixer_ctx, win);
847 mixer_graph_buffer(mixer_ctx, win);
850 static void mixer_win_disable(
void *ctx,
int win)
856 DRM_DEBUG_KMS(
"[%d] %s, win: %d\n", __LINE__, __func__, win);
859 mixer_vsync_set_update(mixer_ctx,
false);
861 mixer_cfg_layer(mixer_ctx, win,
false);
863 mixer_vsync_set_update(mixer_ctx,
true);
864 spin_unlock_irqrestore(&res->
reg_slock, flags);
869 .enable_vblank = mixer_enable_vblank,
870 .disable_vblank = mixer_disable_vblank,
874 .wait_for_vblank = mixer_wait_for_vblank,
875 .win_mode_set = mixer_win_mode_set,
876 .win_commit = mixer_win_commit,
877 .win_disable = mixer_win_disable,
881 static void mixer_finish_pageflip(
struct drm_device *drm_dev,
int crtc)
884 struct drm_pending_vblank_event *
e, *
t;
887 bool is_checked =
false;
899 e->event.sequence = 0;
900 e->event.tv_sec = now.tv_sec;
901 e->event.tv_usec = now.tv_usec;
903 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
912 if (
atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
915 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
946 mixer_finish_pageflip(drm_hdmi_ctx->
drm_dev, ctx->
pipe);
953 val &= ~MXR_INT_EN_VSYNC;
975 if (IS_ERR_OR_NULL(mixer_res->
mixer)) {
976 dev_err(dev,
"failed to get clock 'mixer'\n");
982 if (IS_ERR_OR_NULL(mixer_res->
sclk_hdmi)) {
983 dev_err(dev,
"failed to get clock 'sclk_hdmi'\n");
989 dev_err(dev,
"get memory resource failed.\n");
997 dev_err(dev,
"register mapping failed.\n");
1004 dev_err(dev,
"get interrupt resource failed.\n");
1009 ret = devm_request_irq(&pdev->
dev, res->
start, mixer_irq_handler,
1010 0,
"drm_mixer", ctx);
1012 dev_err(dev,
"request interrupt failed.\n");
1020 if (!IS_ERR_OR_NULL(mixer_res->
sclk_hdmi))
1022 if (!IS_ERR_OR_NULL(mixer_res->
mixer))
1037 if (IS_ERR_OR_NULL(mixer_res->
vp)) {
1038 dev_err(dev,
"failed to get clock 'vp'\n");
1044 dev_err(dev,
"failed to get clock 'sclk_mixer'\n");
1049 if (IS_ERR_OR_NULL(mixer_res->
sclk_dac)) {
1050 dev_err(dev,
"failed to get clock 'sclk_dac'\n");
1060 dev_err(dev,
"get memory resource failed.\n");
1066 resource_size(res));
1068 dev_err(dev,
"register mapping failed.\n");
1076 if (!IS_ERR_OR_NULL(mixer_res->
sclk_dac))
1080 if (!IS_ERR_OR_NULL(mixer_res->
vp))
1097 .name =
"s5p-mixer",
1098 .driver_data = (
unsigned long)&exynos4_mxr_drv_data,
1100 .name =
"exynos5-mixer",
1101 .driver_data = (
unsigned long)&exynos5_mxr_drv_data,
1109 .compatible =
"samsung,exynos5-mixer",
1110 .data = &exynos5_mxr_drv_data,
1128 if (!drm_hdmi_ctx) {
1129 DRM_ERROR(
"failed to allocate common hdmi context.\n");
1135 DRM_ERROR(
"failed to alloc mixer context.\n");
1152 drm_hdmi_ctx->
ctx = (
void *)ctx;
1156 platform_set_drvdata(pdev, drm_hdmi_ctx);
1159 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1161 DRM_ERROR(
"mixer_resources_init failed\n");
1167 ret = vp_resources_init(drm_hdmi_ctx, pdev);
1169 DRM_ERROR(
"vp_resources_init failed\n");
1194 pm_runtime_disable(&pdev->
dev);
1199 #ifdef CONFIG_PM_SLEEP
1200 static int mixer_suspend(
struct device *dev)
1205 mixer_poweroff(ctx);
1215 .name =
"exynos-mixer",
1217 .pm = &mixer_pm_ops,
1218 .of_match_table = mixer_match_types,
1220 .probe = mixer_probe,
1222 .id_table = mixer_driver_types,