Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2573)

Unified Diff: drivers/media/video/samsung/tv20/vmixer_s5pv210.c

Issue 2036011: V4L/DVB : Add S5PV210 TV out driver support (Closed) Base URL: swsolcc@12.23.106.100:kernel-samsung.git
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
+}
« no previous file with comments | « drivers/media/video/samsung/tv20/tv_power_s5pv210.c ('k') | drivers/media/video/samsung/tv20/vp_coeff_s5pv210.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698