This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

using Off-Chip HDMI sii9134(9034)

HI

i have custom B/D and  testing Off-Chip HDMI1 port output .

i changed sii9922a to sii9134(sii9034 compatible) chip  . because we can't received sii9022a chip from local FAE.

i setted silicon image hdmi transmitter to the "1080p 422 embedded sync signal".

but i can't see anything. 

Pls is there any check point?

any advice will be appreciated. 

i attached my driver.

/*
*
* Silicon Image SIL9034 HDMI driver.
*
*
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/poll.h>
#include <linux/workqueue.h>

#include <linux/mm.h>

#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>



#include "sii9034hdmi.h" /* Silicon Image 9034 register definition */

#if 1
	#define sil9034_dbg(fmt, arg...) \
		printk(KERN_INFO "%s:%d> " fmt, __func__, __LINE__ , ## arg)
#else
	#define sil9034_dbg(fmt, arg...)
#endif
  
 #define I2C_RETRY_SLEEP 200 
 #define I2C_RETRY_COUNT 3
 
#define MOD_DESC "Sil9034 HDMI Driver"
/* Si9034 use 2 i2c to control the chip 0x39 & 0x3A */
#define SLAVE_SIZE 2
#define TIMER_JIFFIES   (1 * HZ)

/* Timer only could cause the kernel busy, we push it into schedule */
#define SIL9034_TIMER 1
#define SIL9034_SCHED 1

/* Silicon Image provide 2 slave address to control. */
static int slave_num = 0 ;

static unsigned short normal_i2c[] = {
	TX_SLV0, TX_SLV1, I2C_CLIENT_END
};

/* Macro need by addr_data */
I2C_CLIENT_INSMOD;

/* video mapping struct */
typedef struct sil9034_video_mapping
{
	u8 video_reg ;
	u16 value ;
} sil9034_video_mapping ;

/* video mapping for 480p YCbCr 4:2:2 Separate Sync Input*/
sil9034_video_mapping sil9034_480p_setting[] =
{
	{DE_CTRL_ADDR,(DE_GEN_ENABLE|0x70)},
	{DE_DELAY_ADDR,0x7A},
	{DE_TOP_ADDR,0x24},
	{DE_CNTH_ADDR,0x2},
	{DE_CNTL_ADDR,0xD0},
	{DEL_H_ADDR,0x1},
	{DEL_L_ADDR,0xE0},
	{TX_VID_CTRL_ADDR,CSCSEL_BT709|SET_EXTN_12BIT},
	{TX_VID_MODE_ADDR,UPSMP_ENABLE|CSC_ENABLE},
	{0,0}
};

/* video mapping for 720p YCbCr 4:2:2 Separate Sync Input*/
sil9034_video_mapping sil9034_720p_422_sepsync_setting[] =
{
	{DE_CTRL_ADDR,(DE_GEN_ENABLE|0x1)},
	{DE_DELAY_ADDR,0x04},
	{DE_TOP_ADDR,0x19},
	{DE_CNTH_ADDR,0x5},
	{DE_CNTL_ADDR,0x00},
	{DEL_H_ADDR,0x2},
	{DEL_L_ADDR,0xD0},
	{TX_VID_CTRL_ADDR,CSCSEL_BT709|SET_EXTN_12BIT},
	//{TX_VID_MODE_ADDR,UPSMP_ENABLE|CSC_ENABLE},
	{TX_VID_MODE_ADDR, 0}, // kisung cho change
	{0,0}
};

/* video mapping for 720p YCbCr 4:2:2 Embedded Sync Input*/
sil9034_video_mapping sil9034_720p_422_embsync_setting[] =
{
	{DE_CTRL_ADDR,0x0},
	{DE_DELAY_ADDR,0x0},
	{DE_TOP_ADDR,0x0},
	{DE_CNTH_ADDR,0x0},
	{DE_CNTL_ADDR,0x0},
	{DEL_H_ADDR,0x0},
	{DEL_L_ADDR,0x0},
	{HBIT_TO_HSYNC_ADDR1,0x6E},
	{HBIT_TO_HSYNC_ADDR2,0x0},
	{HLENGTH1_ADDR,0x28},
	{HLENGTH2_ADDR,0x0},
	{VBIT_TO_VSYNC_ADDR,0x05},
	{VLENGTH_ADDR,0x05},
	{TX_VID_CTRL_ADDR,SET_EXTN_12BIT},
	{TX_VID_MODE_ADDR,SYNCEXT_ENABLE},
	{0,0}
};

/* video mapping for 1080i YCbCr 4:2:2 Separate Sync Input*/
sil9034_video_mapping sil9034_1080i_422_sepsync_setting[] =
{
	{DE_CTRL_ADDR,(DE_GEN_ENABLE|0x0)},
	{DE_DELAY_ADDR,0xC0},
	{DE_TOP_ADDR,0x14},
	{DE_CNTH_ADDR,0x07},
	{DE_CNTL_ADDR,0x80},
	{DEL_H_ADDR,0x2},
	{DEL_L_ADDR,0x1C},
	{TX_VID_CTRL_ADDR,CSCSEL_BT709|SET_EXTN_12BIT},
	{TX_VID_MODE_ADDR,UPSMP_ENABLE|CSC_ENABLE},
	{0,0}
};

/* video mapping for 1080P YCbCr 4:2:2 Embedded Sync Input*/
sil9034_video_mapping sil9034_1080p_422_embsync_setting[] =
{
	{DE_CTRL_ADDR,(DE_GEN_ENABLE|0x0)},
	{DE_DELAY_ADDR,0xC0},
	{DE_TOP_ADDR,0x29},
	{DE_CNTH_ADDR,0x07},
	{DE_CNTL_ADDR,0x80},
	{DEL_H_ADDR,0x4},
	{DEL_L_ADDR,0x38},
	{TX_VID_CTRL_ADDR,SET_EXTN_12BIT},
	{TX_VID_MODE_ADDR,0},
	{0,0}
};


/* i2c private data */
typedef struct davinci6446_sil9034
{
	struct i2c_client* sil9034_client[SLAVE_SIZE] ;
	#ifdef SIL9034_SCHED
	struct work_struct      work;
	#endif
	#ifdef SIL9034_TIMER
	struct timer_list timer ;
	#endif
	spinlock_t              lock;
	/* pointer to different setting according to system */
	sil9034_video_mapping *sil9034_setting ;
	unsigned char work_flag ;
	unsigned char auth_state ;
	u8 an_ksv_data[8] ;
	char r0rx[2] ;
	char r0tx[2] ;

} davinci6446_sil9034 ;

static davinci6446_sil9034 ds ;

static int sii9034_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct i2c_client *pclient;
        printk("[%s]enter\n", __func__);
	if (!(pclient = kzalloc(sizeof(*client), GFP_KERNEL)))
	{
		sil9034_dbg("ERROR error returned from kzalloc");
		return  -ENOMEM;
	}

	memcpy(pclient, client, sizeof(struct i2c_client));
	ds.sil9034_client[slave_num] = pclient;
	slave_num++;
        printk("[%s]leave\n", __func__);
	return 0;
}

static int sii9034_remove(struct i2c_client *client)
{
        printk("[%s]enter\n", __func__);

        printk("[%s]leave\n", __func__);
        return 0;
}

static int sii9034_detect(struct i2c_client *client, struct i2c_board_info *info)
{

        struct i2c_adapter *adapter = client->adapter;

        printk("[%s]enter\n", __func__);
	/* Jchen: i use a little trick here to make it register 2 i2c in 1 driver */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
	{
		sil9034_dbg("ERROR returned from i2c_check_functionality");
		return -1;
	} 
        printk( "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name);
        strlcpy(info->type, "sii9034", I2C_NAME_SIZE);
        printk("[%s]leave\n", __func__);
	return 0;
}

static const struct i2c_device_id sii9034_id[] = {
        { "sii9034", 0 },
        { }
};
MODULE_DEVICE_TABLE(i2c, sii9034_id);



static struct i2c_driver sil9034_driver = {
	.class = I2C_CLASS_HWMON,
	.driver     = {
		.owner          = THIS_MODULE,
		.name           = "SIL9034 HDMI Driver",
	},
        .probe = sii9034_probe,
        .remove = sii9034_remove,
        .detect = sii9034_detect,
	
	//.attach_adapter = &sil9034_attach_adapter,
	//.detach_client  = &sil9034_detach_client,
	.id_table       = sii9034_id, /*define in i2c-id.h */
	.address_list	= normal_i2c,
};

static const char * pname = "SIL9034 HDMI Driver" ;

#if 0
static int sil9034_detect_client(struct i2c_adapter * adapter, int address, int kind)
{
	int ret = 0;
	struct i2c_client* client = NULL;

	/* Jchen: i use a little trick here to make it register 2 i2c in 1 driver */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
	{
		sil9034_dbg("ERROR returned from i2c_check_functionality");
		ret = -1;
		goto out;
	} 

	if (!(client = kzalloc(sizeof(*client), GFP_KERNEL)))
	{
		sil9034_dbg("ERROR error returned from kzalloc");
		ret = -ENOMEM;
		goto out;
	}

	memset(client, 0, sizeof(struct i2c_client));

	client->addr = address;
	client->adapter = adapter;
	client->driver = &sil9034_driver;
	/* Jchen: it seem like ten bit probe doesn't support here, but we don't need
	 * it, since we know that the i2c address is fix in embedded.
	 * client->flags = I2C_M_IGNORE_NAK|I2C_M_TEN;
	 */
	client->flags = I2C_M_IGNORE_NAK;

	strcpy(client->name, "sil9034");

	/* JChen: i use force mode, no need this */
	if ((ret = i2c_attach_client(client)) != 0)
	{
		sil9034_dbg("%s Unable to attach client.\n", pname);
		kfree(client);
		ret = -1;
		goto out;
	} 
	ds.sil9034_client[slave_num++] = client;

out:
	return ret;
 }
 
static int sil9034_attach_adapter(struct i2c_adapter * adapter)
{
         /* JChen : force to support 10-bit address, i2c-core need to
          * fix to follow the linux i2c game.
         sil9034_detect_client(adapter,TX_SLV0,I2C_DRIVERID_SIL9034) ;
         sil9034_detect_client(adapter,TX_SLV1,I2C_DRIVERID_SIL9034) ;
          */
         return(i2c_probe(adapter, &addr_data, &sil9034_detect_client));
}

static int sil9034_detach_client(struct i2c_client * client)
{
         int ret = 0;
 
         if ((ret = i2c_detach_client(client)) != 0)
         {
                 sil9034_dbg("%s Unable to detach client.\n", pname);
                 goto out;
         }
 
#if SIL9034_TIMER
	 del_timer_sync(&ds.timer);
#endif
#if SIL9034_SCHED
	 flush_scheduled_work();
#endif
	 kfree(client);

out:
	 return ret;
}

#endif
 
static int sil9034_write(davinci6446_sil9034 *priv,u8 slave,u8 reg, u16 value)
{
	int retry = I2C_RETRY_COUNT;
	struct i2c_client* client;
	int ret = -1;
	if(slave > 1) {
		printk("[%s]ERROR slave index :%d\n", __func__, slave);
		return -1;
	}
        client = priv->sil9034_client[slave];


	if(!client) return 0xff;

	while(retry--)
	{
		ret = i2c_smbus_write_byte_data(client, reg, value);
		if (-1 != ret) break;
		printk("sil9034_write retry [%d]\n", retry);
		mdelay(I2C_RETRY_SLEEP);
	}
	return ret;
}

/* JChen: this should be call by others driver or 
 * create new char dev to ioctl the control.
 */
EXPORT_SYMBOL(sil9034_write);
  
static int sil9034_read(davinci6446_sil9034 *priv,u8 slave,u8 reg)
{
	int retry = I2C_RETRY_COUNT;
	int dat;
        struct i2c_client* client;
	if(slave > 1) {
		printk("[%s]ERROR slave index :%d\n", __func__, slave);
		return -1;
	}
        client = priv->sil9034_client[slave];
	if(!client) return 0xff;

	while(retry--)
	{
		dat = i2c_smbus_read_byte_data(priv->sil9034_client[slave], reg);
		if (-1 != dat) break;
		printk("(sil9034_read) retry [%d]\n", retry);
		mdelay(I2C_RETRY_SLEEP);
	}
	return dat;
}
EXPORT_SYMBOL(sil9034_read);

static char *sil9034_ddc_write(davinci6446_sil9034 *priv,u8 *value,u8 reg, u8 length)
{
	u8 count = 0 ;

	while(sil9034_read(priv,SLAVE0,DDC_STATUS_ADDR)&BIT_MDDC_ST_IN_PROGR)
		mdelay(10) ;

	sil9034_write(priv,SLAVE0,DDC_ADDR,HDCP_RX_SLAVE) ;
	sil9034_write(priv,SLAVE0,DDC_OFFSET_ADDR,reg) ;
	sil9034_write(priv,SLAVE0,DDC_CNT1_ADDR,length) ;
	sil9034_write(priv,SLAVE0,DDC_CNT2_ADDR,0) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_CLEAR_FIFO) ;

	for(count=0 ;count < length ; count++)
	{
		sil9034_write(priv,SLAVE0,DDC_DATA_ADDR,value[count]) ;
	}
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_SEQ_WR) ;

	while(sil9034_read(priv,SLAVE0,DDC_STATUS_ADDR)&BIT_MDDC_ST_IN_PROGR)
		mdelay(10) ;

	sil9034_dbg("DDC WRITE FIFO is %d\n",sil9034_read(priv,SLAVE0,DDC_FIFOCNT_ADDR)) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_ABORT) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_CLOCK) ;
	sil9034_write(priv,SLAVE0,DDC_MAN_ADDR,0) ;
	return NULL ;
}

static char *sil9034_ddc_read(davinci6446_sil9034 *priv,u8 *value,u8 reg, u8 length)
{
	u8 count = 0 ;

	sil9034_write(priv,SLAVE0,DDC_ADDR,HDCP_RX_SLAVE) ;
	sil9034_write(priv,SLAVE0,DDC_OFFSET_ADDR,reg) ;
	sil9034_write(priv,SLAVE0,DDC_CNT1_ADDR,length) ;
	sil9034_write(priv,SLAVE0,DDC_CNT2_ADDR,0) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_CLEAR_FIFO) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_SEQ_RD) ;

	while(sil9034_read(priv,SLAVE0,DDC_STATUS_ADDR)&BIT_MDDC_ST_IN_PROGR)
		mdelay(10) ;
	sil9034_dbg("DDC READ FIFO is %d\n",sil9034_read(priv,SLAVE0,DDC_FIFOCNT_ADDR)) ;
	for(count=0 ;count < length ; count++)
	{
		value[count] = sil9034_read(priv,SLAVE0,DDC_DATA_ADDR) ;
	}

	while(sil9034_read(priv,SLAVE0,DDC_STATUS_ADDR)&BIT_MDDC_ST_IN_PROGR)
		mdelay(10) ;

	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_ABORT) ;
	sil9034_write(priv,SLAVE0,DDC_CMD_ADDR,MASTER_CMD_CLOCK) ;
	sil9034_write(priv,SLAVE0,DDC_MAN_ADDR,0) ;
	return NULL ;
}

//--------------------------  INIT / EXIT ---------------------------------------------------------
static int sil9034_chipInfo(davinci6446_sil9034 *priv)
{
	u8 device_info[3] = {255,255,255} ;

	device_info[1] = sil9034_read(priv,SLAVE0,DEV_IDL) ;
	device_info[0] = sil9034_read(priv,SLAVE0,DEV_IDH) ;
	device_info[2] = sil9034_read(priv,SLAVE0,DEV_REV) ;
	printk(KERN_INFO "Silicon Image Device Driver Id 0x%02X%02X. Rev %02i.\n",device_info[0],device_info[1],device_info[2]) ;

	return 0 ;
}

static int sil9034_audioInfoFrameSetting(davinci6446_sil9034 *priv)
{
	u8 aud_info_addr ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* set the audio info frame type according to EIA-CEA-861-B datasheet */
	aud_info_addr = AUD_IF_ADDR ;

	/* Audio type , pg 78 on EIA_CEA_861_B.pdf */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x04) ;

	/* Audio version */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x01) ;

	/* Audio info frame length */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x10) ;

	/* Audio info frame chsum */
	sil9034_write(priv,SLAVE1,aud_info_addr++,(0x04+0x01+0x10)) ;

	/* AUDIO INFO DATA BYTE , according to Sil FAE, 5 byte is enought.
	 * page 56
	 */
	/* CT3 | CT2 | CT1 | CT0 | Rsvd | CC2 | CC1 | CC0| */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x11) ;

	/* Reserved (shall be 0) | SF2 | SF1 | SF0 | SS1 | SS0 |*/
	/* I should provide ioctl to re-sampling the frequence according
	 * to audio header type in user space program.
	 */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x1D) ;

	/* format depend on data byte 1 */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0x11) ;

	/* CA7 | CA6 | CA5 | CA4 | CA3 | CA2 | CA1 | CA0 | */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0) ;

	/* DM_I NH | LSV3 | LSV2 | LSV1 | LSV0 | Reserved (shall be 0)| */
	sil9034_write(priv,SLAVE1,aud_info_addr++,0) ;

	return 0 ;
 }
 
static int sil9034_cea861InfoFrameControl1(davinci6446_sil9034 *priv,u8 enable)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* enable the avi repeat transmission */
	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	if(enable)
		sil9034_write(priv,SLAVE1,INF_CTRL1,(reg_value | (BIT_AVI_REPEAT |BIT_AUD_ENABLE |BIT_AUD_REPEAT))) ;
	else
		sil9034_write(priv,SLAVE1,INF_CTRL1,0) ;
	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	sil9034_dbg("InfoFrame control#1 register 0x%x = 0x%x\n",INF_CTRL1,reg_value) ;


	return 0 ;
}

static int sil9034_cea861InfoFrameControl2(davinci6446_sil9034 *priv,u8 enable)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* Generic packet transmittion & repeat mode enable */
	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL2) ;
	if(enable)
	{
		/* enable GCP_RPT , GCP_EN */
		sil9034_write(priv,SLAVE1,INF_CTRL2,(reg_value |(GCP_EN|GCP_RPT))) ;
	}
	else
	{
		sil9034_write(priv,SLAVE1,INF_CTRL2,reg_value & ~(GCP_EN|GCP_RPT)) ;
	}
	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL2) ;
	sil9034_dbg("InfoFrame control#2 register 0x%x = 0x%x\n",INF_CTRL2,reg_value) ;

	return 0 ;
}
 
static int sil9034_switchClock2M48X1(davinci6446_sil9034 *priv,u8 enable)
{
         sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
#if 0
         outw((inw(IO_CLK_MOD2) & (~(0x1000))), IO_CLK_MOD2); /* disable I2C clock first */
         outw((inw(IO_CLK_DIV4) | 0x01F | 0x0C00), IO_CLK_DIV4);
         outw((inw(IO_CLK_MOD2) | 0x1000), IO_CLK_MOD2); /* re-enable I2C clock */
         if(enable)
         {
                 /* use M48X1 */
                 outw((inw(IO_CLK_SEL0) | 0x0000), IO_CLK_SEL0); /* select M48X1 */
         }
         else
         {
                 /* Use PLLB, MSP430 need this */
                 outw((inw(IO_CLK_SEL0) | 0x0C00), IO_CLK_SEL0); /* select PLLB */
         }
#endif
         return 0 ;
}

static int sil9034_cea861InfoFrameSetting(davinci6446_sil9034 *priv)
{
	u8 avi_info_addr ;
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	sil9034_write(priv,SLAVE1,INF_CTRL1,reg_value & (~BIT_AVI_REPEAT)) ;
	mdelay(64) ; // Delay VSync for unlock DATA buffer
	if(sil9034_read(priv,SLAVE1,INF_CTRL1)&BIT_AVI_ENABLE)
		sil9034_dbg("Sent AVI error\n") ;
	else
		sil9034_dbg("Silicon Image sending AVI success.\n") ;

	if(sil9034_read(priv,SLAVE1,INF_CTRL1)&BIT_AUD_ENABLE)
		sil9034_dbg("Sent AUD error\n") ;
	else
		sil9034_dbg("Silicon Image sending AUD success.\n") ;


	/* set the info frame type according to CEA-861 datasheet */
	avi_info_addr = AVI_IF_ADDR ;

	/* AVI type */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x82) ;

	/* AVI version */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x02) ;

	/* AVI length */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x13) ;

	/* AVI CRC */
	sil9034_write(priv,SLAVE1,avi_info_addr++,(0x82 + 0x02 + 0x13 + 0x1D)) ;

	/* AVI DATA BYTE , according to Sil FAE, 3 byte is enought.
	 * page 102
	 */
	/* 0 | Y1 | Y0 | A0 | B1 | B0 | S1 | S0 */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x1D) ;

	/* C1 | C0 | M1 | M0 | R3 | R2 | R1 | R0 */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x68) ;

	/*  0 | 0 | 0 | 0 | 0 | 0 | SC1 | SC0 */
	sil9034_write(priv,SLAVE1,avi_info_addr++,0x3) ;

	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	sil9034_write(priv,SLAVE1,INF_CTRL1,reg_value | (BIT_AVI_ENABLE|BIT_AVI_REPEAT)) ;
	return 0 ;
}
static int sil9034_wakeupHdmiTx(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	reg_value = sil9034_read(priv,SLAVE0,TX_SYS_CTRL1_ADDR) ;
	sil9034_write(priv,SLAVE0,TX_SYS_CTRL1_ADDR,reg_value|SET_PD) ;
	sil9034_write(priv,SLAVE0,INT_CNTRL_ADDR,0) ;
	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	sil9034_write(priv,SLAVE1,INF_CTRL1,reg_value |BIT_AVI_REPEAT|BIT_AUD_REPEAT) ;

	return 0 ;
}

static int sil9034_sentCPPackage(davinci6446_sil9034 *priv,u8 enable)
{
	u8 reg_value ;
	u8 timeout = 64 ;

	reg_value = sil9034_read(priv,SLAVE1,INF_CTRL2) ;
	sil9034_write(priv,SLAVE1,INF_CTRL2,reg_value &~BIT_CP_REPEAT) ;
	if(enable)
		sil9034_write(priv,SLAVE1,CP_IF_ADDR,BIT_CP_AVI_MUTE_SET) ;
	else
		sil9034_write(priv,SLAVE1,CP_IF_ADDR,BIT_CP_AVI_MUTE_CLEAR) ;

	while(timeout--)
	{
		if(!sil9034_read(priv,SLAVE1,INF_CTRL2)&BIT_CP_REPEAT)
			break ;
	}

	if(timeout)
		sil9034_write(priv,SLAVE1,INF_CTRL2,reg_value |(BIT_CP_REPEAT|BIT_CP_ENABLE)) ;

	return 0 ;
}
int sil9034_unmaskInterruptStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value = 0xFF ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	sil9034_write(priv,SLAVE0,HDMI_INT1_MASK,reg_value) ;
	sil9034_write(priv,SLAVE0,HDMI_INT2_MASK,reg_value) ;
	sil9034_write(priv,SLAVE0,HDMI_INT3_MASK,reg_value) ;

	return 0 ;
}
static int sil9034_hdmiOutputConfig(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* HDMI control register , enable HDMI, disable DVI */
	reg_value = sil9034_read(priv,SLAVE1,HDMI_CTRL_ADDR) ;
	sil9034_write(priv,SLAVE1,HDMI_CTRL_ADDR,(reg_value | HDMI_MODE_ENABLE)) ;
	reg_value = sil9034_read(priv,SLAVE1,HDMI_CTRL_ADDR) ;
	sil9034_dbg("Hdmi control register 0x%x = 0x%x\n",HDMI_CTRL_ADDR,reg_value) ;

	return 0 ;
}


static int sil9034_ddcSetting(davinci6446_sil9034 *priv)
{
	sil9034_write(priv,SLAVE0,DDC_ADDR,HDCP_RX_SLAVE) ;
	return 0 ;
}
 
static int sil9034_powerDown(davinci6446_sil9034 *priv,u8 enable)
{
	/* power down internal oscillator
	 * disable internal read of HDCP keys and KSV
	 * disable master DDC block
	 * page 4,50,113
	 */
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,TX_SYS_CTRL1_ADDR) ;
	if(enable)
	{
		sil9034_write(priv,SLAVE1,DIAG_PD_ADDR,~(0x7)) ;
		sil9034_write(priv,SLAVE0,TX_SYS_CTRL1_ADDR,reg_value & ~0x1) ;
	}
	else
	{
		sil9034_write(priv,SLAVE1,DIAG_PD_ADDR,0x7) ;
		sil9034_write(priv,SLAVE0,TX_SYS_CTRL1_ADDR,(reg_value | 0x1)) ;
	}
	reg_value = sil9034_read(priv,SLAVE0,TX_SYS_CTRL1_ADDR) ;
	sil9034_dbg("System control register #1 0x%x = 0x%x\n",TX_SYS_CTRL1_ADDR, reg_value) ;

	reg_value = sil9034_read(priv,SLAVE1,DIAG_PD_ADDR) ;
	sil9034_dbg("Diagnostic power down register 0x%x = 0x%x\n",DIAG_PD_ADDR, reg_value) ;
	return 0 ;
}

static int sil9034_swReset(davinci6446_sil9034 *priv)
{
	/* use to temporary save inf_ctrl */
	u8 temp1 ;
	u8 temp2 ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	temp1 = sil9034_read(priv,SLAVE1,INF_CTRL1) ;
	temp2 = sil9034_read(priv,SLAVE1,INF_CTRL2) ;
	/*
	 * audio fifo reset enable
	 * software reset enable
	 */
	while(!sil9034_read(priv,SLAVE0,TX_STAT_ADDR)&P_STABLE)
		mdelay(10) ;
	sil9034_write(priv,SLAVE0,TX_SWRST_ADDR,(BIT_TX_SW_RST|BIT_TX_FIFO_RST)) ;
	mdelay(10) ;
	sil9034_write(priv,SLAVE0,TX_SWRST_ADDR,0) ;
	mdelay(64) ; // allow TCLK (sent to Rx across the HDMS link) to stabilize

	/* restore */
	sil9034_write(priv,SLAVE1,INF_CTRL1,temp1) ;
	sil9034_write(priv,SLAVE1,INF_CTRL2,temp2) ;
	return 0 ;
}

static int sil9034_triggerRom(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,KEY_COMMAND_ADDR) ;
	sil9034_write(priv,SLAVE0,KEY_COMMAND_ADDR,reg_value & ~LD_KSV) ;
	mdelay(10) ;
	sil9034_write(priv,SLAVE0,KEY_COMMAND_ADDR,reg_value |LD_KSV) ;
	mdelay(10) ;
	sil9034_write(priv,SLAVE0,KEY_COMMAND_ADDR,reg_value & ~LD_KSV) ;
	return 0 ;
}



static int sil9034_generalControlPacket(davinci6446_sil9034 *priv,u8 enable)
{
	u8 reg_value ;
	/*
	 * mute the video & audio
	 */
	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE1,GCP_BYTE1) ;
	if(enable)
	{
		/* set avmute flag */
		sil9034_write(priv,SLAVE1,GCP_BYTE1,(reg_value | SET_AVMUTE)) ;
	}
	else
	{
		/* clear avmute flag */
		sil9034_write(priv,SLAVE1,GCP_BYTE1,(reg_value | CLR_AVMUTE)) ;
	}
	reg_value = sil9034_read(priv,SLAVE1,GCP_BYTE1) ;
	sil9034_dbg("General control packet register 0x%x = 0x%x\n",GCP_BYTE1,reg_value) ;

	return 0 ;
}

static int sil9034_audioInputConfig(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* Audio mode register */
	sil9034_write(priv,SLAVE1,AUD_MODE_ADDR,0xF9) ;
	reg_value = sil9034_read(priv,SLAVE1,AUD_MODE_ADDR) ;
	sil9034_dbg("Audio in mode register 0x%x = 0x%x\n",AUD_MODE_ADDR,reg_value) ;

	/* ACR audio frequency register: * MCLK=128 Fs */
	sil9034_write(priv,SLAVE1,FREQ_SVAL_ADDR,0) ;
	reg_value = sil9034_read(priv,SLAVE1,FREQ_SVAL_ADDR) ;
	sil9034_dbg("Audio frequency register 0x%x = 0x%x\n",FREQ_SVAL_ADDR,reg_value) ;

	return 0 ;
}

static int sil9034_hdmiVideoEmbSyncDec(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,INTERLACE_ADJ_MODE) ;
	sil9034_write(priv,SLAVE0,INTERLACE_ADJ_MODE,(reg_value & ~(0x7))) ;
	reg_value = sil9034_read(priv,SLAVE0,INTERLACE_ADJ_MODE) ;
	sil9034_dbg("Interlace Adjustment register 0x%x = 0x%x\n",INTERLACE_ADJ_MODE,reg_value) ;
	return 0 ;
}
 

static int sil9034_hdmiTmdsConfig(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* TMDS control register
	 * FPLL is 1.0*IDCK.
	 * Internal source termination enabled.
	 * Driver level shifter bias enabled.
	 * page 27
	 */
	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL_ADDR) ;
	sil9034_write(priv,SLAVE0,TX_TMDS_CTRL_ADDR,reg_value|0x5) ;
	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL_ADDR) ;
	sil9034_dbg("TMDS control register 0x%x = 0x%x\n",TX_TMDS_CTRL_ADDR,reg_value) ;
}

static int sil9034_hdmiHdcpConfig(davinci6446_sil9034 *priv,u8 enable)
{
          u8 reg_value ;
  
          sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
          /* HDMI HDCP configuration */
          reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
          if(enable){
		sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,(reg_value | SET_ENC_EN)) ;
		priv->auth_state = AUTH_NEED ;
          }else{
		sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,(reg_value & ~(SET_ENC_EN))) ;
		priv->auth_state = AUTH_DONE ;
 	  } 
          reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
          sil9034_dbg("Hdmi hdcp register 0x%x = 0x%x\n",HDCP_CTRL_ADDR,reg_value) ;
  
          return 0 ;
}

char sil9034_hotplugEvent(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	reg_value = sil9034_read(priv,SLAVE0,TX_STAT_ADDR) ;
	if(reg_value&SET_HPD)
		return 1 ;
	else
		return 0 ;
}

static int sil9034_checkHdcpDevice(davinci6446_sil9034 *priv)
{
	u8 total = 0 ;
	u8 bits = 0 ;
	u8 count = 0 ;

	/* read 5 byte from ddc */
	sil9034_ddc_read(priv,&priv->an_ksv_data[0],DDC_BKSV_ADDR,5) ;

	/* calculate bits */
	for(count=0 ;count<5 ; count++)
	{
		sil9034_dbg("bksv %d,0x%x\n",count,priv->an_ksv_data[count]) ;
		for(bits=0 ;bits<8 ; bits++)
			if(priv->an_ksv_data[count] & (1<<bits))
				total++ ;
	}

	if(total == HDCP_ACC)
		return TRUE ;
	else
		return FALSE ;
}

static int sil9034_toggleRepeatBit(davinci6446_sil9034 *priv)
{ 
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
	if(reg_value & RX_RPTR_ENABLE)
		sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value&~RX_RPTR_ENABLE) ;
	else
		sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value|RX_RPTR_ENABLE) ;

	return 0 ;
}

static int sil9034_releaseCPReset(davinci6446_sil9034 *priv)
{ 
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
	sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value|SET_CP_RESTN) ;

	return 0 ;
}

static int sil9034_StopRepeatBit(davinci6446_sil9034 *priv)
{ 
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
	sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value&~RX_RPTR_ENABLE) ;
	return 0 ;
}

static int sil9034_writeAnHdcpRx(davinci6446_sil9034 *priv)
{ 
	/* write 8 byte to ddc hdcp rx*/
	sil9034_ddc_write(priv,&priv->an_ksv_data[0],DDC_AN_ADDR,8) ;

	return 0 ;
}
static int sil9034_writeBksvHdcpTx(davinci6446_sil9034 *priv)
{ 
	u8 count = 0 ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	for(count=0; count<5; count++)
	{
		 sil9034_write(priv,SLAVE0,HDCP_BKSV1_ADDR+count,priv->an_ksv_data[count]) ;
		 sil9034_dbg("write bksv to tx 0x%x\n",priv->an_ksv_data[count]) ;
	}

	return 0 ;
}
static int sil9034_readBksvHdcpRx(davinci6446_sil9034 *priv)
{ 
	u8 count = 0 ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	/* read 5 byte from ddc */
	sil9034_ddc_read(priv,&priv->an_ksv_data[0],DDC_BKSV_ADDR,5) ;
	for(count=0; count<5; count++)
	{
		sil9034_dbg("bksv data %d 0x%x\n",count,priv->an_ksv_data[count]) ;
	}

	return 0 ;
}

static int sil9034_writeAksvHdcpRx(davinci6446_sil9034 *priv)
{ 
	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* write 5 byte to ddc hdcp rx*/
	sil9034_ddc_write(priv,&priv->an_ksv_data[0],DDC_AKSV_ADDR,5) ;

	return 0 ;
}

static int sil9034_readAksvHdcpTx(davinci6446_sil9034 *priv)
{ 
	u8 count = 0 ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	for(count=0; count<5; count++)
	{
		priv->an_ksv_data[count] = sil9034_read(priv,SLAVE0,HDCP_AKSV1_ADDR+count) ;
		sil9034_dbg("aksv data %d 0x%x\n",count,priv->an_ksv_data[count]) ;
	}

	return 0 ;
}

static int sil9034_readAnHdcpTx(davinci6446_sil9034 *priv)
{ 
	u8 count = 0 ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	for(count=0; count<8; count++)
	{
		priv->an_ksv_data[count] = sil9034_read(priv,SLAVE0,HDCP_AN1_ADDR+count) ;
		sil9034_dbg("an data %d 0x%x\n",count,priv->an_ksv_data[count]) ;
	}

	return 0 ;
}

static int sil9034_generateAn(davinci6446_sil9034 *priv)
{ 
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	reg_value = sil9034_read(priv,SLAVE0,HDCP_CTRL_ADDR) ;
	sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value&~TX_ANSTOP) ;
	mdelay(10) ;
	sil9034_write(priv,SLAVE0,HDCP_CTRL_ADDR,reg_value|TX_ANSTOP) ;

	return 0 ;
}
static int sil9034_isRepeater(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/* read 1 byte from ddc */
	sil9034_ddc_read(priv,&reg_value,DDC_BCAPS_ADDR,1) ;
	if(reg_value&DDC_BIT_REPEATER)
		return TRUE ;

	return FALSE ;
}
static int sil9034_compareR0(davinci6446_sil9034 *priv)
{
	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	/* read 2 byte from ddc */
	sil9034_ddc_read(priv,&priv->r0rx[0],DDC_RI_ADDR,2) ;
	priv->r0tx[0] = sil9034_read(priv,SLAVE0,HDCP_RI1) ;
	priv->r0tx[1] = sil9034_read(priv,SLAVE0,HDCP_RI2) ;

	if((priv->r0rx[0]==priv->r0tx[0])&&(priv->r0rx[1]==priv->r0tx[1]))
	{
		printk(KERN_INFO "HDCP handshake complete match.\n") ;
		return TRUE ;
	}

	return FALSE ;
}

  
static int sil9034_videoInputConfig(davinci6446_sil9034 *priv)
{
	u8 count = 0 ;

	/* Auto setting by the sil9034_video_mapping struct */
	while(priv->sil9034_setting[count++].video_reg != 0)
	{
		sil9034_dbg("setting count %d 0x%x-0x%x\n",count,\
				priv->sil9034_setting[count].video_reg,\
				priv->sil9034_setting[count].value) ;

		sil9034_write(priv,SLAVE0,priv->sil9034_setting[count].video_reg,\
				priv->sil9034_setting[count].value) ;
	}


	return 0 ;
}


static int sil9034_autoRiCheck(davinci6446_sil9034 *priv,u8 enable)
{
	u8 reg_value ;

	reg_value = sil9034_read(priv,SLAVE0,RI_CMD_ADDR) ;
	if(enable)
		sil9034_write(priv,SLAVE0,RI_CMD_ADDR, reg_value|SET_RI_ENABLE);
	else
		sil9034_write(priv,SLAVE0,RI_CMD_ADDR, reg_value&~SET_RI_ENABLE);
	return 0 ;
}

int sil9034_dumpSystemStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,TX_STAT_ADDR) ;
	sil9034_dbg("System status register 0x%x = 0x%x\n",TX_STAT_ADDR,reg_value) ;
	return 0 ;
}

int sil9034_dumpDataCtrlStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,DCTL_ADDR) ;
	sil9034_dbg("Data control register 0x%x = 0x%x\n",DCTL_ADDR,reg_value) ;
	return 0 ;
}



int sil9034_clearInterruptStatus(davinci6446_sil9034 *priv)
{

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	/*
	   u8 reg_value ;

	   reg_value = sil9034_read(priv,SLAVE0,INT_CNTRL_ADDR) ;
	   sil9034_write(priv,SLAVE0,INT_CNTRL_ADDR,reg_value) ;
	   reg_value = sil9034_read(priv,SLAVE0,INT_CNTRL_ADDR) ;
	   sil9034_dbg("Interrupt control register 0x%x = 0x%x\n",INT_CNTRL_ADDR,reg_value) ;
	 */

	sil9034_write(priv,SLAVE0,INT_SOURCE1_ADDR,0xFF) ;
	sil9034_write(priv,SLAVE0,INT_SOURCE2_ADDR,0xFF) ;
	sil9034_write(priv,SLAVE0,INT_SOURCE3_ADDR,0xFF) ;

	return 0 ;
}
 
int sil9034_dumpInterruptSourceStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,INT_SOURCE1_ADDR) ;
	sil9034_dbg("Interrupt source 1 register 0x%x = 0x%x\n",INT_SOURCE1_ADDR,reg_value) ;
	reg_value = sil9034_read(priv,SLAVE0,INT_SOURCE2_ADDR) ;
	sil9034_dbg("Interrupt source 2 register 0x%x = 0x%x\n",INT_SOURCE2_ADDR,reg_value) ;
	reg_value = sil9034_read(priv,SLAVE0,INT_SOURCE3_ADDR) ;
	sil9034_dbg("Interrupt source 3 register 0x%x = 0x%x\n",INT_SOURCE3_ADDR,reg_value) ;
	/* Interrupt register will auto clean after read ?*/
	sil9034_clearInterruptStatus(priv) ;

	return 0 ;
}

int sil9034_dumpVideoConfigureStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,HRES_L_ADDR) ;
	sil9034_dbg("H resolution low register 0x%x = 0x%x\n",HRES_L_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,HRES_H_ADDR) ;
	sil9034_dbg("H resolution high register 0x%x = 0x%x\n",HRES_H_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,VRES_L_ADDR) ;
	sil9034_dbg("V resolution low register 0x%x = 0x%x\n",VRES_L_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,VRES_H_ADDR) ;
	sil9034_dbg("V resolution high register 0x%x = 0x%x\n",VRES_H_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,DEL_L_ADDR) ;
	sil9034_dbg("DE line low register 0x%x = 0x%x\n",DEL_L_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,DEL_H_ADDR) ;
	sil9034_dbg("DE line high register 0x%x = 0x%x\n",DEL_H_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,POL_DETECT_ADDR) ;
	sil9034_dbg("Video polarity detect register 0x%x = 0x%x\n",POL_DETECT_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,HLENGTH1_ADDR) ;
	sil9034_dbg("Video HSYNC length1 register 0x%x = 0x%x\n",HLENGTH1_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,HLENGTH2_ADDR) ;
	sil9034_dbg("Video HSYNC length2 register 0x%x = 0x%x\n",HLENGTH2_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,VBIT_TO_VSYNC_ADDR) ;
	sil9034_dbg("Video Vbit to VSync register 0x%x = 0x%x\n",VBIT_TO_VSYNC_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,VLENGTH_ADDR) ;
	sil9034_dbg("Video VSYNC length register 0x%x = 0x%x\n",VLENGTH_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CCTRL_ADDR) ;
	sil9034_dbg("TMDS C control register 0x%x = 0x%x\n",TX_TMDS_CCTRL_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL_ADDR) ;
	sil9034_dbg("TMDS control register 0x%x = 0x%x\n",TX_TMDS_CTRL_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL2_ADDR) ;
	sil9034_dbg("TMDS control #2 register 0x%x = 0x%x\n",TX_TMDS_CTRL2_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL3_ADDR) ;
	sil9034_dbg("TMDS control #3 register 0x%x = 0x%x\n",TX_TMDS_CTRL3_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_TMDS_CTRL4_ADDR) ;
	sil9034_dbg("TMDS control #4 register 0x%x = 0x%x\n",TX_TMDS_CTRL4_ADDR,reg_value) ;

	reg_value = sil9034_read(priv,SLAVE0,TX_VID_ACEN_ADDR) ;
	sil9034_dbg("Video action enable register 0x%x = 0x%x\n",TX_VID_ACEN_ADDR,reg_value) ;

	return 0 ;
}

int sil9034_dumpInterruptStateStatus(davinci6446_sil9034 *priv)
{
	u8 reg_value ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	reg_value = sil9034_read(priv,SLAVE0,INT_STATE_ADDR) ;
	sil9034_dbg("Interrupt state register 0x%x = 0x%x\n",INT_STATE_ADDR,reg_value) ;
	if(reg_value & INT_ENABLE)
		sil9034_dumpInterruptSourceStatus(priv) ;
	else
		sil9034_dbg("No unmask interrupt\n") ;
	return 0 ;
}

int sil9034_hdcpAuthentication(davinci6446_sil9034 *priv)
{
	sil9034_autoRiCheck(priv,DISABLE) ;
	if(sil9034_hotplugEvent(priv))
	{

		sil9034_sentCPPackage(priv,ENABLE) ;
		if(sil9034_checkHdcpDevice(priv) == TRUE)
		{
			sil9034_dbg("got 20's 1\n") ;
			/* Random key */
			sil9034_toggleRepeatBit(priv) ;
			sil9034_releaseCPReset(priv) ;
			sil9034_StopRepeatBit(priv) ;
			sil9034_generateAn(priv) ;
			/* Handshake start */
			sil9034_readAnHdcpTx(priv) ;
			sil9034_writeAnHdcpRx(priv) ;
			sil9034_readAksvHdcpTx(priv) ;
			sil9034_writeAksvHdcpRx(priv) ;
			sil9034_readBksvHdcpRx(priv) ;
			sil9034_writeBksvHdcpTx(priv) ;
			if(sil9034_isRepeater(priv)==TRUE)
				printk(KERN_ERR "This is repeater,not support.\n") ;
			/* Finally, compare key */
			mdelay(100) ; //delay for R0 calculation
			if(sil9034_compareR0(priv)==FALSE)
			{
				priv->auth_state = REAUTH_NEED ;
			}
			else
			{
				/* unmute */
				sil9034_sentCPPackage(priv,DISABLE) ;
				sil9034_autoRiCheck(priv,ENABLE) ;
				priv->auth_state = AUTH_DONE ;
			}
		}
		else // no 20 ones and zeros
		{
			/* mute */
			sil9034_sentCPPackage(priv,ENABLE) ;
			sil9034_dbg("TV not send 20's 1,retry!!\n") ;
		}
	}
	return 0 ;
}

/* HDCP key exchange for hdmi */
static void sil9034_timer(unsigned long data)
{
	int status;
	davinci6446_sil9034 *priv = (void *)data ;

	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;

	if(priv)
	{
#if SIL9034_SCHED
		priv->work_flag = EVENT_NOTIFY ;
		status = schedule_work(&priv->work);
		if(!status)
			printk(KERN_ERR "scheduling work error\n") ;
#else
		mod_timer(&ds.timer, jiffies + TIMER_JIFFIES);
#endif
	}
	return ;
}

#if SIL9034_SCHED
static void sil9034_sched(void *data)
{
	/* This is important, get out of the interrupt context switch trouble */
	davinci6446_sil9034 *priv = container_of(data, davinci6446_sil9034, work);
	u8 intr1_isr ;
	u8 intr3_isr ;
	
	switch(priv->work_flag)
	{
		case EVENT_NOTIFY:
			intr3_isr = sil9034_read(priv,SLAVE0,INT_SOURCE3_ADDR) ;
			intr1_isr = sil9034_read(priv,SLAVE0,INT_SOURCE1_ADDR) ;
			/* ri frame error occur */
			if(intr3_isr & (INTR3_STAT7|INTR3_STAT5|INTR3_STAT4))
			{
				printk(KERN_INFO "Ri frame error 0x%x\n",intr3_isr) ;
				priv->auth_state = REAUTH_NEED ;
			}
			/* line plug */
			if(intr1_isr & (INTR1_HPD|INTR1_RSEN))
			{
				printk(KERN_INFO "line plug 0x%x\n",intr1_isr) ;
				priv->auth_state = REAUTH_NEED ;
			}

			break ;
		default:
			break ;
	}
	//printk(KERN_ERR "%s, %d\n",__FUNCTION__,__LINE__) ;

	/* Check if hdcp authentication need */
	if((priv->auth_state == AUTH_NEED) || (priv->auth_state == REAUTH_NEED))
	{
		sil9034_hdcpAuthentication(priv) ;
	}

	sil9034_dumpSystemStatus(priv) ;
	//sil9034_dumpDataCtrlStatus(priv) ;
	//sil9034_dumpInterruptStateStatus(priv) ;
	//sil9034_dumpVideoConfigureStatus(priv) ;

	/* clean the work flag */
	priv->work_flag = DO_NOTHING ;
	
#if SIL9034_TIMER
	mod_timer(&ds.timer, jiffies + TIMER_JIFFIES);
#endif

	sil9034_clearInterruptStatus(priv) ;
	return ;

}
#endif

void sil9034_read_table(davinci6446_sil9034 *priv, u8 slaveIndex, u8 reg,  u8 tbl_cnt)
{
        unsigned char i = 0;
	int data;
printk("[%s]enter slaveIndex:0x%x\n", __func__, slaveIndex);
        for(i = 0; i < tbl_cnt; i++){
		if(  (i %16 == 0)){
			printk("\n");
		}
                data = sil9034_read(priv, slaveIndex, (reg+ i));
printk("0x%02x ", data);

	}
printk("\n[%s]leave\n\n", __func__);
}

static int __init sil9034_init(void)
{
	int status = 0 ;


	if ((status = i2c_add_driver(&sil9034_driver)) < 0)
	{
		printk(KERN_INFO "%s Couldn't register SIL9034 I2C driver.\n", pname);
		goto out;
	} 
	/* Initial default as 720p */
	//ds.sil9034_setting = sil9034_720p_422_embsync_setting ;
	//ds.sil9034_setting = sil9034_720p_422_sepsync_setting ;
	ds.sil9034_setting = sil9034_1080p_422_embsync_setting ;

	/* read chip id & revision */
	sil9034_chipInfo(&ds) ;

	/* power down occilator */
	sil9034_powerDown(&ds,ENABLE) ;

	/* TMDS control register */
	sil9034_hdmiTmdsConfig(&ds) ;


#if 1
	/* Tune the audio input table according to DM320 hardware spec */
	//sil9034_audioInputConfig() ;

	/* Tune the video input table according to DM320 hardware spec */
	sil9034_videoInputConfig(&ds) ;


	/* software reset */
	sil9034_swReset(&ds) ;



	/* power up occilator */
	sil9034_powerDown(&ds, DISABLE) ;

	/* Trigger ROM */
	sil9034_triggerRom(&ds) ;

	/* software reset */
	sil9034_swReset(&ds) ;

	/* CEA-861 Info Frame control setting */
	sil9034_cea861InfoFrameSetting(&ds) ;

	/* Wake up HDMI TX */
	sil9034_wakeupHdmiTx(&ds) ;

	/* Sent CP package */
	sil9034_sentCPPackage(&ds,ENABLE) ;

	/* unmask the interrupt status */
	sil9034_unmaskInterruptStatus(&ds) ;

	/* Hdmi output setting */
	sil9034_hdmiOutputConfig(&ds) ;

	/* ddc master config */
	sil9034_ddcSetting(&ds) ;

	/* General control packet */
	sil9034_sentCPPackage(&ds,DISABLE) ;

	sil9034_cea861InfoFrameControl2(&ds,ENABLE) ;

	/* HDCP control handshaking */
	sil9034_hdmiHdcpConfig(&ds,ENABLE) ;

	/* Disable Auto RI check here, enable it until hdcp complete. */
	sil9034_autoRiCheck(&ds,DISABLE) ;

	sil9034_clearInterruptStatus(&ds) ;

#endif
#if SIL9034_SCHED
	INIT_WORK(&ds.work, sil9034_sched);
	ds.work_flag = EVENT_NOTIFY ;
	schedule_work(&ds.work);
#endif

#if SIL9034_TIMER
	init_timer(&ds.timer);
	ds.timer.data = (unsigned long)&ds;
	ds.timer.function = sil9034_timer;
	ds.timer.expires = jiffies + TIMER_JIFFIES;
	add_timer(&ds.timer);
#endif
	sil9034_read_table(&ds, 0, 0, 255);

out:
	return status;
}

static void __exit sil9034_exit(void)
{
	sil9034_dbg("----------%s----------\n",__FUNCTION__) ;
	i2c_del_driver(&sil9034_driver);
	if( ds.sil9034_client[0] ) kfree( ds.sil9034_client[0] );
	if( ds.sil9034_client[1] ) kfree( ds.sil9034_client[1] );


}

MODULE_LICENSE("GPL");

module_init(sil9034_init);
module_exit(sil9034_exit);

8510.sii9034hdmi.h

Regards.