| 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;
|
| +}
|
|
|