//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// 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:    OV2655_module.cpp

Abstract:       OV2655 Camera module control module

Functions:


Notes:


--*/

#include <bsp.h>
#include <module.h>
#include "OV2655_module.h"
#include "OV2655_module_reg.h"
//#include "ov2655_2m.h"


#define PREDEFINED_IMAGE_SIZE       (14)

#ifndef TVP5150
#define CAMERA_WRITE_ADDRESS    (0x60 + 0)
#define CAMERA_READ_ADDRESS     (0x60 + 1)
#define IIC_CLOCK                   (100)
#else
// for tvp5150 
#define CAMERA_WRITE_ADDRESS    (0xB8 + 0)	//0xBAÉÏÀ­  	0XB8 ÏÂÀ­
//#define CAMERA_READ_ADDRESS     (0x60 + 1)
#define IIC_CLOCK                   (100)

#endif



BYTE SupportedModuleImageSize[PREDEFINED_IMAGE_SIZE][2]
 // SizeValue[0], SizeValue[1]
  = { {0x02, 6},    // QCIF
      {0x02, 5},    // CIF  /*352x288*/
      {0x02, 4},    // QQVGA
      {0x02, 3},    // QVGA
      {0x02, 2},    // VGA
      {0,0},        // SVGA /*800x600*/
      {0x02, 1},    // SXGA /*1280x1024*/
      {0x02, 0},    // UXGA /*1600x1200*/
      {0,0},        // QXGA /*2048x1536*/
      {0,0},        // WVGA /*854x480*/
      {0,0},        // HD720    /*1280x720*/
      {0,0},        // HD1080   /*1920x1080*/
      {0x02, 9},    // SUB_SAMPLING2    /*800x600*/
      {0x02, 0x0B}, // SUB_SAMPLING4    /*400x300*/
    };


#define MODULE_NAME _T("OV2655")

//========================================================
//  Global variable definition

//========================================================
//  OV2655 functions
OV2655::OV2655()
{
    m_oCommIF = NULL;
    memset(&ModuleDescriptor , 0 , sizeof(MODULE_DESCRIPTOR));

}

OV2655::~OV2655()
{
}
OV2655::OV2655(ICamComm *CommIF)
{
    m_oCommIF = CommIF;
}
MODULE_STATUS OV2655::Init()
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));

	RETAILMSG(1, (TEXT("\r\nOV2655::Init\r\n")));

    PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

    // GPIO Virtual alloc
    ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
    m_regIOP = (GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG), FALSE);
    if (m_regIOP == NULL)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): m_regIOP DrvLib_MapIoSpace failed!\r\n"), _T(__FUNCTION__)));
        return MOD_STATUS_FAIL;
    }

    m_oCommIF = new CamCommI2C();
    if(!m_oCommIF)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Cannot create Comm Instance!\r\n"), _T(__FUNCTION__)));
        return MOD_STATUS_FAIL;
    }

    ModuleDescriptor.ModuleID = SYSLSI_OV2655;
    ModuleDescriptor.ITUXXX = OV2655_MODULE_ITUXXX;
    ModuleDescriptor.ModuleInterlace = OV2655_MODULE_INTERLACE;
    ModuleDescriptor.MIPI = OV2655_MODULE_MIPI;
    ModuleDescriptor.UVOffset = OV2655_MODULE_UVOFFSET;
    ModuleDescriptor.SourceHSize = OV2655_MODULE_HSIZE;
    ModuleDescriptor.Order422 = OV2655_MODULE_YUVORDER;
    ModuleDescriptor.SourceVSize = OV2655_MODULE_VSIZE;
    ModuleDescriptor.Clock = OV2655_MODULE_CLOCK;
    ModuleDescriptor.Codec = OV2655_MODULE_CODEC;
    ModuleDescriptor.HighRst = OV2655_MODULE_HIGHRST;
    ModuleDescriptor.SourceHOffset = OV2655_MODULE_HOFFSET;
    ModuleDescriptor.SourceVOffset = OV2655_MODULE_VOFFSET;
    ModuleDescriptor.InvPCLK = OV2655_MODULE_INVPCLK;
    ModuleDescriptor.InvVSYNC = OV2655_MODULE_INVVSYNC;
    ModuleDescriptor.InvHREF = OV2655_MODULE_INVHREF;

    DBGMSG(CAMC_FUNC,(_T("%s ModuleDescriptor Dump:%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n"), _T(__FUNCTION__),
    ModuleDescriptor.ITUXXX,
    ModuleDescriptor.ModuleInterlace,
    ModuleDescriptor.MIPI,
    ModuleDescriptor.LANE,
    ModuleDescriptor.JPEG,
    ModuleDescriptor.UVOffset,
    ModuleDescriptor.SourceHSize,
    ModuleDescriptor.Order422,
    ModuleDescriptor.SourceVSize,
    ModuleDescriptor.Clock,
    ModuleDescriptor.Codec,
    ModuleDescriptor.HighRst,
    ModuleDescriptor.SourceHOffset,
    ModuleDescriptor.SourceVOffset,
    ModuleDescriptor.InvPCLK,
    ModuleDescriptor.InvVSYNC,
    ModuleDescriptor.InvHREF,
    ModuleDescriptor.JpegSpoofHeight,
    ModuleDescriptor.JpegSpoofWidth,
    ModuleDescriptor.eHSsettle
    ));


	//RETAILMSG(1, (TEXT("OV2655::SensorStart---init------------------------\r\n")));
    //m_oCommIF->WriteRegisterSeq(ov2655_init_reg);


    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::Deinit()
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));

if (0)//x210
{
    // camera power  GPH2_2     added by terry 20120426
    Set_PinFunction(m_regIOP, GPH22_Output);
    Set_PinPullUD(m_regIOP, GPH22_Output, sgip_PULL_DISABLE);
    Set_PinData(m_regIOP, GPH22_Output, 1);
}
else //x210 ii
{
	// camera power  GPF3_4 	added by terry 20120705  //FOR x210-ii
	Set_PinFunction(m_regIOP, GPF34_Output);
	Set_PinPullUD(m_regIOP, GPF34_Output, sgip_PULL_DISABLE);
	Set_PinData(m_regIOP, GPF34_Output, 1);
//	RETAILMSG(1, (TEXT("\r\nTVP5150::GPH34	1	POWER Off-----x210-ii---------------\r\n")));
}


    if(m_regIOP != NULL)
    {
        MmUnmapIoSpace((PVOID)m_regIOP, sizeof(GPIO_REG));
        m_regIOP = NULL;
    }
    if(m_oCommIF)
    {
        delete m_oCommIF;
        m_oCommIF=NULL;
    }
    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::InitSensor()
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));


    // Set the i2c slave address and clock
    // add allocation of resources which are used for S5K6AA isp
    // initialize the camera sensor


    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::SensorPrepare()
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));


    // Set the i2c slave address and clock
    // add allocation of resources which are used for S5K6AA isp
    // initialize the camera sensor

    return MOD_STATUS_SUCCESS;
}




MODULE_STATUS OV2655::SensorStart()
{
    int i=0,nLen = 0;
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));


    DBGMSG(CAMC_FUNC, (_T("Write Init Command to Module\r\n")));

	RETAILMSG(1, (TEXT("OV2655::SensorStart\r\n")));



	if(0)
	{
	    // camera power  GPH2_2     added by terry 20120426
	    Set_PinFunction(m_regIOP, GPH22_Output);
	    Set_PinPullUD(m_regIOP, GPH22_Output, sgip_PULL_DISABLE);
	    Set_PinData(m_regIOP, GPH22_Output, 0);  // POWER ON

	}
	else
	{

		Set_PinFunction(m_regIOP, GPF34_Output);
		Set_PinPullUD(m_regIOP, GPF34_Output, sgip_PULL_DISABLE);
		Set_PinData(m_regIOP, GPF34_Output, 0);
		RETAILMSG(1, (TEXT("\r\nOV2655::GPH34  0	POWER On-----x210-ii---------------\r\n")));
	
	}

#ifndef TVP5150

    // Set the i2c slave address and clock
    // add allocation of resources which are used for S5K6AA isp
    // initialize the camera sensor
    m_oCommIF->Open(CAM_OV2655_DEVICE_ID, CAM_OV2655_I2C_CLOCK);

    nLen = sizeof(ov2655_init_reg)/sizeof(ov2655_init_reg[0]);

    m_oCommIF->WriteRegisterSeq(ov2655_init_reg,nLen);

    m_oCommIF->Close();


#else
/*
	// camera power  GPF3_4 	added by terry 20120705  //FOR x210-ii
	Set_PinFunction(m_regIOP, GPF34_Output);
	Set_PinPullUD(m_regIOP, GPF34_Output, sgip_PULL_DISABLE);
	Set_PinData(m_regIOP, GPF34_Output, 0);
	RETAILMSG(1, (TEXT("\r\nTVP5150::GPH34  0	POWER On-----x210-ii---------------\r\n")));
*/

	// Set the i2c slave address and clock
	// add allocation of resources which are used for TVP5150 isp
	// initialize the camera sensor
	m_oCommIF->Open(CAM_TVP5150_DEVICE_ID, CAM_TVP5150_I2C_CLOCK);

	UCHAR ID[5] = {0};

//read tvp5150 ID 5051
	m_oCommIF->ReadRegisters(ID,0x80,2);
	RETAILMSG(1,(TEXT("ID[0x%x] ID[0x%x]\r\n"),ID[0],ID[1]));

	memset(ID,0,sizeof(ID));


	nLen = sizeof(tvp5150_init_reg)/sizeof(tvp5150_init_reg[0]);
#if 0	
	m_oCommIF->ReadRegisters(&ID[0],0x0,1);
	m_oCommIF->ReadRegisters(&ID[1],0x3,1);
		m_oCommIF->ReadRegisters(&ID[2],0x4,1);
		RETAILMSG(1,(TEXT("ID[0x%x] ID[0x%x] ID[0x%x] nlen=%d\r\n"),ID[0],ID[1],ID[2],nLen));

#endif	
	m_oCommIF->WriteRegisterSeq(tvp5150_init_reg,nLen);
	RETAILMSG(1,(TEXT("[TVP5150_module]------------------------------2---------\r\n")));	
#if 1
	m_oCommIF->ReadRegisters(&ID[0],0x3,1);
	m_oCommIF->ReadRegisters(&ID[1],0x0d,1);
		m_oCommIF->ReadRegisters(&ID[2],0x0f,1);
		m_oCommIF->ReadRegisters(&ID[3],0x1b,1);



		
		RETAILMSG(1,(TEXT("ID[0x%x] ID[0x%x] ID[0x%x] ID[0x%x]\r\n"),ID[0],ID[1],ID[2],ID[3]));
		RETAILMSG(1,(TEXT("[TVP5150_module]----------------------------3-----------\r\n")));	
#endif

	m_oCommIF->Close();

#endif
    return MOD_STATUS_SUCCESS;
}


MODULE_STATUS OV2655::Power(BOOL bOnOff)
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s - OnOff=%d\r\n"), MODULE_NAME, _T(__FUNCTION__), bOnOff));

    if ( bOnOff == TRUE )
    {
        PowerStatus = MOD_PWR_STATUS_ON;
    }
    else
    {
        PowerStatus = MOD_PWR_STATUS_OFF;
    }

    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::Standby(BOOL bActive)
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s - Active=%d\r\n"), MODULE_NAME, _T(__FUNCTION__), bActive));

    if ( bActive == TRUE )
    {

        PowerStatus = MOD_PWR_STATUS_STANDBY;
    }
    else
    {

        PowerStatus = MOD_PWR_STATUS_ON;
    }

    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::Reset(BOOL bActive)
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s - Active=%d\r\n"), MODULE_NAME, _T(__FUNCTION__), bActive));

    if ( bActive == TRUE )
    {
        PowerStatus = MOD_PWR_STATUS_RESET_ACTIVE;
    }
    else
    {
        PowerStatus = MOD_PWR_STATUS_RESET_DEACTIVE;
    }
    return MOD_STATUS_SUCCESS;
}

MODULE_STATUS OV2655::GetSupportFormat(MODULE_DESCRIPTOR *outModuleDesc)
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));

    memcpy(outModuleDesc, &ModuleDescriptor, sizeof(MODULE_DESCRIPTOR));

    DBGMSG(CAMC_FUNC,(_T("gModuleDesc Dump:%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n"),
                    outModuleDesc->ITUXXX,
                    outModuleDesc->ModuleInterlace,
                    outModuleDesc->MIPI,
                    outModuleDesc->LANE,
                    outModuleDesc->JPEG,
                    outModuleDesc->UVOffset,
                    outModuleDesc->SourceHSize,
                    outModuleDesc->Order422,
                    outModuleDesc->SourceVSize,
                    outModuleDesc->Clock,
                    outModuleDesc->Codec,
                    outModuleDesc->HighRst,
                    outModuleDesc->SourceHOffset,
                    outModuleDesc->SourceVOffset,
                    outModuleDesc->InvPCLK,
                    outModuleDesc->InvVSYNC,
                    outModuleDesc->InvHREF
                    ));

    return MOD_STATUS_SUCCESS;
}

// OV2655 isp support only yuv422(UYVY) format
// So, we don't check the media format
MODULE_STATUS OV2655::SetFormatSize(CAMIF_IMG_SIZE Size)
{
    DBGMSG(CAMC_FUNC, (_T("[%s] %s - %s, Size = %d\r\n"), MODULE_NAME, _T(__FUNCTION__), CAM_OPMODE_TO_STR(OperationMode), Size));
    MODULE_STATUS Status = MOD_STATUS_SUCCESS;

    return Status;
}


