/*=================================< video.c >===============================*/
//  
//    Title:      VIDEO UNIT 
//    Saved date: 04 Jun 2003 12:41:59
//    Written by: JAG
//    Project:    RMS101 SBC
//    Target:     LH79520
//    Compiler:   GNU GCC for ARM
//		Copyright:	Subject to the Revely Open Source License (see readme.txt)
//
// The Video.c unit contains low level functions for configuring the video 
// hardware on the RMS101 board. This includes the CH7013 Encoder and the 
// LH79520's internal CLCD controller.  Calls to this unit are usually made
// from the Graphics unit.
//
//	The following Resolution Modes are currently supported:
//
//		- 640x480 in 8 bit color 60Hz (NTSC and PAL only work in this mode)
//		- 640x480 in 15 bit color 60Hz
//		- 800x600 in 8 bit color 72Hz
//
// The following Output Modes are currently supported:
//
//		- RGB
//		- NTSC
//		- PAL
//
// History: 
//
// 1.00	10-12-02	JAG Initial release
//	1.01	02-06-03 JAG Added PAL support
// 1.02	04-06-03 JAG Added dual video buffers
// 
/*===========================================================================*/

#include <stddefs.h> 
#include <regs.h>
#include <video.h>
#include <i2c.h>

/*=========================< Constant Definitions >==========================*/

	// Defines for CLCDC 

	// VGA Values
	#define VGAHORIZ_BP 41 
	#define VGAHORIZ_FP 19
	#define VGAHORIZ_SW 93 
	#define VGAVERT_BP 32 
	#define VGAVERT_FP 11 
	
	// SVGA Values
	#define SVGAHORIZ_BP 63 	// 64 - 1
	#define SVGAHORIZ_FP 55 	// 56 - 1
	#define SVGAHORIZ_SW 119 // 120 - 1
	#define SVGAVERT_BP 20	// 20 - 1 
	#define SVGAVERT_FP 34	// 35 - 1 
			
	// NTSC Values
	// Note : HBP + HFP + HSW + PIX = 784
	#define NTSCHORIZ_BP 39 //40-1=39
	#define NTSCHORIZ_FP 39	//40-1=39
	#define NTSCHORIZ_SW 64 //64   
	// Note : VBP + VFP + VSW + LINES = 600
	#define NTSCVERT_BP 59   // 58
	#define NTSCVERT_FP 58   // 58	
	
	// PAL Values
	// HBP + HFP + HSW + PIX = 840 
	#define PALHORIZ_BP 67 //68-1
	#define PALHORIZ_FP 67 //68-1
	#define PALHORIZ_SW 64 //64 
	// VBP + VFP + VSW + LINES = 625
	#define PALVERT_BP 71   // 134-1
	#define PALVERT_FP 71   // 134-1
		
	// VGA settings
	#define PIXLINE 39	// 640 / 16 - 1
	#define VERT_SW 1		// 60ms 
	#define LINES 479		// 480 - 1
	
	// SVGA video settings
	#define SVVERT_SW 5		// 125us 
	#define SVLINES 	599	// 600 - 1
	#define SVPIXLINE 49	// 800 / 16 - 1 = 49



/*----------------------------< Unit Variables >-----------------------------*/
unsigned char vram1[VRAM_SIZE]  __attribute__ ((section (".video"))) = {0};
unsigned char vram2[VRAM_SIZE]  __attribute__ ((section (".video"))) = {0};

// A Dac register data value of 0xff signifies an unused address

// Register settings for NTSC Master mode 17
const BYTE NTSCDacRegs []  = {
	0x6a, 0x02, 0xff, 0x00, 0x00, 0xff, 0xd0, 108,  0x00, 0x7f, // 0-9
	0x2c,	0x00,	0xff, 0x03, 0xff, 0xff, 0xff, 0x03, 0xff, 0x00, // 0A - 13
	0x3f, 0x7e, 0xff, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, // 14 - 1D
	0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};// 1E - 27

// Register settings for PAL Master mode 15
const BYTE PALDacRegs []  = {
	0x61, 0x02, 0xff, 0x00, 0x00, 0xff, 0xd0, 108,  0x00, 0x7f, // 0-9
	0x2c,	0x00,	0xff, 0x03, 0xff, 0xff, 0xff, 0x03, 0xff, 0x00, // 0A - 13
	0x04, 0x09, 0xff, 0x07, 0x02, 0x06, 0x06, 0x0f, 0x01, 0x0f, // 14 - 1D
	0x0d, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};// 1E - 27

// Register settings for VGA DAC Only mode (SVGA too, except for Pout setting)
const BYTE VGADacRegs []  = {
	0x6a, 0x32, 0xff, 0x00, 0x23, 0xff, 0xd0, 0x00, 0x00, 0x7f, // 0-9
	0x00,	0x00,	0xff, 0x00, 0xff, 0xff, 0xff, 0x03, 0xff, 0x00, // 10 - 19
	56,   100,  0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 20 - 29
	0xff, 0xff, 0x0a, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};// 30 - 39


/*-------------------------------< InitVideo >-------------------------------*/
void VideoInit(PWORD pV1, PWORD pV2, BYTE bVRes, BYTE bVOut)
{
	unsigned int i,x,y, z; 
	unsigned char b,c;
		
	if (bVOut != VOUT_RGB)
		bVRes = VRES_VGA;
		
	// We're using TFT mode, but we must config HR-TFT controller anyway
	HRTFTSETUP = 0x0000;
	HRTFTCONT = 0x0000; 
	
	// Set up LCD I/O Pins
	LCDMUX = 0x1f3dbc1c;	
		
	// Setup LCD Controller 
	LCDCLKPRE = 0;						// CLCDC = CLKIN 
	PERCLKSEL2 |= 0x00000001;		// select ext clk from CH7013 POUT 
	PERCLKCTRL2 &= 0xfffffffe;		// enable CLCDC clock	
	VideoSetBuff(vram1);				// Default video memory
		
	if (bVOut == VOUT_NTSC)
	{		
		LCDTIMING0 = (NTSCHORIZ_BP << 24)+(NTSCHORIZ_FP << 16)+(NTSCHORIZ_SW << 8)+PIXLINE;
		LCDTIMING1 = (NTSCVERT_BP << 24)+(NTSCVERT_FP << 16)+(VERT_SW << 10)+ LINES;
		LCDTIMING2 = 0x04002002 + (639 << 16);
	}
	else if (bVOut == VOUT_PAL)
	{		
		LCDTIMING0 = (PALHORIZ_BP << 24)+(PALHORIZ_FP << 16)+(PALHORIZ_SW << 8)+PIXLINE;
		LCDTIMING1 = (PALVERT_BP << 24)+(PALVERT_FP << 16)+(VERT_SW << 10)+ LINES;
		LCDTIMING2 = 0x04002002 + (639 << 16);
	}
	else if (bVRes == VRES_VGA)
	{		
		LCDTIMING0 = (VGAHORIZ_BP << 24)+(VGAHORIZ_FP << 16)+(VGAHORIZ_SW << 8)+PIXLINE;
		LCDTIMING1 = (VGAVERT_BP << 24)+(VGAVERT_FP << 16)+(VERT_SW << 10)+ LINES;
		LCDTIMING2 = 0x04002002 + (639 << 16);
	}
	else if (bVRes == VRES_SVGA)
	{
		LCDTIMING0 = (VGAHORIZ_BP << 24)+(VGAHORIZ_FP << 16)+(VGAHORIZ_SW << 8)+SVPIXLINE;
		LCDTIMING1 = (VGAVERT_BP << 24)+(VGAVERT_FP << 16)+(SVVERT_SW << 10)+ SVLINES;
		LCDTIMING2 = 0x04002002 + (799 << 16);
	}
	else if (bVRes == VRES_VGATC)
	{
		LCDTIMING0 = (VGAHORIZ_BP << 24)+(VGAHORIZ_FP << 16)+(VGAHORIZ_SW << 8)+PIXLINE;
		LCDTIMING1 = (VGAVERT_BP << 24)+(VGAVERT_FP << 16)+(VERT_SW << 10)+ LINES;
		LCDTIMING2 = 0x04002002 + (639 << 16);
		
	}
	// Start
	if (bVRes != VRES_VGATC)
		LCDCONTROL = 0x00010827;			// TFT, 8 bit/pix, GO !!
	else
		LCDCONTROL = 0x00010929;			// TFT, BGR, 15/16 bit/pix, GO !!
	
	// Return start addresses of video buffers
	*pV1 = (WORD)vram1;
	*pV2 = (WORD)vram2;
}

/*-----------------------------< VideoInitDAC >----------------------------------*/
void VideoInitDAC(BYTE bVRes, BYTE bVOut)
{
	BYTE Dat[3];
	BYTE bReg;

	I2cInitialise(0);
	// Reset
	Dat[0] = 0x0e;
	Dat[1] = 0x0b;
	I2cTalk(I2C_7013,2, 0, Dat);	
	if (bVOut == VOUT_RGB)
	{
			// VGA Mode
			// Reset (VGA) 
			Dat[0] = 0x0e;
			Dat[1] = 0x1b;
			I2cTalk(I2C_7013,2, 0, Dat);
			// Now load DAC regs
			for (bReg=0; bReg < 40; bReg++)
			{	
				Dat[0] = bReg;
				Dat[1] = VGADacRegs[bReg];
				if (Dat[1] != 0xff)
					I2cTalk(I2C_7013,2, 0, Dat);
			} 
			// Special case SVGA - set Pout to 50Mhz
			if (bVRes == VRES_SVGA)
			{
				Dat[0] = 0x14;
				Dat[1] = 63;	// PLL M
				I2cTalk(I2C_7013,2, 0, Dat);
				Dat[0] = 0x15;	
				Dat[1] = 218;	// PLL N
				I2cTalk(I2C_7013,2, 0, Dat);	
			
			}
			// Reg 4 must be done last, don't know why ?
			Dat[0] = 0x04;
			Dat[1] = 0x23;
			I2cTalk(I2C_7013,2, 0, Dat);
			
	}
	else if (bVOut == VOUT_NTSC)
	{
		// NTSC Mode
		// Now load DAC regs
			for (bReg=0; bReg < 40; bReg++)
			{	
				Dat[0] = bReg;
				Dat[1] = NTSCDacRegs[bReg];
				if (Dat[1] != 0xff)
					I2cTalk(I2C_7013,2, 0, Dat);
			}
						
			// Reg 4 must be done last, don't know why ?
			Dat[0] = 0x04;
			Dat[1] = 0x03;
			I2cTalk(I2C_7013,2, 0, Dat); 
	}
	else
	{
		// PAL Mode
		// Now load DAC regs
			for (bReg=0; bReg < 40; bReg++)
			{	
				Dat[0] = bReg;
				Dat[1] = PALDacRegs[bReg];
				if (Dat[1] != 0xff)
					I2cTalk(I2C_7013,2, 0, Dat);
			}
			// Reg 4 must be done last, don't know why ?
			Dat[0] = 0x04;
			Dat[1] = 0x03;
			I2cTalk(I2C_7013,2, 0, Dat); 
	}
}

/*-----------------------------< VideoSelectBuff >---------------------------*/
void VideoSetBuff(PBYTE pBuff)
{
	LCDUPBASE = (WORD)pBuff;	
}

// end of video.c

