//iic.c
#include <windows.h>
#include "dvhw32.h"
#include "ls220.h"
#include "iic.h"
#include "video.h"

#define HW_ASM

#define G_SC		0x200L		// Chrontel uses GPIO(1) as SC
#define G_SD		0x400L		// Chrontel uses GPIO(2) as SD
#define	G_EN		0x60000L	// Enable bit 1 and 2

BYTE BT865_NTSC[4][18] = {
	{0x00,0x60,0x0f,0x0f,0x00,0x00,0xfc,0x03,0xb9,0x6d,
		0xb6,0x95,0xb0,0x72,0x0d,0xff,0x2c,0xd0},
	{0x36,0x60,0x0f,0x0f,0x00,0x00,0xfc,0x03,0xb9,0x6d,
		0xb6,0x95,0xb0,0x72,0x0d,0xff,0x2c,0xd0},
	{0x3e,0x60,0x0f,0x0f,0x00,0x00,0xfc,0x03,0xb9,0x6d,
		0x3c,0x91,0x32,0xd2,0x0d,0xff,0x2c,0xd0},
	{0x3e,0x60,0x0f,0x0f,0x00,0x00,0xfc,0x03,0xb9,0x6d,
		0xb6,0x95,0xb0,0x72,0x0d,0xff,0x2c,0xd0}
};

BYTE BT865_PAL[4][18] =  {
	{0x00,0x60,0x7e,0xfe,0x54,0x01,0xff,0x01,0xd5,0x73,
		0xa8,0x22,0x55,0xa4,0x05,0x55,0x27,0x40},
	{0x36,0x60,0x7e,0xfe,0x54,0x01,0xff,0x01,0xd5,0x73,
		0xa8,0x22,0x55,0xa4,0x05,0x55,0x27,0x40},
	{0x36,0x60,0x7e,0xfe,0x54,0x01,0xff,0x01,0xd5,0x73,
		0xa8,0x22,0x55,0xa4,0x05,0x55,0x27,0x40},
	{0x36,0x60,0x7e,0xfe,0x54,0x01,0xff,0x01,0xd5,0x73,
		0xa8,0x22,0x55,0xa4,0x05,0x55,0x27,0x40}
};

BYTE CS4953_NTSC[4][20] = {
	{0x00,0x17,0x15,0x21,0x15,0xb7,0x1b,0x1b,0x24,0x0f,
		0x78,0x00,0x00,0x0f,0x0f,0x60,0x07,0xa0,0x2c,0xff},
	{0x36,0x17,0x15,0x21,0x15,0xb7,0x1b,0x1b,0x24,0x0f,
		0x78,0x00,0x00,0x0f,0x0f,0x60,0x07,0xbf,0x1a,0xf0},
	{0x3e,0x1d,0x11,0x25,0x11,0x3c,0x1b,0x1b,0x24,0x0f,
		0x78,0x00,0x00,0x0f,0x0f,0x60,0x07,0xa0,0x2c,0xff},
	{0x3e,0x17,0x15,0x21,0x15,0xb6,0x1b,0x1b,0x24,0x0f,
		0x78,0x00,0x00,0x0f,0x0f,0x60,0x07,0xa0,0x2c,0xff}

};

BYTE CS4953_PAL[4][20] = {
	{0x00,0x1a,0x22,0x34,0x22,0xa8,0x1c,0x3d,0x14,0x07,
		0x7e,0x03,0x24,0xfe,0x7e,0x60,0x02,0x40,0x27,0x55},
	{0x36,0x1a,0x22,0x34,0x22,0xa8,0x1c,0x3d,0x14,0x07,
		0x7e,0x02,0x54,0xfe,0x7e,0x60,0x02,0x40,0x27,0x55},
	{0x36,0x1a,0x22,0x34,0x22,0xa8,0x1c,0x3d,0x14,0x07,
		0x7e,0x02,0x54,0xfe,0x7e,0x60,0x02,0x40,0x27,0x55},
	{0x36,0x1a,0x22,0x34,0x22,0xa8,0x1c,0x3d,0x14,0x07,
		0x7e,0x02,0x54,0xfe,0x7e,0x60,0x02,0x40,0x27,0x55}

};

BYTE AD7175_NTSC[4][17] = {
	{0xc0,0x45,0x85,0x54,0xfb,0xb6,0x91,0xf8,0x07,0x00,0xc0,0xc3,0x03,
	 0x58,0x85,0xca,0xff}, 

	{0x76,0x07,0x95,0x50,0xce,0xb6,0x91,0xf8,0x07,0x00,0xc0,0xc3,0x03,
	 0x58,0x85,0xca,0xff}, 

	{0x7e,0x07,0x95,0x50,0xce,0xb6,0x91,0xf8,0x07,0x00,0xc0,0xc3,0x03,
	 0x58,0x85,0xca,0xff}, 

	{0xfe,0x45,0x85,0x54,0xeb,0xb6,0x91,0xf8,0x07,0x00,0xc0,0xc3,0x03,
	 0x58,0x85,0xca,0xff} 

};

// The table is not available, except for AD7175_PAL[0]

BYTE AD7175_PAL[4][17] = {

	{0x80,0x16,0xaa,0x61,0x05,0xd7,0x53,0xfe,0x03,0xaa,0x80,0xbf,0x1f,
	 0x18,0x04,0x7a,0x55}, 

	{0xb6,0x16,0xaa,0x61,0x05,0xd7,0x53,0xfe,0x03,0xaa,0x80,0xbf,0x1f,
	 0x18,0x04,0x7a,0x55}, 

	{0xb6,0x16,0xaa,0x61,0x05,0xd7,0x53,0xfe,0x03,0xaa,0x80,0xbf,0x1f,
	 0x18,0x04,0x7a,0x55}, 

	{0xb6,0x16,0xaa,0x61,0x05,0xd7,0x53,0xfe,0x03,0xaa,0x80,0xbf,0x1f,
	 0x18,0x04,0x7a,0x55}

};

// SAA7120

BYTE SAA7120_SADDR[27] = { 0x5d,0x5e,0x5f,0x60,0x7d,
						0x01,0x03,0x04,0x05,0x06,
						0x07,0x08,0x10,0x11,0x12,
						0x14,0x15,0x20,0x21,0x24,
						0x25,0x30,0x31,0x33,0x34,
						0x36,0x37 };

BYTE SAA7120_NTSCi[4][27] = {
	{0x2a,0x2e,0x2e,0x20,0x00,0x18,0x15,0x22,0x0a,0xc5,0xff,0x03,0x15,0xad,0x60,0x0f,0x78,0x9b,
	0x04,0x00,0x00,0x1b,0x04,0x0f,0x0f,0x0f,0x0f},

	{0x0b,0x0e,0x2e,0x20,0xd0,0x18,0x15,0x22,0x0a,0xc5,0xff,0x03,0x15,0xad,0x60,0x0f,0x78,0x9b,
	0x04,0x00,0x00,0x1b,0x04,0x0f,0x0f,0x0f,0x0f},

	{0x0b,0x0e,0x2e,0x20,0xf0,0x1e,0x11,0x26,0x0a,0xc5,0xff,0x03,0x11,0xad,0x60,0x0f,0x78,0x9b,
	0x04,0x00,0x00,0x1b,0x04,0x0f,0x0f,0x0f,0x0f},

	{0x0b,0x0e,0x2e,0x20,0xf0,0x18,0x15,0x22,0x0a,0xc5,0xff,0x03,0x15,0xad,0x60,0x0f,0x78,0x9b,
	0x04,0x00,0x00,0x1b,0x04,0x0f,0x0f,0x0f,0x0f}
};

BYTE SAA7120_PALi[2][27] = {
	{0x23,0x35,0x35,0x21,0x00,0x1b,0x22,0x2b,0x08,0x74,0x55,0x01,0x22,0x15,0x60,0x07,0x7e,0xbb,
	0x72,0x02,0x54,0x2c,0x04,0xfe,0xfe,0x7e,0x7e},

	{0x0b,0x1b,0x35,0x21,0xd0,0x1b,0x22,0x2b,0x08,0x74,0x55,0x01,0x22,0x15,0x60,0x07,0x7e,0xbb,
	0x72,0x02,0x54,0x2c,0x04,0xfe,0xfe,0x7e,0x7e},
};

// HS8171

BYTE HS8171_SADDR[19] = { 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2f,0x72,0x73,0x74,0x75,
							0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d };

BYTE HS8171_NTSCi[4][19] = {
	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0 },
	{ 0x36, 0x1d, 0x91, 0x45, 0x73, 0x6c, 0x1b, 0x24, 0x7, 0xf8, 0x0, 0x0, 0xf, 0xf,
	0x60, 0x15, 0x50, 0xfc, 0x1f },
	{ 0x3e, 0x1d, 0x91, 0x45, 0x73, 0x6c, 0x1b, 0x24, 0x7, 0xf8, 0x0, 0x0, 0xf, 0xf, 
	0x60, 0x15, 0x50, 0xfc, 0x1f },
	{ 0x3e, 0x17, 0x95, 0x51, 0x5b, 0x6e, 0x1b, 0x24, 0x7, 0xf8, 0x0, 0x0, 0xf, 0xf,
	0x60, 0x15, 0x50, 0xfc, 0x1f }
};

BYTE HS8171_PALi[19] = {
	0x36, 0x5a, 0xa2, 0x8a, 0x2a, 0x70, 0x3d, 0x14, 0x3, 0xfe, 0x1, 0x54, 0xfe, 0x7e,
	0x60, 0x10, 0x40, 0x57, 0x15
};

BYTE AGC_RAMP_NTSC[16] = { 0x20,0x27,0x2d,0x33,0x39,0x3f,0x45,0x4b,0x51,0x57,	// load into 0x60
					0x5d,0x63,0x69,0x6f,0x75,0x7c };

BYTE AGC_RAMP_PAL[16] = { 0x21,0x27,0x2d,0x33,0x39,0x3f,0x45,0x4b,0x51,0x57,
					0x5d,0x63,0x69,0x6f,0x75,0x7b };

BYTE PULSATION_MODE[2][2] = { { 0x7a,0x52 }, { 0x72,0x2d } };	// { State A ( reg 21 , reg 60 ) } , { State B ( reg 21 , reg 60 ) } 

BYTE OSD_row10[]={41,1,0,40,0xc0,5};

extern BYTE eprom[16];

#ifdef DBG
	extern ULONG DbgPrint(PCH pchFormat, ...);
#endif

extern VOID KeStallExecutionProcessor(IN ULONG MicroSeconds);

//////////////////////////////////////////////////////////////////////////

void gpio_startcode()
{
DWORD tmp;

	tmp = DVReadReg(0x350)&0xff000000L|G_EN;
	DVWriteREG(0x350, tmp | G_SC|G_SD);	// SC(H) and SD(H)
	KeStallExecutionProcessor(100);

	DVWriteREG(0x350, tmp | G_SC);	// SC(H) and SD(L)
	KeStallExecutionProcessor(100);

	DVWriteREG(0x350, tmp);	
	KeStallExecutionProcessor(100);
}

//////////////////////////////////////////////////////////////////////////

void gpio_stopcode()
{
DWORD tmp;
	tmp = DVReadReg(0x350)&0xff000000L|G_EN;
	DVWriteREG(0x350, tmp);		// SC(L) and SD(L)
	KeStallExecutionProcessor(10);

	DVWriteREG(0x350, tmp|G_SC);// set SC(H) & SD(L)
	KeStallExecutionProcessor(10);

	DVWriteREG(0x350, tmp);		// SC(L) and SD(L)
	KeStallExecutionProcessor(10);

	DVWriteREG(0x350, tmp|G_SC);// set SC(H) & SD(L)
	KeStallExecutionProcessor(10);

	DVWriteREG(0x350, tmp|G_SC|G_SD);	// SC(H) & SD(H)
}

//////////////////////////////////////////////////////////////////////////

void gpio_addr(BYTE addr)
{
DWORD tmp;
BYTE	bit_mask;
int i=0;

	bit_mask = 0x4;

	tmp = DVReadReg(0x350) & 0xff000000L|G_EN;
	for(i=0;i<3;i++) 
	{
		if (addr & (bit_mask >> i))	
		{	
			DVWriteREG(0x350, tmp|G_SD);// set SD(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SC|G_SD);// set SC(H) & SD(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SD);// set SD(H)
			KeStallExecutionProcessor(10);
		} 
		else 
		{
			DVWriteREG(0x350, tmp);
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SC);// set SC(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp);
			KeStallExecutionProcessor(10);
		}
	}
	DVWriteREG(0x350, tmp);
	KeStallExecutionProcessor(10);
	DVWriteREG(0x350, tmp|G_SC);// set SC(H)
	KeStallExecutionProcessor(10);
	DVWriteREG(0x350, tmp);
	KeStallExecutionProcessor(10);
}

//////////////////////////////////////////////////////////////////////////

void gpio_data(BYTE data)
{
DWORD tmp;
BYTE	bit_mask;
int i;

	bit_mask = 0x8;

	tmp = DVReadReg(0x350) & 0xff0000L|G_EN;
	for(i=0;i<4;i++) 
	{
		if (data & (bit_mask >> i))	
		{
			DVWriteREG(0x350, tmp|G_SD);// set SD(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SC|G_SD);// set SC(H) & SD(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SD);// set SD(H)
			KeStallExecutionProcessor(10);
		} 
		else 
		{
			DVWriteREG(0x350, tmp);
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp|G_SC);// set SC(H)
			KeStallExecutionProcessor(10);
			DVWriteREG(0x350, tmp);
			KeStallExecutionProcessor(10);
		}
	}
}

//////////////////////////////////////////////////////////////////////////

void send_gpio(BYTE addr,BYTE data)
{
	gpio_startcode();
	gpio_addr(addr);
	gpio_data(data);
	gpio_stopcode();
}

//////////////////////////////////////////////////////////////////////////

void iic_delay()
{
int i;
#ifdef OLD
	Sleep(2);
#else

	
	for (i = 0; i < 200 ; i++ )
	{
	#ifdef HW_ASM
		_asm {
			push eax
			push ebx
			imul ebx,eax
			pop	ebx
			pop	eax
		}
	#else
		KeStallExecutionProcessor(10);
	#endif
	}
	

#endif
}

//////////////////////////////////////////////////////////////////////////

void iic_init()
{
	if (!eprom[EPROM_BOARDTYPE])
//		DVWriteREG(0x350,0x4ff0100L);
		DVWriteREG(0x350,0x4f70100L);
	else
//		DVWriteREG(0x350,0x4ff0f00L);
		DVWriteREG(0x350,0x4f70f00L);

	DVWriteREG(0x364,0xff031fL);

}

//////////////////////////////////////////////////////////////////////////
 
void iic_startcode()
{
DWORD tmp;

	tmp = DVReadReg(0x350) & 0x3fffffL;
	DVWriteREG(0x350, tmp);				// both = 1
	iic_delay();

	DVWriteREG(0x350, tmp | 0x400000L);	// SDA = 0
	
	iic_delay();

	DVWriteREG(0x350, tmp | 0xc00000L);	// SCL = 0
	iic_delay();
}

//////////////////////////////////////////////////////////////////////////

void iic_dataxfer(BYTE val)
{
DWORD tmp;
BYTE  data;
int   i;

	data = ~val;
	for(i=0;i<8;i++) 
	{
		tmp = DVReadReg(0x350) & 0xbfffffL;
		tmp |= (DWORD)((data >> (7-i)) & 0x1) << 22; // set SDA
		DVWriteREG(0x350, tmp);
		iic_delay();
		tmp = DVReadReg(0x350);
		DVWriteREG(0x350, tmp & 0x7fffffL);// set SCL = 1
		iic_delay();
		DVWriteREG(0x350, tmp | 0x800000L);// set SCL = 0
		iic_delay();
	}
}

//////////////////////////////////////////////////////////////////////////

BOOL iic_ack()
{
DWORD tmp,ack;

	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp & 0xbfffffL);	// disable SDA = 1
	iic_delay();
	ack = DVReadReg(0x350) & 0x40;
	DVWriteREG(0x350, tmp & 0x3fffffL);	// SCL = 1
	iic_delay();
	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp | 0x800000L);// set SCL = 0
	iic_delay();

	if (!ack)
		return TRUE;
	else
		return FALSE;
}

//////////////////////////////////////////////////////////////////////////

void iic_endcode()
{
DWORD tmp;

	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp | 0x400000L);	// SDA = 0
	iic_delay();
	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp & 0x7fffffL); // set SCL = 1
	iic_delay();
	DVWriteREG(0x350, tmp & 0x3fffffL);	// SDA = 1
	iic_delay();
}

//////////////////////////////////////////////////////////////////////////

BYTE iic_dataget()
{
BYTE val,i;
DWORD tmp;

	val = 0;
	for(i=0;i<8;i++) 
	{
		iic_delay();
		tmp = DVReadReg(0x350);
		val <<= 1;
		if (tmp & 0x40)
			val = val | 0x1;

		tmp = tmp & 0x3fffffL;
		DVWriteREG(0x350, tmp);// set SCL = 1
		iic_delay();
		DVWriteREG(0x350, tmp | 0x800000L);// set SCL = 0
		iic_delay();
	}

	return val;
}

//////////////////////////////////////////////////////////////////////////

void send_ack()
{
DWORD tmp;

	tmp = DVReadReg(0x350);
	tmp = tmp | 0xc00000L;		//    SCLK SDA
	DVWriteREG(0x350, tmp);		// set  00
	iic_delay();
	tmp = tmp & 0x7fffffL;
	DVWriteREG(0x350, tmp);		// set	10
	iic_delay();
	tmp = tmp | 0xc00000L;
	DVWriteREG(0x350, tmp);		// set  00
	iic_delay();
	tmp = tmp & 0xb00000L;
	DVWriteREG(0x350, tmp);		// set  01
	iic_delay();
}

//////////////////////////////////////////////////////////////////////////

BOOL i2c_readeprom(BYTE addr, BYTE subaddr, BYTE num,BYTE *pb)
{
BYTE val;
int i;

	iic_startcode();
	iic_dataxfer(addr);			// write command
	iic_ack();
	iic_dataxfer(subaddr);	
	iic_ack();
	iic_startcode();
	iic_dataxfer((BYTE)(addr|0x1));		// read command
	iic_ack();

	for(i=0;i<num;i++) 
	{
		pb[i] = iic_dataget();	// load array here
		if (i < (num-1))
			send_ack();
		else
			iic_endcode();
	}	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////

BOOL detect_i2c(BYTE addr)
{
BOOL	val;

	iic_startcode();
	iic_dataxfer(addr);			// write command
	val = iic_ack();
	iic_endcode();
	return val;
}

//////////////////////////////////////////////////////////////////////////

BOOL read_i2c(BYTE addr)
{
DWORD	tmp,val;
DWORD	dwcnt=0;

	val =0xff;
	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp | 0x4000000);	// set bit 26=1	
	iic_delay();
	DVWriteREG(0x354, addr<<24|0x1000000L);
	iic_delay();

	while(!(DVReadReg(0x368)&0x1000))
	{
		iic_delay();
		if(dwcnt++ > 0xffff)
			break;
	}
	val=(BYTE)DVReadReg(0x36c);
	DVWriteREG(0x350, tmp);
	iic_delay();
	return val;
}

//////////////////////////////////////////////////////////////////////////

BYTE detect_i2c_device()
{
	BYTE	id,type;

	iic_startcode();
	iic_endcode();
	send_i2c(0x00,0x0f,0x40);
	

	if (detect_i2c(0x80)) 
	{
		i2c_readeprom(0x80,0x3d,1,&id);
		if (id & 0xf0)
			type = CS4953;
		else
			type = CS4952;
		return type;
	}

	if (detect_i2c(0x8a)) 
	{	// BT865 family
		id = read_i2c(0x8a);
		if (((id>>5)&7) == 5)
			type = BT865;
		else
			type = BT864;
		return type;
	}
	
	if (detect_i2c(0x42)) 
	{
		i2c_readeprom(0x42,0x0,1,&id);
		if ( id & 0xf )
			type = HS8171;
		else
			type = HS8170;	// non-MV7
		return type;
	}
	
	if (detect_i2c(0x8c))	
	{	// SAA7120 family	
		type = SAA7120;
		return type;
	} 
	
	if (detect_i2c(0xd4)) 
	{
		type = AD7175;
		return type;
	}
	
	if (detect_i2c(0x54)) 
	{
		type = AD7176;
		return type;
	}
	
	type = 0xff;

	return type;
}

//////////////////////////////////////////////////////////////////////////

void send_i2c(BYTE addr,BYTE subadr,BYTE data)
{

#ifdef	OLD
	iic_startcode();
	iic_dataxfer(addr);
	iic_ack();
	iic_dataxfer(subadr);
	iic_ack();
	iic_dataxfer(data);
	iic_ack();
	iic_endcode();
#endif
DWORD	val,tmp;

	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp | 0x4000000);	// set bit 26=1	

	val = ((DWORD)addr)<< 24| ((DWORD)subadr)<<16|((DWORD)data)<<8;
	DVWriteREG(0x358, val);
	KeStallExecutionProcessor(500);
	DVWriteREG(0x350,tmp);
}

//////////////////////////////////////////////////////////////////////////

void set_macrovision(BYTE tvencoder,BYTE mode,BYTE aps_mode)
{
BYTE	saddr;
BYTE * bptr;
int	i;
	
	switch(tvencoder) 
	{
		case BT865:
			saddr = 0xd8;
			if (mode == NTSC_VIDEO)
				bptr = BT865_NTSC[aps_mode];
			else
				bptr = BT865_PAL[aps_mode];
			for(i=0;i<18;i++) 
			{
				send_i2c(0x8a,saddr,*bptr++);
				saddr += 2;
			}
			break;
	
		case BT864:
			if (aps_mode)
				send_i2c(0x8a,0xce,0x12); // S-VIDEO & COMP w color bar
			else
				send_i2c(0x8a,0xce,0x2); // S-VIDEO & COMP
			break;

		case CS4953:
			saddr = 0x20;
			if (mode == NTSC_VIDEO)
				bptr = CS4953_NTSC[aps_mode];
			else
				bptr = CS4953_PAL[aps_mode];
			for(i=0;i<20;i++) 
			{
				send_i2c(0x80,saddr,*bptr++);
				saddr++;
			}
			break;

		case CS4952:
			if (aps_mode)
				send_i2c(0x80,0x1,0x6);	// S-VIDEO & COMP with color bar
			else
				send_i2c(0x80,0x1,0x4);	// S-VIDEO & COMP
			break;

		case AD7175:
			saddr = 0x13;
			if (mode == NTSC_VIDEO)
				bptr = AD7175_NTSC[aps_mode];
			else
				bptr = AD7175_PAL[aps_mode];
			for(i=0;i<17;i++) 
			{
				send_i2c(0xd4,saddr,*bptr++);
				saddr ++;
			}
			break;

		case AD7176:
			if (aps_mode)
				send_i2c(0x54,1,0x80);
			else
				send_i2c(0x54,1,0x00);
			break;
	
		case SAA7120:
			if (mode == NTSC_VIDEO)
				bptr = SAA7120_NTSCi[aps_mode];
			else
			{
				if ( aps_mode > 1 )
					aps_mode = 1;

				bptr = SAA7120_PALi[aps_mode];
			}

			for(i=0;i<27;i++) 
			{
				send_i2c(0x8c,SAA7120_SADDR[i],*bptr++);
			}
			break;

		case SAA7121:
			if (aps_mode)
				send_i2c(0x8c,0x3a,0x83);
			else
				send_i2c(0x8c,0x3a,0x3);
			break;

		case HS8171:
			if ( mode == NTSC_VIDEO )
			{
				bptr = HS8171_NTSCi[aps_mode];
			}
			else
			{
				bptr = HS8171_PALi;
			}
			for (i=0;i<19;i++)
			{
				send_i2c(0x42,HS8171_SADDR[i],*bptr++);
			}
			break;
	
		case HS8170:
			if (aps_mode)
				send_i2c(0x42,0x2,0xe0);
			else
				send_i2c(0x42,0x2,0x20);
			break;

	}
}

///////////////////////////////////////////////////////////////////////////////////

void send_i2cOSD(BYTE addr,BYTE row,BYTE col,BYTE data)
{
DWORD	val,tmp;

	tmp = DVReadReg(0x350);
	DVWriteREG(0x350, tmp | 0x4000000);	// set bit 26=1	

	val = ((DWORD)addr)<< 24| ((DWORD)row)<<16|((DWORD)col)<<8 | (DWORD)data;
	
	DVWriteREG(0x35c, val);

	KeStallExecutionProcessor(50);
	
	DVWriteREG(0x350,tmp);
}

///////////////////////////////////////////////////////////////////////////////////

BYTE detect_osd_device()
{
BYTE	id,type;

	iic_startcode();
	iic_endcode();
	send_i2c(0x00,0x0f,0x40);
	
	if (detect_i2c(0x7a)) 
	{
		return 0x7a;
	}

	return 0xff;
}

///////////////////////////////////////////////////////////////////////////////////

void OSDInit(BYTE addr)
{
BYTE	row, col,colstart=12, colend=17;

	// clear display register
	send_i2cOSD((BYTE)addr,(BYTE)0x8a,(BYTE)16,(BYTE)0x2);		// CTRL
	for(col=colstart;col<=colend;col++)
	  send_i2cOSD((BYTE)addr,(BYTE)0x8a,(BYTE)col,(BYTE)OSD_row10[col-colstart]);

	// Initialize color attribute for each row
	for(row=0;row<=9;row++)
	{
	  send_i2cOSD((BYTE)addr,(BYTE)(0x80+row),(BYTE)28,(BYTE)0x8a);
	  send_i2cOSD((BYTE)addr,(BYTE)(0x80+row),(BYTE)29,(BYTE)0x3c);
	}

}

///////////////////////////////////////////////////////////////////////////////////

void OSDExit(BYTE addr)
{
	send_i2cOSD((BYTE)addr,(BYTE)0x8a,(BYTE)0x10,(BYTE)0x2);
}
