//
// Copyright (c) Samsung Electronics. Co. LTD.  All rights reserved.
//
//
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:    video_mixer.c

Abstract:       Implementation of video mixer Library
                This module implements Low Level HW control

Functions:


Notes:


--*/

#include <windows.h>
#include <bsp_cfg.h>    // for reference HCLK, ECLK
#include <register_map.h>
#include "vmixer_reg.h"
#include "tvout_message.h"
#include "video_mixer.h"
#include "video_mixer_internal.h"


// initialization
//  - iniization functions are only called under stopping vmixer

VMIXER_ERROR
VMixer_initialize_register_address
(void *pVMReg)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_register_address(0x%08x)\n\r"), pVMReg));

	if (pVMReg == NULL)
	{
		DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_register_address() : NULL pointer parameter\n\r")));
		return VMIXER_ERROR_INVALID_PARAM;
	}
	else
	{
		g_pVMixerConfig = (PVMIXER_REG)pVMReg;
		DBGMSG(TV_INFO,(_T("[VMIXER]--VMixer_initialize_register_address(0x%08x)\n\r"), g_pVMixerConfig));
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_register_address()\n\r")));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_initialize_status_reg
(VMIXER_BURST_MODE burst,
TVOUT_ENDIAN_FORMAT_TYPE endian)
{
	unsigned int uiTempReg = 0;

	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_status_reg(%d,%d)\n\r"),burst,endian));

	uiTempReg = VM_MIXER_RESERVED | VM_CMU_CANNOT_STOP_CLOCK;

	switch(burst)
	{
		case VM_BURST_8:
			uiTempReg |= VM_BURST8_MODE;
			break;
		case VM_BURST_16:
			uiTempReg |= VM_BURST16_MODE;
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_status_reg() : invalid burst parameter = %d\n\r"),burst));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	switch(endian)
	{
		case TVOUT_BIG_ENDIAN_MODE:
			uiTempReg |= VM_BIG_ENDIAN_SOURCE_FORMAT;
			break;
		case TVOUT_LITTLE_ENDIAN_MODE:
			uiTempReg |= VM_LITTLE_ENDIAN_SOURCE_FORMAT;
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_status_reg() : invalid endian parameter = %d\n\r"),endian));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	g_pVMixerConfig->MIXER_STATUS = uiTempReg;

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_status_reg(0x%x)\n\r"),g_pVMixerConfig->MIXER_STATUS));

return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_initialize_display_mode
(TVOUT_DISPLAY_MODE mode,
TVOUT_OUTPUT_MODE outputMode)
{
	unsigned int uiTempReg = 0;

	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_display_mode(%d,%d)\n\r"),mode,outputMode));

	switch(outputMode)
	{
		case TVOUT_OUTPUT_COMPOSITE:
			uiTempReg = (VM_INTERLACE_MODE | VM_YUV444);
			break;
		case TVOUT_OUTPUT_HDMI:
		case TVOUT_OUTPUT_DVI:
			uiTempReg = (VM_PROGRESSIVE_MODE | VM_RGB888);
			break;
		case TVOUT_OUTPUT_HDMI_YCBCR:
			uiTempReg = (VM_PROGRESSIVE_MODE | VM_YUV444);
			break;

		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_display_mode() : invalid mode parameter = %d\n\r"),mode));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	switch(mode)
	{
		case TVOUT_NTSC_M:
		case TVOUT_NTSC_J:
		case TVOUT_NTSC_443:
			uiTempReg |= (VM_SD | VM_NTSC | VM_REG_DST_SEL_SD);  // | VM_INTERLACE_MODE;
			break;
		case TVOUT_PAL_BDGHI:
		case TVOUT_PAL_M:
		case TVOUT_PAL_N:
		case TVOUT_PAL_NC:
		case TVOUT_PAL_60:
			uiTempReg |= (VM_SD | VM_PAL | VM_REG_DST_SEL_SD);  // | VM_INTERLACE_MODE;
			break;
		case TVOUT_480P_60_16_9:
		case TVOUT_480P_60_4_3:
			uiTempReg |= (VM_SD | VM_NTSC | VM_REG_DST_SEL_HD | VM_RGB601_16_235);  // | VM_PROGRESSIVE_MODE;
			break;
		case TVOUT_576P_50_16_9:
		case TVOUT_576P_50_4_3:
			uiTempReg |= (VM_SD | VM_PAL | VM_REG_DST_SEL_HD | VM_RGB601_16_235);  // | VM_PROGRESSIVE_MODE;
			break;
		case TVOUT_720P_60:
			uiTempReg |= (VM_HD | VM_HD_720P_MODE | VM_REG_DST_SEL_HD | VM_RGB709_16_235);  // | VM_PROGRESSIVE_MODE;
			break;
		case TVOUT_1080I_60:
			uiTempReg |= (VM_HD | VM_HD_1080I_MODE | VM_REG_DST_SEL_HD | VM_RGB709_16_235);  // | VM_INTERLACE_MODE;
			uiTempReg &= ~VM_PROGRESSIVE_MODE;
			break;
		case TVOUT_1080P_30:
			uiTempReg |= (VM_HD | VM_HD_1080I_MODE | VM_REG_DST_SEL_HD | VM_RGB709_16_235);  // | VM_PROGRESSIVE_MODE;
			break;
		case TVOUT_1080P_60:
			uiTempReg |= (VM_HD | VM_HD_1080I_MODE | VM_REG_DST_SEL_HD | VM_RGB709_16_235);  // | VM_PROGRESSIVE_MODE;
			break;

		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_display_mode() : invalid mode parameter = %d\n\r"),mode));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}


	g_pVMixerConfig->MIXER_CFG = uiTempReg;

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_display_mode(0x%x)\n\r"),g_pVMixerConfig->MIXER_CFG));

	return VMIXER_NO_ERROR;
}


VMIXER_ERROR
VMixer_initialize_Limit_Para_Cfg
(unsigned int uiYUpper,
unsigned int uiYLower,
unsigned int uiCUpper,
unsigned int uiCLower)
{
	unsigned int uiTempReg = 0;

	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_Linit_Para_Cfg(%d,%d,%d,%d)\n\r"),
																			uiYUpper,
																			uiYLower,
																			uiCUpper,
																			uiCUpper));

	g_pVMixerConfig->MIXER_VIDEO_LIMITER_PA_RA_CFG = (VM_REG_PARA_Y_UPPER(uiYUpper) |
	VM_REG_PARA_Y_LOWER(uiYLower) |
	VM_REG_PARA_C_UPPER(uiCUpper) |
	VM_REG_PARA_C_LOWER(uiCUpper));

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_Linit_Para_Cfg(0x%x)\n\r"),g_pVMixerConfig->MIXER_VIDEO_LIMITER_PA_RA_CFG));

	return VMIXER_NO_ERROR;
}


VMIXER_ERROR
VMixer_initialize_layer
(VMIXER_LAYER layer,
BOOL bShow,               //video,grp
BOOL bWinBlending,        //video,grp
unsigned int uiAlpha,     //video,grp
unsigned int uiPriority,  //video,grp
VMIXER_COLOR_FORMAT color,    //grp
BOOL bBlankChange,            //grp
BOOL bPixelBlending,           //grp
BOOL bPreMul,                 //grp
unsigned int uiBlankColor,    //grp
unsigned int uiBaseAddress,   //grp
unsigned int uiSpan,          //grp
unsigned int uiWidth,         //grp
unsigned int uiHeight,        //grp
unsigned int uiSrcOffsetX,    //grp
unsigned int uiSrcOffsetY,    //grp
unsigned int uiDestOffsetX,   //grp
unsigned int uiDestOffsetY,   //grp
unsigned int uiScaleEnH,   //grp
unsigned int uiScaleEnV)   //grp
{
	unsigned int uiTempReg = 0;

	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_layer(%d,%d,%d,%d,%d,%d,%d,%d,%d,0x%x,0x%x,%d,%d,%d,%d,%d,%d,%d)\n\r"),
				layer,bShow,bWinBlending,uiAlpha,uiPriority,color,bBlankChange,bPixelBlending,bPreMul,uiBlankColor,
				uiBaseAddress,uiSpan,uiWidth,uiHeight,uiSrcOffsetX,uiSrcOffsetY,uiDestOffsetX,uiDestOffsetY));


	switch(layer)
	{
		case VM_VIDEO_LAYER:
			uiTempReg = (bWinBlending)? VM_VP_BLEND_ENABLE : VM_VP_BLEND_DISABLE;
			uiTempReg |= VM_VP_ALPHA_VALUE(uiAlpha);
			g_pVMixerConfig->MIXER_VIDEO_CFG = uiTempReg;
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_layer(0x%x)\n\r"),g_pVMixerConfig->MIXER_VIDEO_CFG));
			break;
		case VM_GPR0_LAYER:
			uiTempReg = (bBlankChange)? VM_BLANK_CHANGE_NEW_PIXEL :
									VM_BLANK_NOT_CHANGE_NEW_PIXEL;
			uiTempReg |= (bPreMul)? VM_PRE_MUL_MODE : VM_NORMAL_MODE;
 			uiTempReg |= (bWinBlending)? VM_WIN_BLEND_ENABLE : VM_WIN_BLEND_DISABLE;
			uiTempReg |= (bPixelBlending)? VM_PIXEL_BLEND_ENABLE : VM_PIXEL_BLEND_DISABLE;
			uiTempReg |= VM_EG_COLOR_FORMAT(color);
			uiTempReg |= VM_GRP_ALPHA_VALUE(uiAlpha);
			g_pVMixerConfig->MIXER_GRAPH0_CFG = uiTempReg;
			g_pVMixerConfig->MIXER_GRAPH0_BLANK = VM_GPR_BLANK_COLOR(uiBlankColor);

			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_layer(0x%x,0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH0_CFG,g_pVMixerConfig->MIXER_GRAPH0_BLANK));

			VMixer_set_grp_layer_size(layer,uiBaseAddress,uiSpan,uiWidth,uiHeight,
								uiSrcOffsetX,uiSrcOffsetY,uiDestOffsetX,uiDestOffsetY,uiScaleEnH,uiScaleEnV);
			break;
		case VM_GPR1_LAYER:
			uiTempReg = (bBlankChange)? VM_BLANK_CHANGE_NEW_PIXEL : VM_BLANK_NOT_CHANGE_NEW_PIXEL;
			uiTempReg |= (bPreMul)? VM_PRE_MUL_MODE : VM_NORMAL_MODE;
			uiTempReg |= (bWinBlending)? VM_WIN_BLEND_ENABLE : VM_WIN_BLEND_DISABLE;
			uiTempReg |= (bPixelBlending)? VM_PIXEL_BLEND_ENABLE : VM_PIXEL_BLEND_DISABLE;
			uiTempReg |= VM_EG_COLOR_FORMAT(color);
			uiTempReg |= VM_GRP_ALPHA_VALUE(uiAlpha);

			g_pVMixerConfig->MIXER_GRAPH1_CFG = uiTempReg;
			g_pVMixerConfig->MIXER_GRAPH1_BLANK = VM_GPR_BLANK_COLOR(uiBlankColor);

			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_layer(0x%x,0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH1_CFG,g_pVMixerConfig->MIXER_GRAPH1_BLANK));

			VMixer_set_grp_layer_size(layer,uiBaseAddress,uiSpan,uiWidth,uiHeight,
								uiSrcOffsetX,uiSrcOffsetY,uiDestOffsetX,uiDestOffsetY,uiScaleEnH,uiScaleEnV);
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_layer() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	VMixer_set_layer_priority(layer,uiPriority);
	VMixer_set_layer_show(layer,bShow);

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_layer()\n\r")));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_initialize_bg_color
(VMIXER_BG_COLOR_NUM colorNum,
unsigned int uiColorY,
unsigned int uiColorCb,
unsigned int uiColorCr)
{
	return VMixer_set_bg_color(colorNum,uiColorY,uiColorCb,uiColorCr);
}

VMIXER_ERROR
VMixer_initialize_csc_coef
(TVOUT_YUV_FORMAT_COMPONENT component,
VMIXER_COEF_Y_MODE mode,
unsigned int uiCoeff_0,
unsigned int uiCoeff_1,
unsigned int uiCoeff_2)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_csc_coef(%d,%d,%d,%d,d)\n\r"),component,mode,uiCoeff_0,uiCoeff_1,uiCoeff_2));

	switch(component)
	{
		case TVOUT_YUV_Y:
			g_pVMixerConfig->MIXER_CM_COEFF_Y = (mode==VMIXER_COEF_Y_WIDE)?
			VM_BG_COLOR_WIDE : VM_BG_COLOR_NARROW;
			g_pVMixerConfig->MIXER_CM_COEFF_Y |= VM_BG_COEFF_0(uiCoeff_0) |
			VM_BG_COEFF_1(uiCoeff_1) |
			VM_BG_COEFF_2(uiCoeff_2);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_csc_coef(0x%x)\n\r"),g_pVMixerConfig->MIXER_CM_COEFF_Y));
			break;
		case TVOUT_YUV_CB:
			g_pVMixerConfig->MIXER_CM_COEFF_CB = VM_BG_COEFF_0(uiCoeff_0) |
			VM_BG_COEFF_1(uiCoeff_1) |
			VM_BG_COEFF_2(uiCoeff_2);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_csc_coef(0x%x)\n\r"),g_pVMixerConfig->MIXER_CM_COEFF_CB));
			break;
		case TVOUT_YUV_CR:
			g_pVMixerConfig->MIXER_CM_COEFF_CR = VM_BG_COEFF_0(uiCoeff_0) |
			VM_BG_COEFF_1(uiCoeff_1) |
			VM_BG_COEFF_2(uiCoeff_2);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_csc_coef(0x%x)\n\r"),g_pVMixerConfig->MIXER_CM_COEFF_CR));
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_csc_coef() : invalid component parameter = %d\n\r"),component));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}
	
	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_csc_coef()\n\r")));

	return VMIXER_NO_ERROR;
}

void
VMixer_initialize_csc_coef_default
(VMIXER_CSC_TYPE cscType)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_initialize_csc_coef_default(%d)\n\r"),cscType));

	switch(cscType)
	{
		case VMIXER_CSC_RGB_TO_YUV601_LR:
			g_pVMixerConfig->MIXER_CM_COEFF_Y  = (0<<30)|(153<<20)|(300<<10)|(58<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CB = (936<<20)|(851<<10)|(262<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CR = (262<<20)|(805<<10)|(982<<0);
			break;
		case VMIXER_CSC_RGB_TO_YUV601_FR:
			g_pVMixerConfig->MIXER_CM_COEFF_Y  = (1<<30)|(132<<20)|(258<<10)|(50<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CB = (949<<20)|(876<<10)|(225<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CR = (225<<20)|(836<<10)|(988<<0);
			break;
		case VMIXER_CSC_RGB_TO_YUV709_LR:
			g_pVMixerConfig->MIXER_CM_COEFF_Y  = (0<<30)|(109<<20)|(366<<10)|(36<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CB = (964<<20)|(822<<10)|(216<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CR = (262<<20)|(787<<10)|(1000<<0);
			break;
		case VMIXER_CSC_RGB_TO_YUV709_FR:
			g_pVMixerConfig->MIXER_CM_COEFF_Y  = (1<<30)|(94<<20)|(314<<10)|(32<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CB = (972<<20)|(851<<10)|(225<<0);
			g_pVMixerConfig->MIXER_CM_COEFF_CR = (225<<20)|(820<<10)|(1004<<0);
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_initialize_csc_coef_default() : invalid cscType parameter = %d\n\r"),cscType));
			break;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_initialize_csc_coef_default(0x%x,0x%x,0x%x)\n\r"),
			g_pVMixerConfig->MIXER_CM_COEFF_Y,g_pVMixerConfig->MIXER_CM_COEFF_CB,g_pVMixerConfig->MIXER_CM_COEFF_CR));
}


// set
//  - set functions are only called under running vmixer
VMIXER_ERROR
VMixer_set_layer_show
(VMIXER_LAYER layer,
BOOL bShow)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_layer_show(%d,%d)\n\r"),layer,bShow));

	switch(layer)
	{
		case VM_VIDEO_LAYER:
			g_pVMixerConfig->MIXER_CFG = (bShow)?
			(g_pVMixerConfig->MIXER_CFG | VM_VIDEO_LAYER_SHOW):
			(g_pVMixerConfig->MIXER_CFG & ~VM_VIDEO_LAYER_SHOW);
			break;
		case VM_GPR0_LAYER:
			g_pVMixerConfig->MIXER_CFG = (bShow)?
			(g_pVMixerConfig->MIXER_CFG | VM_GRAPHIC0_LAYER_SHOW):
			(g_pVMixerConfig->MIXER_CFG & ~VM_GRAPHIC0_LAYER_SHOW);
			break;
		case VM_GPR1_LAYER:
			g_pVMixerConfig->MIXER_CFG = (bShow)?
			(g_pVMixerConfig->MIXER_CFG | VM_GRAPHIC1_LAYER_SHOW):
			(g_pVMixerConfig->MIXER_CFG & ~VM_GRAPHIC1_LAYER_SHOW);
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_layer_show() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}
	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_layer_show(0x%x)\n\r"),g_pVMixerConfig->MIXER_CFG));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_set_layer_priority
(VMIXER_LAYER layer,
unsigned int uiPriority)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_layer_priority(%d,%d)\n\r"),layer,uiPriority));

	switch(layer)
	{
		case VM_VIDEO_LAYER:
			g_pVMixerConfig->MIXER_LAYER_CFG
			= VM_VP_LAYER_PRIORITY_CLEAR(g_pVMixerConfig->MIXER_LAYER_CFG) |
			VM_VP_LAYER_PRIORITY(uiPriority);
			break;
		case VM_GPR0_LAYER:
			g_pVMixerConfig->MIXER_LAYER_CFG
			= VM_GRP0_LAYER_PRIORITY_CLEAR(g_pVMixerConfig->MIXER_LAYER_CFG) |
			VM_GRP0_LAYER_PRIORITY(uiPriority);
			break;
		case VM_GPR1_LAYER:
			g_pVMixerConfig->MIXER_LAYER_CFG
			= VM_GRP1_LAYER_PRIORITY_CLEAR(g_pVMixerConfig->MIXER_LAYER_CFG) |
			VM_GRP1_LAYER_PRIORITY(uiPriority);
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_layer_priority() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_layer_priority(0x%x)\n\r"),g_pVMixerConfig->MIXER_LAYER_CFG));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_set_grp_base_address
(VMIXER_LAYER layer,
unsigned int uiBaseAddress)
{
	RETAILMSG(TV_PLAY,(_T("[VMIXER]++VMixer_set_grp_base_address(%d,0x%x)\n\r"),layer,uiBaseAddress));

	if(VM_GRP_ADDR_ILLEGAL(uiBaseAddress))
	{
		DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_grp_base_address() : address is not word align = %d\n\r"),uiBaseAddress));
		return VMIXER_ERROR_BASE_ADDRESS_MUST_WORD_ALIGN;
	}

	switch(layer)
	{
		case VM_GPR0_LAYER:
			g_pVMixerConfig->MIXER_GRAPH0_BASE = VM_GPR_BASE(uiBaseAddress);
			RETAILMSG(TV_PLAY,(_T("[VMIXER]--VMixer_set_grp_base_address(0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH0_BASE));
			break;
		case VM_GPR1_LAYER:
			g_pVMixerConfig->MIXER_GRAPH1_BASE = VM_GPR_BASE(uiBaseAddress);
			RETAILMSG(TV_PLAY,(_T("[VMIXER]--VMixer_set_grp_base_address(0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH1_BASE));
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_grp_base_address() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	RETAILMSG(TV_PLAY,(_T("[VMIXER]--VMixer_set_grp_base_address()\n\r")));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_set_grp_layer_position
(VMIXER_LAYER layer,
unsigned int uiDestOffsetX,
unsigned int uiDestOffsetY)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_grp_layer_position(%d,%d,%d)\n\r"),layer,uiDestOffsetX,uiDestOffsetY));

	switch(layer)
	{
		case VM_GPR0_LAYER:
			g_pVMixerConfig->MIXER_GRAPH0_DXY = VM_GRP_DESTX(uiDestOffsetX) | VM_GRP_DESTY(uiDestOffsetY);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_position(0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH0_DXY));
			break;
		case VM_GPR1_LAYER:
			g_pVMixerConfig->MIXER_GRAPH1_DXY = VM_GRP_DESTX(uiDestOffsetX) | VM_GRP_DESTY(uiDestOffsetY);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_position(0x%x)\n\r"),g_pVMixerConfig->MIXER_GRAPH1_DXY));
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_grp_layer_position() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_position()\n\r")));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_set_grp_layer_size
(VMIXER_LAYER layer,
unsigned int uiBaseAddress,
unsigned int uiSpan,
unsigned int uiWidth,
unsigned int uiHeight,
unsigned int uiSrcOffsetX,
unsigned int uiSrcOffsetY,
unsigned int uiDestOffsetX,
unsigned int uiDestOffsetY,
unsigned int uiScaleEnH,
unsigned int uiScaleEnV
)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_grp_layer_size(%d,0x%x,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n\r"),
	layer,uiBaseAddress,uiSpan,uiWidth,uiHeight,uiSrcOffsetX,uiSrcOffsetY,uiDestOffsetX,uiDestOffsetY,uiScaleEnH,uiScaleEnV));

	switch(layer)
	{
		case VM_GPR0_LAYER:
			g_pVMixerConfig->MIXER_GRAPH0_SPAN = VM_GRP_SPAN(uiSpan);
			g_pVMixerConfig->MIXER_GRAPH0_WH = VM_GRP_WIDTH(uiWidth) | 
												VM_GRP_HEIGHT(uiHeight)|
												VM_GRP_H_SCALE_EN(uiScaleEnH) |
												VM_GRP_V_SCALE_EN(uiScaleEnV);
			g_pVMixerConfig->MIXER_GRAPH0_SXY = VM_GRP_STARTX(uiSrcOffsetX) | VM_GRP_STARTY(uiSrcOffsetY);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_size(0x%x,0x%x,0x%x)\n\r"),
			g_pVMixerConfig->MIXER_GRAPH0_SPAN,g_pVMixerConfig->MIXER_GRAPH0_WH,g_pVMixerConfig->MIXER_GRAPH0_SXY));

			break;
		case VM_GPR1_LAYER:
			g_pVMixerConfig->MIXER_GRAPH1_SPAN = VM_GRP_SPAN(uiSpan);
			g_pVMixerConfig->MIXER_GRAPH1_WH = VM_GRP_WIDTH(uiWidth) | 
												VM_GRP_HEIGHT(uiHeight)|
												VM_GRP_H_SCALE_EN(uiScaleEnH) |
												VM_GRP_V_SCALE_EN(uiScaleEnV);
			g_pVMixerConfig->MIXER_GRAPH1_SXY = VM_GRP_STARTX(uiSrcOffsetX) | VM_GRP_STARTY(uiSrcOffsetY);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_size(0x%x,0x%x,0x%x)\n\r"),
			g_pVMixerConfig->MIXER_GRAPH1_SPAN,g_pVMixerConfig->MIXER_GRAPH1_WH,g_pVMixerConfig->MIXER_GRAPH1_SXY));

			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_grp_layer_size() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	VMixer_set_grp_base_address(layer,uiBaseAddress);
	VMixer_set_grp_layer_position(layer,uiDestOffsetX,uiDestOffsetY);

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_grp_layer_size()\n\r")));

	return VMIXER_NO_ERROR;
}

VMIXER_ERROR
VMixer_set_bg_color
(VMIXER_BG_COLOR_NUM colorNum,
unsigned int uiColorY,
unsigned int uiColorCb,
unsigned int uiColorCr)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_bg_color(%d,%d,%d,%d)\n\r"),colorNum,uiColorY,uiColorCb,uiColorCr));

	switch(colorNum)
	{
		case VMIXER_BG_COLOR_0:
			g_pVMixerConfig->MIXER_BG_COLOR0 = VM_BG_COLOR_Y(uiColorY) |
			VM_BG_COLOR_CB(uiColorCb) |
			VM_BG_COLOR_CR(uiColorCr);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_bg_color(0x%x)\n\r"),g_pVMixerConfig->MIXER_BG_COLOR0));
			break;
		case VMIXER_BG_COLOR_1:
			g_pVMixerConfig->MIXER_BG_COLOR1 = VM_BG_COLOR_Y(uiColorY) |
			VM_BG_COLOR_CB(uiColorCb) |
			VM_BG_COLOR_CR(uiColorCr);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_bg_color(0x%x)\n\r"),g_pVMixerConfig->MIXER_BG_COLOR1));
			break;
		case VMIXER_BG_COLOR_2:
			g_pVMixerConfig->MIXER_BG_COLOR2 = VM_BG_COLOR_Y(uiColorY) |
			VM_BG_COLOR_CB(uiColorCb) |
			VM_BG_COLOR_CR(uiColorCr);
			DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_bg_color(0x%x)\n\r"),g_pVMixerConfig->MIXER_BG_COLOR2));
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_bg_color() : invalid uiColorNum parameter = %d\n\r"),colorNum));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_bg_color()\n\r")));

	return VMIXER_NO_ERROR;
}



// etc
//  -

VMIXER_ERROR
VMixer_get_layer_info
(VMIXER_LAYER layer,
BOOL* bShow,
unsigned int* uiPriority)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_get_layer_priority(%d)\n\r"),layer));

	switch(layer)
	{
		case VM_VIDEO_LAYER:
			*bShow = (g_pVMixerConfig->MIXER_LAYER_CFG & VM_VIDEO_LAYER_SHOW)?  TRUE:FALSE;
			*uiPriority = VM_VP_LAYER_PRIORITY_INFO(g_pVMixerConfig->MIXER_LAYER_CFG);
			break;
		case VM_GPR0_LAYER:
			*bShow = (g_pVMixerConfig->MIXER_LAYER_CFG & VM_GRAPHIC0_LAYER_SHOW)?  TRUE:FALSE;
			*uiPriority = VM_GRP0_LAYER_PRIORITY_INFO(g_pVMixerConfig->MIXER_LAYER_CFG);
			break;
		case VM_GPR1_LAYER:
			*bShow = (g_pVMixerConfig->MIXER_LAYER_CFG & VM_GRAPHIC1_LAYER_SHOW)?  TRUE:FALSE;
			*uiPriority = VM_GRP1_LAYER_PRIORITY_INFO(g_pVMixerConfig->MIXER_LAYER_CFG);
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_get_layer_priority() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_get_layer_priority(%d,%d)\n\r"),*bShow,*uiPriority));

	return VMIXER_NO_ERROR;
}

// start
//  - start functions are only called under stopping vmixer
void
VMixer_start
(void)
{
	//int i;
	//unsigned int *puiTemp = (unsigned int*)g_pVMixerConfig;
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_start()\n\r")));

	g_pVMixerConfig->MIXER_STATUS |= VM_MIXER_START;

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_start(0x%x)\n\r"),g_pVMixerConfig->MIXER_STATUS));
	//for(i=0;i<(0x8C/4);i++)
	//{
	//    DBGMSG(TV_USR1,(_T("[VMIXER] 0x%x = 0x%x\n\r"),puiTemp+i,*(puiTemp+i)));
	//}
}


// stop
//  - stop functions are only called under running vmixer
void
VMixer_stop
(void)
{
	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_stop()\n\r")));

	g_pVMixerConfig->MIXER_STATUS &= ~VM_MIXER_START;

	while((g_pVMixerConfig->MIXER_STATUS_S & (VM_MIXER_START)))
	{
		Sleep(1);
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_stop(0x%x)\n\r"),g_pVMixerConfig->MIXER_STATUS));
}


// interrupt
//  - for debug
VMIXER_ERROR
VMixer_set_underflow_interrupt_enable
(VMIXER_LAYER layer,
BOOL bEn)
{
	unsigned int uiEnableMaks;

	DBGMSG(TV_FUNC,(_T("[VMIXER]++VMixer_set_underflow_interrupt_enable(%d,%d)\n\r"),layer,bEn));

	switch(layer)
	{
		case VM_VIDEO_LAYER:
			uiEnableMaks = VM_VP_INT_ENABLE;
			break;
		case VM_GPR0_LAYER:
			uiEnableMaks = VM_GRP0_INT_ENABLE;
			break;
		case VM_GPR1_LAYER:
			uiEnableMaks = VM_GRP1_INT_ENABLE;
			break;
		default:
			DBGMSG(TV_USR1,(_T("[VMIXER:ERR] VMixer_set_underflow_interrupt_enable() : invalid layer parameter = %d\n\r"),layer));
			return VMIXER_ERROR_INVALID_PARAM;
			break;
	}

	if(bEn)
	{
		g_pVMixerConfig->MIXER_INT_EN |= uiEnableMaks;
	}
	else
	{
		g_pVMixerConfig->MIXER_INT_EN &= ~uiEnableMaks;
	}

	DBGMSG(TV_FUNC,(_T("[VMIXER]--VMixer_set_underflow_interrupt_enable(0x%x)\n\r"),g_pVMixerConfig->MIXER_INT_EN));

	return VMIXER_NO_ERROR;
}

void
VMixer_clear_underflow_interrupt
(BOOL bVideo,
BOOL bGrp0,
BOOL bGpr1,
BOOL bInt)
{
	unsigned int uiTempReg = 0;

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]++VMixer_clear_underflow_interrupt(%d,%d,%d,%d)\n\r"),bVideo,bGrp0,bGpr1,bInt));

	if(bVideo)
	{
		g_pVMixerConfig->MIXER_INT_STATUS |= VM_VP_INT_FIRED;
	}
	if(bGrp0)
	{
		g_pVMixerConfig->MIXER_INT_STATUS |= VM_GRP0_INT_FIRED;
	}
	if(bGpr1)
	{
		g_pVMixerConfig->MIXER_INT_STATUS |= VM_GRP1_INT_FIRED;
	}
	if(bInt)
	{
		g_pVMixerConfig->MIXER_INT_STATUS |= VM_VSYNC_INT_FIRED;
	}

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]--VMixer_clear_underflow_interrupt(0x%x)\n\r"),g_pVMixerConfig->MIXER_INT_STATUS));
}

void
VMixer_get_underflow_interrupt_fired
(BOOL* bVideo,
BOOL* bGrp0,
BOOL* bGpr1,
BOOL* bInt)
{
	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]++VMixer_get_underflow_interrupt_fired(0x%x)\n\r"),g_pVMixerConfig->MIXER_INT_STATUS));

	*bVideo = (g_pVMixerConfig->MIXER_INT_STATUS & VM_VP_INT_FIRED)? TRUE:FALSE;
	*bGrp0 = (g_pVMixerConfig->MIXER_INT_STATUS & VM_GRP0_INT_FIRED)? TRUE:FALSE;
	*bGpr1 = (g_pVMixerConfig->MIXER_INT_STATUS & VM_GRP1_INT_FIRED)? TRUE:FALSE;
	*bInt = (g_pVMixerConfig->MIXER_INT_STATUS & VM_INT_FIRED)? TRUE:FALSE;

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]--VMixer_get_underflow_interrupt_fired(%d,%d,%d,%d)\n\r"),*bVideo,*bGrp0,*bGpr1,*bInt));
}

void 
VMixer_set_vsync_interrupt_enable(BOOL bEn)
{
	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]++VMixer_clear_vsync_interrupt()\n\r")));

	if(bEn)
	{
		g_pVMixerConfig->MIXER_INT_EN |= VM_VSYNC_INT_ENABLE;
	}
	else
	{
		g_pVMixerConfig->MIXER_INT_EN &= ~VM_VSYNC_INT_ENABLE;
	}

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]--VMixer_clear_vsync_interrupt()\n\r")));
}


void 
VMixer_clear_vsync_interrupt()
{
	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]++VMixer_clear_vsync_interrupt()\n\r")));

	g_pVMixerConfig->MIXER_INT_STATUS |= VM_VSYNC_INT_FIRED;

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]--VMixer_clear_vsync_interrupt()\n\r")));
}

BOOL
VMixer_get_vsync_interrupt_fired()
{
	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]++VMixer_get_vsync_interrupt_fired()\n\r")));

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[VMIXER]--VMixer_get_vsync_interrupt_fired()\n\r")));
	
	return (g_pVMixerConfig->MIXER_INT_STATUS & VM_INT_FIRED)? TRUE:FALSE;

}



