Index: drivers/media/video/samsung/tv20/vmixer_s5pv210.c |
diff --git a/drivers/media/video/samsung/tv20/vmixer_s5pv210.c b/drivers/media/video/samsung/tv20/vmixer_s5pv210.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5e21581e0fcdad605b5ac053b14a89c66b9bb4bd |
--- /dev/null |
+++ b/drivers/media/video/samsung/tv20/vmixer_s5pv210.c |
@@ -0,0 +1,1233 @@ |
+/* linux/drivers/media/video/samsung/tv20/vmixer_s5pv210.c |
+* |
+* Copyright (c) 2010 Samsung Electronics Co., Ltd. |
+* http://www.samsung.com/ |
+* |
+* S5PV210 - Mixer raw ftn file for Samsung TVOut driver |
+* |
+* This program is free software; you can redistribute it and/or modify |
+* it under the terms of the GNU General Public License version 2 as |
+* published by the Free Software Foundation. |
+*/ |
+ |
+#include <linux/module.h> |
+#include <linux/kernel.h> |
+#include <linux/errno.h> |
+#include <linux/string.h> |
+#include <linux/interrupt.h> |
+#include <linux/platform_device.h> |
+#include <linux/clk.h> |
+ |
+#include <plat/clock.h> |
+ |
+#include <linux/io.h> |
+ |
+ |
+#include "tv_out_s5pv210.h" |
+ |
+#include <mach/regs-vmx.h> |
+ |
+#include <linux/irq.h> |
+#include <linux/delay.h> |
+ |
+#ifdef CONFIG_TVOUT_RAW_DBG |
+#define S5P_MXR_DEBUG 1 |
+#endif |
+ |
+#ifdef S5P_MXR_DEBUG |
+#define VMPRINTK(fmt, args...) \ |
+ printk(KERN_INFO "\t\t[VM] %s: " fmt, __func__ , ## args) |
+#else |
+#define VMPRINTK(fmt, args...) |
+#endif |
+ |
+static struct resource *mixer_mem; |
+void __iomem *mixer_base; |
+ |
+/* |
+*set - set functions are only called under running vmixer |
+*/ |
+enum s5p_tv_vmx_err tv_vm_set_layer_show(enum s5p_tv_vmx_layer layer, bool show) |
+{ |
+ u32 mxr_config; |
+ |
+ VMPRINTK("%d,%d\n\r", layer, show); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ mxr_config = (show) ? |
+ (readl(mixer_base + S5P_MXR_CFG) | |
+ S5P_MXR_VIDEO_LAYER_SHOW) : |
+ (readl(mixer_base + S5P_MXR_CFG) & |
+ ~S5P_MXR_VIDEO_LAYER_SHOW); |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ mxr_config = (show) ? |
+ (readl(mixer_base + S5P_MXR_CFG) | |
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) : |
+ (readl(mixer_base + S5P_MXR_CFG) & |
+ ~S5P_MXR_GRAPHIC0_LAYER_SHOW); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ mxr_config = (show) ? |
+ (readl(mixer_base + S5P_MXR_CFG) | |
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) : |
+ (readl(mixer_base + S5P_MXR_CFG) & |
+ ~S5P_MXR_GRAPHIC1_LAYER_SHOW); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ writel(mxr_config, mixer_base + S5P_MXR_CFG); |
+ |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_CFG)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_set_layer_priority(enum s5p_tv_vmx_layer layer, |
+ u32 priority) |
+{ |
+ u32 layer_cfg; |
+ |
+ VMPRINTK("%d,%d\n\r", layer, priority); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ layer_cfg = S5P_MXR_VP_LAYER_PRIORITY_CLEAR(readl( |
+ mixer_base + S5P_MXR_LAYER_CFG)) | |
+ S5P_MXR_VP_LAYER_PRIORITY(priority); |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ layer_cfg = S5P_MXR_GRP0_LAYER_PRIORITY_CLEAR( |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) | |
+ S5P_MXR_GRP0_LAYER_PRIORITY(priority); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ layer_cfg = S5P_MXR_GRP1_LAYER_PRIORITY_CLEAR( |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) | |
+ S5P_MXR_GRP1_LAYER_PRIORITY(priority); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ writel(layer_cfg, mixer_base + S5P_MXR_LAYER_CFG); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_set_win_blend(enum s5p_tv_vmx_layer layer, |
+ bool enable) |
+{ |
+ u32 temp_reg; |
+ VMPRINTK("%d,%d\n\r", layer, enable); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG) |
+ & (~S5P_MXR_VP_BLEND_ENABLE) ; |
+ |
+ if (enable) |
+ temp_reg |= S5P_MXR_VP_BLEND_ENABLE; |
+ else |
+ temp_reg |= S5P_MXR_VP_BLEND_DISABLE; |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG); |
+ |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG) |
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ; |
+ |
+ if (enable) |
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE; |
+ else |
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE; |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG); |
+ |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG) |
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ; |
+ |
+ if (enable) |
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE; |
+ else |
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE; |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG); |
+ |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG)); |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)); |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+ |
+enum s5p_tv_vmx_err tv_vm_set_layer_alpha(enum s5p_tv_vmx_layer layer, |
+ u32 alpha) |
+{ |
+ u32 temp_reg; |
+ VMPRINTK("%d,%d\n\r", layer, alpha); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG) |
+ & (~S5P_MXR_ALPHA) ; |
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha); |
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG); |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG) |
+ & (~S5P_MXR_ALPHA) ; |
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha); |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG) |
+ & (~S5P_MXR_ALPHA) ; |
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha); |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG)); |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)); |
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+ |
+enum s5p_tv_vmx_err tv_vm_set_grp_base_address( |
+ enum s5p_tv_vmx_layer layer, u32 base_addr) |
+{ |
+ VMPRINTK("%d,0x%x\n\r", layer, base_addr); |
+ |
+ if (S5P_MXR_GRP_ADDR_ILLEGAL(base_addr)) { |
+ VMPRINTK(" address is not word align = %d\n\r", base_addr); |
+ return S5P_TV_VMX_ERR_BASE_ADDRESS_MUST_WORD_ALIGN; |
+ } |
+ |
+ switch (layer) { |
+ |
+ case VM_GPR0_LAYER: |
+ writel(S5P_MXR_GPR_BASE(base_addr), |
+ mixer_base + S5P_MXR_GRAPHIC0_BASE); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_BASE)); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ writel(S5P_MXR_GPR_BASE(base_addr), |
+ mixer_base + S5P_MXR_GRAPHIC1_BASE); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_BASE)); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_set_grp_layer_position(enum s5p_tv_vmx_layer layer, |
+ u32 dst_offs_x, u32 dst_offs_y) |
+{ |
+ VMPRINTK("%d,%d,%d)\n\r", layer, dst_offs_x, dst_offs_y); |
+ |
+ switch (layer) { |
+ |
+ case VM_GPR0_LAYER: |
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) | |
+ S5P_MXR_GRP_DESTY(dst_offs_y), |
+ mixer_base + S5P_MXR_GRAPHIC0_DXY); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_DXY)); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) | |
+ S5P_MXR_GRP_DESTY(dst_offs_y), |
+ mixer_base + S5P_MXR_GRAPHIC1_DXY); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_DXY)); |
+ break; |
+ |
+ default: |
+ VMPRINTK("invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_set_grp_layer_size(enum s5p_tv_vmx_layer layer, |
+ u32 span, |
+ u32 width, |
+ u32 height, |
+ u32 src_offs_x, |
+ u32 src_offs_y) |
+{ |
+ VMPRINTK("%d,%d,%d,%d,%d,%d)\n\r", layer, span, width, height, |
+ src_offs_x, src_offs_y); |
+ |
+ switch (layer) { |
+ |
+ case VM_GPR0_LAYER: |
+ writel(S5P_MXR_GRP_SPAN(span), |
+ mixer_base + S5P_MXR_GRAPHIC0_SPAN); |
+ writel(S5P_MXR_GRP_WIDTH(width) | S5P_MXR_GRP_HEIGHT(height), |
+ mixer_base + S5P_MXR_GRAPHIC0_WH); |
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) | |
+ S5P_MXR_GRP_STARTY(src_offs_y), |
+ mixer_base + S5P_MXR_GRAPHIC0_SXY); |
+ VMPRINTK("0x%x,0x%x,0x%x\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN), |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH), |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY)); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ writel(S5P_MXR_GRP_SPAN(span), |
+ mixer_base + S5P_MXR_GRAPHIC1_SPAN); |
+ writel(S5P_MXR_GRP_WIDTH(width) | S5P_MXR_GRP_HEIGHT(height), |
+ mixer_base + S5P_MXR_GRAPHIC1_WH); |
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) | |
+ S5P_MXR_GRP_STARTY(src_offs_y), |
+ mixer_base + S5P_MXR_GRAPHIC1_SXY); |
+ VMPRINTK("0x%x,0x%x,0x%x\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN), |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH), |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY)); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_set_bg_color(enum s5p_tv_vmx_bg_color_num colornum, |
+ u32 color_y, |
+ u32 color_cb, |
+ u32 color_cr) |
+{ |
+ u32 reg_value; |
+ VMPRINTK("%d,%d,%d,%d)\n\r", colornum, color_y, color_cb, color_cr); |
+ |
+ reg_value = S5P_MXR_BG_COLOR_Y(color_y) | |
+ S5P_MXR_BG_COLOR_CB(color_cb) | S5P_MXR_BG_COLOR_CR(color_cr); |
+ |
+ switch (colornum) { |
+ |
+ case VMIXER_BG_COLOR_0: |
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR0); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR0)); |
+ break; |
+ |
+ case VMIXER_BG_COLOR_1: |
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR1); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR1)); |
+ break; |
+ |
+ case VMIXER_BG_COLOR_2: |
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR2); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR2)); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid uiColorNum parameter = %d\n\r", colornum); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+/* |
+* initialization - iniization functions are only called under stopping vmixer |
+*/ |
+enum s5p_tv_vmx_err tv_vm_init_status_reg( |
+ enum s5p_vmx_burst_mode burst, enum s5p_endian_type endian) |
+{ |
+ u32 temp_reg = 0; |
+ |
+ VMPRINTK("++(%d,%d)\n\r", burst, endian); |
+ |
+ temp_reg = S5P_MXR_MIXER_RESERVED | S5P_MXR_CMU_CANNOT_STOP_CLOCK; |
+ |
+ switch (burst) { |
+ |
+ case VM_BURST_8: |
+ temp_reg |= S5P_MXR_BURST8_MODE; |
+ break; |
+ |
+ case VM_BURST_16: |
+ temp_reg |= S5P_MXR_BURST16_MODE; |
+ break; |
+ |
+ default: |
+ VMPRINTK("[ERR] : invalid burst parameter = %d\n\r", burst); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ switch (endian) { |
+ |
+ case TVOUT_BIG_ENDIAN_MODE: |
+ temp_reg |= S5P_MXR_BIG_ENDIAN_SOURCE_FORMAT; |
+ break; |
+ |
+ case TVOUT_LITTLE_ENDIAN_MODE: |
+ temp_reg |= S5P_MXR_LITTLE_ENDIAN_SOURCE_FORMAT; |
+ break; |
+ |
+ default: |
+ VMPRINTK("[ERR] : invalid endian parameter = %d\n\r", endian); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_STATUS); |
+ |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_STATUS)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_init_display_mode( |
+ enum s5p_tv_disp_mode mode, enum s5p_tv_o_mode output_mode) |
+{ |
+ u32 temp_reg = readl(mixer_base + S5P_MXR_CFG); |
+ |
+ VMPRINTK("%d,%d)\n\r", mode, output_mode); |
+ |
+ switch (mode) { |
+ |
+ case TVOUT_NTSC_M: |
+ case TVOUT_NTSC_443: |
+ temp_reg &= ~S5P_MXR_HD; |
+ temp_reg &= ~S5P_MXR_PAL; |
+ temp_reg &= S5P_MXR_INTERLACE_MODE; |
+ break; |
+ |
+ case TVOUT_PAL_BDGHI: |
+ case TVOUT_PAL_M: |
+ case TVOUT_PAL_N: |
+ case TVOUT_PAL_NC: |
+ case TVOUT_PAL_60: |
+ temp_reg &= ~S5P_MXR_HD; |
+ temp_reg |= S5P_MXR_PAL; |
+ temp_reg &= S5P_MXR_INTERLACE_MODE; |
+ break; |
+ |
+ case TVOUT_480P_60_16_9: |
+ case TVOUT_480P_60_4_3: |
+ case TVOUT_480P_59: |
+ temp_reg &= ~S5P_MXR_HD; |
+ temp_reg &= ~S5P_MXR_PAL; |
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE; |
+ break; |
+ |
+ case TVOUT_576P_50_16_9: |
+ case TVOUT_576P_50_4_3: |
+ temp_reg &= ~S5P_MXR_HD; |
+ temp_reg |= S5P_MXR_PAL; |
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE; |
+ break; |
+ |
+ case TVOUT_720P_50: |
+ case TVOUT_720P_59: |
+ case TVOUT_720P_60: |
+ temp_reg |= S5P_MXR_HD; |
+ temp_reg &= ~S5P_MXR_HD_1080I_MODE; |
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE; |
+ break; |
+ |
+ case TVOUT_1080I_50: |
+ case TVOUT_1080I_59: |
+ case TVOUT_1080I_60: |
+ temp_reg |= S5P_MXR_HD; |
+ temp_reg |= S5P_MXR_HD_1080I_MODE; |
+ temp_reg &= S5P_MXR_INTERLACE_MODE; |
+ break; |
+ |
+ case TVOUT_1080P_50: |
+ case TVOUT_1080P_59: |
+ case TVOUT_1080P_60: |
+ case TVOUT_1080P_30: |
+ temp_reg |= S5P_MXR_HD; |
+ temp_reg |= S5P_MXR_HD_1080P_MODE; |
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE; |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ switch (output_mode) { |
+ |
+ case TVOUT_OUTPUT_COMPOSITE: |
+ case TVOUT_OUTPUT_SVIDEO: |
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED: |
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE: |
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE: |
+ temp_reg &= S5P_MXR_DST_SEL_ANALOG; |
+ break; |
+ |
+ case TVOUT_OUTPUT_HDMI_RGB: |
+ case TVOUT_OUTPUT_DVI: |
+ temp_reg |= S5P_MXR_DST_SEL_HDMI; |
+ temp_reg &= ~(0x7<<8); |
+ temp_reg |= RGB709_16_235<<9 | MX_RGB888<<8; |
+ break; |
+ |
+ case TVOUT_OUTPUT_HDMI: |
+ temp_reg |= S5P_MXR_DST_SEL_HDMI; |
+ temp_reg &= ~(0x7<<8); |
+ temp_reg |= RGB601_16_235<<9 | MX_YUV444<<8; |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_CFG); |
+ |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CFG)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+u32 grp_scaling_factor(u32 src, u32 dst, u32 h_v) |
+{ |
+ u32 factor; /* for scaling factor */ |
+ |
+ /* check scale or not */ |
+ if (src == dst) |
+ factor = 0; |
+ |
+ if (dst % src) { |
+ factor = 0; |
+ |
+ VMPRINTK(" can't %s scaling src(%d) into dst(%d)\n" |
+ , h_v ? "horizontal" : "vertical" |
+ , src_w, dst_w); |
+ VMPRINTK(" scaling vector must be 2/4/8x\n"); |
+ } |
+ |
+ factor = dst / src; |
+ |
+ switch (factor) { |
+ case 2: |
+ factor = 1; |
+ break; |
+ |
+ case 4: |
+ factor = 2; |
+ break; |
+ |
+ case 8: |
+ factor = 3; |
+ break; |
+ |
+ default: |
+ VMPRINTK(" scaling vector must be 2/4/8x\n"); |
+ factor = 0; |
+ break; |
+ } |
+ |
+ return factor; |
+} |
+ |
+void tv_vm_set_ctrl(enum s5p_tv_vmx_layer layer, |
+ bool premul, |
+ bool pixel_blending, |
+ bool blank_change, |
+ bool win_blending, |
+ enum s5p_tv_vmx_color_fmt color, |
+ u32 alpha, u32 blank_color) |
+{ |
+ u32 reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG); |
+ |
+ if (blank_change) |
+ reg &= ~S5P_MXR_BLANK_CHANGE_NEW_PIXEL; |
+ else |
+ reg |= S5P_MXR_BLANK_CHANGE_NEW_PIXEL; |
+ |
+ |
+ if (premul) |
+ reg |= S5P_MXR_PRE_MUL_MODE; |
+ else |
+ reg &= ~S5P_MXR_PRE_MUL_MODE; |
+ |
+ if (win_blending) |
+ reg |= S5P_MXR_WIN_BLEND_ENABLE; |
+ else |
+ reg &= ~S5P_MXR_WIN_BLEND_ENABLE; |
+ |
+ reg &= ~S5P_MXR_EG_COLOR_FORMAT(VM_DIRECT_RGB8888); |
+ reg |= S5P_MXR_EG_COLOR_FORMAT(color); |
+ |
+ reg &= ~S5P_MXR_GRP_ALPHA_VALUE(0xff); |
+ reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha); |
+ |
+ writel(reg, mixer_base + S5P_MXR_GRAPHIC0_CFG); |
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color), |
+ mixer_base + S5P_MXR_GRAPHIC0_BLANK); |
+ |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_init_layer(enum s5p_tv_disp_mode mode, |
+ enum s5p_tv_vmx_layer layer, |
+ bool show, |
+ bool win_blending, |
+ u32 alpha, |
+ u32 priority, |
+ enum s5p_tv_vmx_color_fmt color, |
+ bool blank_change, |
+ bool pixel_blending, |
+ bool premul, |
+ u32 blank_color, |
+ u32 base_addr, |
+ u32 span, |
+ u32 width, |
+ u32 height, |
+ u32 src_offs_x, |
+ u32 src_offs_y, |
+ u32 dst_offs_x, |
+ u32 dst_offs_y, |
+ u32 dst_width, |
+ u32 dst_height) |
+{ |
+ u32 temp_reg = 0; |
+ u32 h_factor = 0, v_factor = 0; |
+ |
+ VMPRINTK("%d,%d,%d,%d,%d,%d,%d,%d,%d,0x%x,0x%x,%d,%d, \ |
+ %d,%d,%d,%d,%d)\n\r", |
+ layer, show, win_blending, alpha, priority, color, |
+ blank_change, pixel_blending, premul, blank_color, |
+ base_addr, span, width, height, src_offs_x, src_offs_y, |
+ dst_offs_x, dst_offs_y); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ temp_reg = (win_blending) ? |
+ S5P_MXR_VP_BLEND_ENABLE : S5P_MXR_VP_BLEND_DISABLE; |
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha); |
+ /* temp yuv pxl limiter setting*/ |
+ temp_reg &= ~(1<<17); |
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG); |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ temp_reg = (blank_change) ? S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL : |
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL; |
+ temp_reg |= (premul) ? S5P_MXR_PRE_MUL_MODE : |
+ S5P_MXR_NORMAL_MODE; |
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE : |
+ S5P_MXR_WIN_BLEND_DISABLE; |
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE : |
+ S5P_MXR_PIXEL_BLEND_DISABLE; |
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color); |
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha); |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG); |
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color), |
+ mixer_base + S5P_MXR_GRAPHIC0_BLANK); |
+ |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)); |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK)); |
+ |
+ tv_vm_set_grp_layer_size(layer, span, width, height, |
+ src_offs_x, src_offs_y); |
+ |
+ tv_vm_set_grp_base_address(layer, base_addr); |
+ tv_vm_set_grp_layer_position(layer, dst_offs_x, dst_offs_y); |
+ |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_WH); |
+ h_factor = grp_scaling_factor(width, dst_width, 1); |
+ v_factor = grp_scaling_factor(height, dst_height, 0); |
+ |
+ temp_reg &= ~((0x3<<28)|(0x3<<12)); |
+ |
+ if (v_factor) { |
+ |
+ u32 reg = readl(mixer_base + S5P_MXR_CFG); |
+ |
+ /* In interlaced mode, vertical scaling must be |
+ * replaced by PROGRESSIVE_MODE - pixel duplication |
+ */ |
+ if (mode == TVOUT_1080I_50 || |
+ mode == TVOUT_1080I_59 || |
+ mode == TVOUT_1080I_60) { |
+ /* scaled up by progressive setting */ |
+ reg |= S5P_MXR_PROGRESSVE_MODE; |
+ writel(reg, mixer_base + S5P_MXR_CFG); |
+ } else |
+ /* scaled up by scale factor */ |
+ temp_reg |= v_factor << 12; |
+ } else { |
+ u32 reg = readl(mixer_base + S5P_MXR_CFG); |
+ |
+ /* |
+ * if v_factor is 0, recover the original mode |
+ */ |
+ if (mode == TVOUT_1080I_50 || |
+ mode == TVOUT_1080I_59 || |
+ mode == TVOUT_1080I_60) { |
+ reg &= S5P_MXR_INTERLACE_MODE; |
+ writel(reg, mixer_base + S5P_MXR_CFG); |
+ } |
+ } |
+ temp_reg |= h_factor << 28; |
+ writel(temp_reg , mixer_base + S5P_MXR_GRAPHIC0_WH); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ temp_reg = (blank_change) ? |
+ S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL : |
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL; |
+ temp_reg |= (premul) ? |
+ S5P_MXR_PRE_MUL_MODE : S5P_MXR_NORMAL_MODE; |
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE : |
+ S5P_MXR_WIN_BLEND_DISABLE; |
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE : |
+ S5P_MXR_PIXEL_BLEND_DISABLE; |
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color); |
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha); |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG); |
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color), |
+ mixer_base + S5P_MXR_GRAPHIC1_BLANK); |
+ |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)); |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK)); |
+ |
+ tv_vm_set_grp_layer_size(layer, span, width, height, |
+ src_offs_x, src_offs_y); |
+ |
+ tv_vm_set_grp_base_address(layer, base_addr); |
+ tv_vm_set_grp_layer_position(layer, dst_offs_x, dst_offs_y); |
+ |
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_WH); |
+ h_factor = grp_scaling_factor(width, dst_width, 1); |
+ v_factor = grp_scaling_factor(height, dst_height, 0); |
+ |
+ temp_reg &= ~((0x3<<28)|(0x3<<12)); |
+ |
+ if (v_factor) { |
+ |
+ u32 reg = readl(mixer_base + S5P_MXR_CFG); |
+ |
+ /* In interlaced mode, vertical scaling must be |
+ * replaced by PROGRESSIVE_MODE - pixel duplication |
+ */ |
+ if (mode == TVOUT_1080I_50 || |
+ mode == TVOUT_1080I_59 || |
+ mode == TVOUT_1080I_60) { |
+ /* scaled up by progressive setting */ |
+ reg |= S5P_MXR_PROGRESSVE_MODE; |
+ writel(reg, mixer_base + S5P_MXR_CFG); |
+ } else |
+ /* scaled up by scale factor */ |
+ temp_reg |= v_factor << 12; |
+ } else { |
+ u32 reg = readl(mixer_base + S5P_MXR_CFG); |
+ |
+ /* |
+ * if v_factor is 0, recover the original mode |
+ */ |
+ if (mode == TVOUT_1080I_50 || |
+ mode == TVOUT_1080I_59 || |
+ mode == TVOUT_1080I_60) { |
+ reg &= S5P_MXR_INTERLACE_MODE; |
+ writel(reg, mixer_base + S5P_MXR_CFG); |
+ } |
+ } |
+ |
+ temp_reg |= h_factor << 28; |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_WH); |
+ break; |
+ |
+ default: |
+ VMPRINTK("invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ tv_vm_set_layer_priority(layer, priority); |
+ |
+ tv_vm_set_layer_show(layer, show); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+void tv_vm_init_bg_dither_enable(bool cr_dither_enable, |
+ bool cb_dither_enable, |
+ bool y_dither_enable) |
+{ |
+ u32 temp_reg = 0; |
+ |
+ VMPRINTK("%d,%d,%d\n\r", |
+ cr_dither_enable, cb_dither_enable, y_dither_enable); |
+ |
+ temp_reg = (cr_dither_enable) ? |
+ (temp_reg | S5P_MXR_BG_CR_DIHER_EN) : |
+ (temp_reg & ~S5P_MXR_BG_CR_DIHER_EN); |
+ temp_reg = (cb_dither_enable) ? |
+ (temp_reg | S5P_MXR_BG_CB_DIHER_EN) : |
+ (temp_reg & ~S5P_MXR_BG_CB_DIHER_EN); |
+ temp_reg = (y_dither_enable) ? |
+ (temp_reg | S5P_MXR_BG_Y_DIHER_EN) : |
+ (temp_reg & ~S5P_MXR_BG_Y_DIHER_EN); |
+ |
+ writel(temp_reg, mixer_base + S5P_MXR_BG_CFG); |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_BG_CFG)); |
+ |
+} |
+ |
+ |
+enum s5p_tv_vmx_err tv_vm_init_bg_color(enum s5p_tv_vmx_bg_color_num color_num, |
+ u32 color_y, |
+ u32 color_cb, |
+ u32 color_cr) |
+{ |
+ return tv_vm_set_bg_color(color_num, color_y, color_cb, color_cr); |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_init_csc_coef(enum s5p_yuv_fmt_component component, |
+ enum s5p_tv_coef_y_mode mode, |
+ u32 coeff0, |
+ u32 coeff1, |
+ u32 coeff2) |
+{ |
+ u32 mxr_cm; |
+ |
+ VMPRINTK("%d,%d,%d,%d,%d\n\r", component, mode, coeff0, coeff1, coeff2); |
+ |
+ switch (component) { |
+ |
+ case TVOUT_YUV_Y: |
+ mxr_cm = (mode == VMIXER_COEF_Y_WIDE) ? |
+ S5P_MXR_BG_COLOR_WIDE : S5P_MXR_BG_COLOR_NARROW; |
+ mxr_cm |= S5P_MXR_BG_COEFF_0(coeff0) | |
+ S5P_MXR_BG_COEFF_1(coeff1) | |
+ S5P_MXR_BG_COEFF_2(coeff2); |
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_Y); |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y)); |
+ break; |
+ |
+ case TVOUT_YUV_CB: |
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) | |
+ S5P_MXR_BG_COEFF_1(coeff1) | |
+ S5P_MXR_BG_COEFF_2(coeff2); |
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_CB); |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB)); |
+ break; |
+ |
+ case TVOUT_YUV_CR: |
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) | |
+ S5P_MXR_BG_COEFF_1(coeff1) | |
+ S5P_MXR_BG_COEFF_2(coeff2); |
+ writel(mxr_cm, S5P_MXR_CM_COEFF_CR); |
+ VMPRINTK("--(0x%x)\n\r", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR)); |
+ break; |
+ |
+ default: |
+ VMPRINTK("invalid component parameter = %d\n\r", component); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+void tv_vm_init_csc_coef_default(enum s5p_tv_vmx_csc_type csc_type) |
+{ |
+ VMPRINTK("%d\n\r", csc_type); |
+ |
+ switch (csc_type) { |
+ |
+ case VMIXER_CSC_RGB_TO_YUV601_LR: |
+ writel((0 << 30) | (153 << 20) | (300 << 10) | (58 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_Y); |
+ writel((936 << 20) | (851 << 10) | (262 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CB); |
+ writel((262 << 20) | (805 << 10) | (982 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CR); |
+ break; |
+ |
+ case VMIXER_CSC_RGB_TO_YUV601_FR: |
+ writel((1 << 30) | (132 << 20) | (258 << 10) | (50 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_Y); |
+ writel((948 << 20) | (875 << 10) | (225 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CB); |
+ writel((225 << 20) | (836 << 10) | (988 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CR); |
+ break; |
+ |
+ case VMIXER_CSC_RGB_TO_YUV709_LR: |
+ writel((0 << 30) | (109 << 20) | (366 << 10) | (36 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_Y); |
+ writel((964 << 20) | (822 << 10) | (216 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CB); |
+ writel((262 << 20) | (787 << 10) | (1000 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CR); |
+ break; |
+ |
+ case VMIXER_CSC_RGB_TO_YUV709_FR: |
+ writel((1 << 30) | (94 << 20) | (314 << 10) | (32 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_Y); |
+ writel((972 << 20) | (851 << 10) | (225 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CB); |
+ writel((225 << 20) | (820 << 10) | (1004 << 0), |
+ mixer_base + S5P_MXR_CM_COEFF_CR); |
+ break; |
+ |
+ default: |
+ VMPRINTK(" invalid csc_type parameter = %d\n\r", csc_type); |
+ break; |
+ } |
+ |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_Y)); |
+ |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CB)); |
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CR)); |
+} |
+ |
+enum s5p_tv_vmx_err tv_vm_get_layer_info(enum s5p_tv_vmx_layer layer, |
+ bool *show, |
+ u32 *priority) |
+{ |
+ VMPRINTK("%d\n\r", layer); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) & |
+ S5P_MXR_VIDEO_LAYER_SHOW) ? 1 : 0; |
+ *priority = S5P_MXR_VP_LAYER_PRIORITY_INFO( |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)); |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) & |
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) ? 1 : 0; |
+ *priority = S5P_MXR_GRP0_LAYER_PRIORITY_INFO( |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)); |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) & |
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) ? 1 : 0; |
+ *priority = S5P_MXR_GRP1_LAYER_PRIORITY_INFO( |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)); |
+ break; |
+ |
+ default: |
+ VMPRINTK("invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ VMPRINTK("%d,%d\n\r", *show, *priority); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+/* |
+* start - start functions are only called under stopping vmixer |
+*/ |
+ |
+void tv_vm_start(void) |
+{ |
+ VMPRINTK("()\n\r"); |
+ writel((readl(mixer_base + S5P_MXR_STATUS) | S5P_MXR_MIXER_START), |
+ mixer_base + S5P_MXR_STATUS); |
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_STATUS)); |
+ |
+ |
+ VMPRINTK("S5P_MXR_STATUS \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_STATUS)); |
+ VMPRINTK("S5P_MXR_INT_EN \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_INT_EN)); |
+ VMPRINTK("S5P_MXR_BG_CFG \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_BG_CFG)); |
+ VMPRINTK("S5P_MXR_BG_COLOR0 \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_BG_COLOR0)); |
+ VMPRINTK("S5P_MXR_BG_COLOR1 \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_BG_COLOR1)); |
+ VMPRINTK("S5P_MXR_BG_COLOR2 \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_BG_COLOR2)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB)); |
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_CFG \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_BASE \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BASE)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_SPAN \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_WH \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_SXY \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_DXY \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_DXY)); |
+ VMPRINTK("S5P_MXR_GRAPHIC0_BLANK \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_BASE \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BASE)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_SPAN \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_WH \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_SXY \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_DXY \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_DXY)); |
+ VMPRINTK("S5P_MXR_GRAPHIC1_BLANK \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK)); |
+ VMPRINTK("S5P_MXR_CFG \t\t 0x%08x\n ", readl(mixer_base + S5P_MXR_CFG)); |
+ VMPRINTK("S5P_MXR_LAYER_CFG \t\t 0x%08x\n ", |
+ readl(mixer_base + S5P_MXR_LAYER_CFG)); |
+ |
+} |
+ |
+/* |
+* stop - stop functions are only called under running vmixer |
+*/ |
+void tv_vm_stop(void) |
+{ |
+ u32 reg = readl(mixer_base + S5P_MXR_STATUS); |
+ |
+ reg &= ~S5P_MXR_MIXER_START; |
+ |
+ writel(reg, mixer_base + S5P_MXR_STATUS); |
+ |
+ do { |
+ reg = readl(mixer_base + S5P_MXR_STATUS); |
+ } while (reg & S5P_MXR_MIXER_START); |
+} |
+ |
+/* |
+* interrupt - for debug |
+*/ |
+enum s5p_tv_vmx_err tv_vm_set_underflow_interrupt_enable( |
+ enum s5p_tv_vmx_layer layer, bool en) |
+{ |
+ u32 enablemaks; |
+ |
+ VMPRINTK("%d,%d\n\r", layer, en); |
+ |
+ switch (layer) { |
+ |
+ case VM_VIDEO_LAYER: |
+ enablemaks = S5P_MXR_VP_INT_ENABLE; |
+ break; |
+ |
+ case VM_GPR0_LAYER: |
+ enablemaks = S5P_MXR_GRP0_INT_ENABLE; |
+ break; |
+ |
+ case VM_GPR1_LAYER: |
+ enablemaks = S5P_MXR_GRP1_INT_ENABLE; |
+ break; |
+ |
+ default: |
+ VMPRINTK("invalid layer parameter = %d\n\r", layer); |
+ return S5P_TV_VMX_ERR_INVALID_PARAM; |
+ } |
+ |
+ if (en) { |
+ writel((readl(mixer_base + S5P_MXR_INT_EN) | enablemaks), |
+ mixer_base + S5P_MXR_INT_EN); |
+ } else { |
+ writel((readl(mixer_base + S5P_MXR_INT_EN) & ~enablemaks), |
+ mixer_base + S5P_MXR_INT_EN); |
+ } |
+ |
+ VMPRINTK("0x%x)\n\r", readl(mixer_base + S5P_MXR_INT_EN)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+ |
+enum s5p_tv_vmx_err tv_vm_set_vsync_interrupt(bool en) |
+{ |
+ if (en) { |
+ writel(S5P_MXR_VSYNC_INT_CLEARED, mixer_base + |
+ S5P_MXR_INT_STATUS); |
+ writel((readl(mixer_base + S5P_MXR_INT_EN) | |
+ S5P_MXR_VSYNC_INT_ENABLE), |
+ mixer_base + S5P_MXR_INT_EN); |
+ } else { |
+ writel((readl(mixer_base + S5P_MXR_INT_EN) & |
+ ~S5P_MXR_VSYNC_INT_ENABLE), |
+ mixer_base + S5P_MXR_INT_EN); |
+ } |
+ |
+ VMPRINTK("0x%x)\n\r", readl(mixer_base + S5P_MXR_INT_EN)); |
+ |
+ return VMIXER_NO_ERROR; |
+} |
+ |
+void tv_vm_clear_pend_all(void) |
+{ |
+ writel(S5P_MXR_INT_FIRED | S5P_MXR_VP_INT_FIRED | |
+ S5P_MXR_GRP0_INT_FIRED | S5P_MXR_GRP1_INT_FIRED, |
+ mixer_base + S5P_MXR_INT_EN); |
+} |
+ |
+irqreturn_t tv_mixer_irq(int irq, void *dev_id) |
+{ |
+ bool v_i_f; |
+ bool g0_i_f; |
+ bool g1_i_f; |
+ bool mxr_i_f; |
+ u32 temp_reg = 0; |
+ |
+ v_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS) |
+ & S5P_MXR_VP_INT_FIRED) ? true : false; |
+ g0_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS) |
+ & S5P_MXR_GRP0_INT_FIRED) ? true : false; |
+ g1_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS) |
+ & S5P_MXR_GRP1_INT_FIRED) ? true : false; |
+ mxr_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS) |
+ & S5P_MXR_INT_FIRED) ? true : false; |
+ |
+ if (mxr_i_f) { |
+ temp_reg |= S5P_MXR_INT_FIRED; |
+ |
+ if (v_i_f) { |
+ temp_reg |= S5P_MXR_VP_INT_FIRED; |
+ printk(KERN_ERR "VP fifo under run!!\n\r"); |
+ } |
+ |
+ if (g0_i_f) { |
+ temp_reg |= S5P_MXR_GRP0_INT_FIRED; |
+ printk(KERN_ERR "GRP0 fifo under run!!\n\r"); |
+ } |
+ |
+ if (g1_i_f) { |
+ temp_reg |= S5P_MXR_GRP1_INT_FIRED; |
+ printk(KERN_ERR "GRP1 fifo under run!!\n\r"); |
+ } |
+ |
+ if (!v_i_f && !g0_i_f && !g1_i_f) { |
+ writel(S5P_MXR_VSYNC_INT_CLEARED, |
+ mixer_base + S5P_MXR_INT_STATUS); |
+ wake_up(&s5ptv_wq); |
+ } else |
+ writel(temp_reg, mixer_base + S5P_MXR_INT_STATUS); |
+ |
+ } |
+ return IRQ_HANDLED; |
+} |
+ |
+int __init tv_mixer_probe(struct platform_device *pdev, u32 res_num) |
+{ |
+ struct resource *res; |
+ size_t size; |
+ |
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num); |
+ |
+ if (res == NULL) { |
+ dev_err(&pdev->dev, |
+ "failed to get memory region resource\n"); |
+ goto error; |
+ |
+ } |
+ |
+ size = (res->end - res->start) + 1; |
+ |
+ mixer_mem = request_mem_region(res->start, size, pdev->name); |
+ |
+ if (mixer_mem == NULL) { |
+ dev_err(&pdev->dev, |
+ "failed to get memory region\n"); |
+ goto error; |
+ |
+ } |
+ |
+ mixer_base = ioremap(res->start, size); |
+ |
+ if (mixer_base == NULL) { |
+ dev_err(&pdev->dev, |
+ "failed to ioremap address region\n"); |
+ goto error; |
+ |
+ |
+ } |
+ |
+ /* Initializing wait queue for mixer vsync interrupt */ |
+ init_waitqueue_head(&s5ptv_wq); |
+ return 0; |
+error: |
+ return -ENOENT; |
+ |
+} |
+ |
+int __init tv_mixer_release(struct platform_device *pdev) |
+{ |
+ iounmap(mixer_base); |
+ |
+ /* remove memory region */ |
+ if (mixer_mem != NULL) { |
+ if (release_resource(mixer_mem)) |
+ dev_err(&pdev->dev, |
+ "Can't remove tvout drv !!\n"); |
+ |
+ kfree(mixer_mem); |
+ |
+ mixer_mem = NULL; |
+ } |
+ |
+ return 0; |
+} |