edp anx6345: add dpcd&edid read support

This commit is contained in:
yxj
2014-02-26 11:03:21 +08:00
parent b39b67de2e
commit bede187814
3 changed files with 1020 additions and 558 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
#include <linux/of_gpio.h>
#endif
#include "anx6345.h"
#include "dpcd_edid.h"
#if defined(CONFIG_DEBUG_FS)
#include <linux/fs.h>
#include <linux/debugfs.h>
@@ -169,8 +169,8 @@ static int get_dp_chip_id(struct i2c_client *client)
{
char c1,c2;
int id;
anx6345_i2c_read_p1_reg(client,SP_TX_DEV_IDL_REG,&c1);
anx6345_i2c_read_p1_reg(client,SP_TX_DEV_IDH_REG,&c2);
anx6345_i2c_read_p1_reg(client,DEV_IDL_REG,&c1);
anx6345_i2c_read_p1_reg(client,DEV_IDH_REG,&c2);
id = c2;
return (id<<8)|c1;
}
@@ -624,119 +624,459 @@ static int anx980x_init(struct i2c_client *client)
return 0;
}
#if 1
static int anx6345_bist_mode(struct i2c_client *client)
{
struct edp_anx6345 *anx6345 = i2c_get_clientdata(client);
struct rk_screen *screen = &anx6345->screen;
u16 x_total ,y_total;
u32 total, act_total;
u16 x_total ,y_total, x_act;
char val = 0x00;
//these register are for bist mode
x_total = screen->mode.left_margin + screen->mode.right_margin +
screen->mode.xres + screen->mode.hsync_len;
y_total = screen->mode.upper_margin + screen->mode.lower_margin +
screen->mode.yres + screen->mode.vsync_len;
total = x_total * y_total;
printk("%s>>>>total:0x%08x\n",__func__, total);
act_total = screen->mode.xres * screen->mode.yres;
x_total >>= 1;
x_act = screen->mode.xres >> 1;
val = y_total & 0xff;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_LINEL_REG,&val);
anx6345_i2c_write_p1_reg(client,TOTAL_LINEL_REG,&val);
val = (y_total >> 8);
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_LINEH_REG,&val);
anx6345_i2c_write_p1_reg(client,TOTAL_LINEH_REG,&val);
val = (screen->mode.yres & 0xff);
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_LINEL_REG,&val);
anx6345_i2c_write_p1_reg(client,ACT_LINEL_REG,&val);
val = (screen->mode.yres >> 8);
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_LINEH_REG,&val);
anx6345_i2c_write_p1_reg(client,ACT_LINEH_REG,&val);
val = screen->mode.lower_margin;
anx6345_i2c_write_p1_reg(client,SP_TX_VF_PORCH_REG,&val);
anx6345_i2c_write_p1_reg(client,VF_PORCH_REG,&val);
val = screen->mode.vsync_len;
anx6345_i2c_write_p1_reg(client,SP_TX_VSYNC_CFG_REG,&val);
anx6345_i2c_write_p1_reg(client,VSYNC_CFG_REG,&val);
val = screen->mode.upper_margin;
anx6345_i2c_write_p1_reg(client,SP_TX_VB_PORCH_REG,&val);
val = total & 0xff;
val = 0x50;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_PIXELL_REG,&val);
val = total >> 8;
val = 0x04;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_PIXELH_REG,&val);
val = (act_total & 0xff);
val = 0x00;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_PIXELL_REG,&val);
val = (act_total >> 8);
val = 0x04;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_PIXELH_REG,&val);
anx6345_i2c_write_p1_reg(client,VB_PORCH_REG,&val);
val = x_total & 0xff;
anx6345_i2c_write_p1_reg(client,TOTAL_PIXELL_REG,&val);
val = x_total >> 8;
anx6345_i2c_write_p1_reg(client,TOTAL_PIXELH_REG,&val);
val = (x_act & 0xff);
anx6345_i2c_write_p1_reg(client,ACT_PIXELL_REG,&val);
val = (x_act >> 8);
anx6345_i2c_write_p1_reg(client,ACT_PIXELH_REG,&val);
val = screen->mode.right_margin & 0xff;
anx6345_i2c_write_p1_reg(client,SP_TX_HF_PORCHL_REG,&val);
anx6345_i2c_write_p1_reg(client,HF_PORCHL_REG,&val);
val = screen->mode.right_margin >> 8;
anx6345_i2c_write_p1_reg(client,SP_TX_HF_PORCHH_REG,&val);
anx6345_i2c_write_p1_reg(client,HF_PORCHH_REG,&val);
val = screen->mode.hsync_len & 0xff;
anx6345_i2c_write_p1_reg(client,SP_TX_HSYNC_CFGL_REG,&val);
anx6345_i2c_write_p1_reg(client,HSYNC_CFGL_REG,&val);
val = screen->mode.hsync_len >> 8;
anx6345_i2c_write_p1_reg(client,SP_TX_HSYNC_CFGH_REG,&val);
anx6345_i2c_write_p1_reg(client,HSYNC_CFGH_REG,&val);
val = screen->mode.left_margin & 0xff;
anx6345_i2c_write_p1_reg(client,SP_TX_HB_PORCHL_REG,&val);
anx6345_i2c_write_p1_reg(client,HB_PORCHL_REG,&val);
val = screen->mode.left_margin >> 8;
anx6345_i2c_write_p1_reg(client,SP_TX_HB_PORCHH_REG,&val);
anx6345_i2c_write_p1_reg(client,HB_PORCHH_REG,&val);
val = 0x13;
anx6345_i2c_write_p1_reg(client,SP_TX_VID_CTRL10_REG,&val);
anx6345_i2c_write_p1_reg(client,VID_CTRL10_REG,&val);
//enable BIST. In normal mode, don't need to config this reg
val = 0x08;
anx6345_i2c_write_p1_reg(client, SP_TX_VID_CTRL4_REG, &val);
anx6345_i2c_write_p1_reg(client, VID_CTRL4_REG, &val);
printk("anx6345 enter bist mode\n");
return 0;
}
#else
static int anx6345_bist_mode(struct i2c_client *client)
int anx6345_start_aux_transaction(struct i2c_client *client)
{
char val = 0x00;
//these register are for bist mode
val = 0x2c;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_LINEL_REG,&val);
val = 0x06;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_LINEH_REG,&val);
val = 0x00;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_LINEL_REG,&val);
val = 0x06;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_LINEH_REG,&val);
val = 0x02;
anx6345_i2c_write_p1_reg(client,SP_TX_VF_PORCH_REG,&val);
val = 0x04;
anx6345_i2c_write_p1_reg(client,SP_TX_VSYNC_CFG_REG,&val);
val = 0x26;
anx6345_i2c_write_p1_reg(client,SP_TX_VB_PORCH_REG,&val);
val = 0x50;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_PIXELL_REG,&val);
val = 0x04;
anx6345_i2c_write_p1_reg(client,SP_TX_TOTAL_PIXELH_REG,&val);
val = 0x00;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_PIXELL_REG,&val);
val = 0x04;
anx6345_i2c_write_p1_reg(client,SP_TX_ACT_PIXELH_REG,&val);
val = 0x18;
anx6345_i2c_write_p1_reg(client,SP_TX_HF_PORCHL_REG,&val);
val = 0x00;
anx6345_i2c_write_p1_reg(client,SP_TX_HF_PORCHH_REG,&val);
val = 0x10;
anx6345_i2c_write_p1_reg(client,SP_TX_HSYNC_CFGL_REG,&val);
val = 0x00;
anx6345_i2c_write_p1_reg(client,SP_TX_HSYNC_CFGH_REG,&val);
val = 0x28;
anx6345_i2c_write_p1_reg(client,SP_TX_HB_PORCHL_REG,&val);
val = 0x13;
anx6345_i2c_write_p1_reg(client,SP_TX_VID_CTRL10_REG,&val);
//enable BIST. In normal mode, don't need to config this reg
val = 0x08;
anx6345_i2c_write_p1_reg(client, SP_TX_VID_CTRL4_REG, &val);
printk("anx6345 enter bist mode\n");
char val;
int retval = 0;
int timeout_loop = 0;
int aux_timeout = 0;
return 0;
anx6345_i2c_read_p0_reg(client, DP_AUX_CH_CTL_2, &val);
val |= AUX_EN;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_2, &val);
anx6345_i2c_read_p0_reg(client, DP_AUX_CH_CTL_2, &val);
while (val & AUX_EN) {
aux_timeout++;
if ((DP_TIMEOUT_LOOP_CNT * 10) < aux_timeout) {
dev_err(&client->dev, "AUX CH enable timeout!\n");
return -ETIMEDOUT;
}
anx6345_i2c_read_p0_reg(client, DP_AUX_CH_CTL_2, &val);
udelay(100);
}
/* Is AUX CH command redply received? */
anx6345_i2c_read_p1_reg(client, DP_INT_STA, &val);
while (!(val & RPLY_RECEIV)) {
timeout_loop++;
if (DP_TIMEOUT_LOOP_CNT < timeout_loop) {
dev_err(&client->dev, "AUX CH command redply failed!\n");
return -ETIMEDOUT;
}
anx6345_i2c_read_p1_reg(client, DP_INT_STA, &val);
udelay(10);
}
/* Clear interrupt source for AUX CH command redply */
anx6345_i2c_write_p1_reg(client, DP_INT_STA, &val);
/* Check AUX CH error access status */
anx6345_i2c_read_p0_reg(client, AUX_CH_STA, &val);
if ((val & AUX_STATUS_MASK) != 0) {
dev_err(&client->dev, "AUX CH error happens: %d\n\n",
val & AUX_STATUS_MASK);
return -EREMOTEIO;
}
return retval;
}
#endif
int anx6345_dpcd_write_bytes(struct i2c_client *client,
unsigned int val_addr,
unsigned int count,
unsigned char data[])
{
char val;
unsigned int start_offset;
unsigned int cur_data_count;
unsigned int cur_data_idx;
int retval = 0;
start_offset = 0;
while (start_offset < count) {
/* Buffer size of AUX CH is 16 * 4bytes */
if ((count - start_offset) > 16)
cur_data_count = 16;
else
cur_data_count = count - start_offset;
val = BUF_CLR;
anx6345_i2c_write_p0_reg(client, BUF_DATA_CTL, &val);
val = AUX_ADDR_7_0(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_7_0, &val);
val = AUX_ADDR_15_8(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_15_8, &val);
val = AUX_ADDR_19_16(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_19_16, &val);
for (cur_data_idx = 0; cur_data_idx < cur_data_count;
cur_data_idx++) {
val = data[start_offset + cur_data_idx];
anx6345_i2c_write_p0_reg(client, BUF_DATA_0 + cur_data_idx, &val);
}
/*
* Set DisplayPort transaction and write
* If bit 3 is 1, DisplayPort transaction.
* If Bit 3 is 0, I2C transaction.
*/
val = AUX_LENGTH(cur_data_count) |
AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_1, &val);
/* Start AUX transaction */
retval = anx6345_start_aux_transaction(client);
if (retval == 0)
break;
else
dev_dbg(&client->dev, "Aux Transaction fail!\n");
start_offset += cur_data_count;
}
return retval;
}
int anx6345_dpcd_read_bytes(struct i2c_client *client,
unsigned int val_addr,
unsigned int count,
unsigned char data[])
{
char val;
unsigned int start_offset;
unsigned int cur_data_count;
unsigned int cur_data_idx;
int i;
int retval = 0;
start_offset = 0;
while (start_offset < count) {
/* Buffer size of AUX CH is 16 * 4bytes */
if ((count - start_offset) > 16)
cur_data_count = 16;
else
cur_data_count = count - start_offset;
/* AUX CH Request Transaction process */
for (i = 0; i < 10; i++) {
/* Select DPCD device address */
val = AUX_ADDR_7_0(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_7_0, &val);
val = AUX_ADDR_15_8(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_15_8, &val);
val = AUX_ADDR_19_16(val_addr + start_offset);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_19_16, &val);
/*
* Set DisplayPort transaction and read
* If bit 3 is 1, DisplayPort transaction.
* If Bit 3 is 0, I2C transaction.
*/
val = AUX_LENGTH(cur_data_count) |
AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_1, &val);
val = BUF_CLR;
anx6345_i2c_write_p0_reg(client, BUF_DATA_CTL, &val);
/* Start AUX transaction */
retval = anx6345_start_aux_transaction(client);
if (retval == 0)
break;
else
dev_dbg(&client->dev, "Aux Transaction fail!\n");
}
for (cur_data_idx = 0; cur_data_idx < cur_data_count;
cur_data_idx++) {
anx6345_i2c_read_p0_reg(client, BUF_DATA_0 + cur_data_idx, &val);
data[start_offset + cur_data_idx] = val;
dev_dbg(&client->dev, "0x%05x :0x%02x\n",cur_data_idx, val);
}
start_offset += cur_data_count;
}
return retval;
}
int anx6345_select_i2c_device(struct i2c_client *client,
unsigned int device_addr,
char val_addr)
{
char val;
int retval;
/* Set normal AUX CH command */
anx6345_i2c_read_p0_reg(client, DP_AUX_CH_CTL_2, &val);
val &= ~ADDR_ONLY;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_2, &val);
/* Set EDID device address */
val = device_addr;
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_7_0, &val);
val = 0;
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_15_8, &val);
anx6345_i2c_write_p0_reg(client, DP_AUX_ADDR_19_16, &val);
/* Set offset from base address of EDID device */
anx6345_i2c_write_p0_reg(client, BUF_DATA_0, &val_addr);
/*
* Set I2C transaction and write address
* If bit 3 is 1, DisplayPort transaction.
* If Bit 3 is 0, I2C transaction.
*/
val = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
AUX_TX_COMM_WRITE;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_1, &val);
/* Start AUX transaction */
retval = anx6345_start_aux_transaction(client);
if (retval != 0)
dev_dbg(&client->dev, "Aux Transaction fail!\n");
return retval;
}
int anx6345_edid_read_bytes(struct i2c_client *client,
unsigned int device_addr,
unsigned int val_addr,
unsigned char count,
unsigned char edid[])
{
char val;
unsigned int i;
unsigned int start_offset;
unsigned int cur_data_idx;
unsigned int cur_data_cnt;
unsigned int defer = 0;
int retval = 0;
for (i = 0; i < count; i += 16) {
start_offset = i;
if ((count - start_offset) > 16)
cur_data_cnt = 16;
else
cur_data_cnt = count - start_offset;
/*
* If Rx sends defer, Tx sends only reads
* request without sending addres
*/
if (!defer)
retval = anx6345_select_i2c_device(client,
device_addr, val_addr + i);
else
defer = 0;
/*
* Set I2C transaction and write data
* If bit 3 is 1, DisplayPort transaction.
* If Bit 3 is 0, I2C transaction.
*/
val = AUX_LENGTH(cur_data_cnt) | AUX_TX_COMM_I2C_TRANSACTION |
AUX_TX_COMM_READ;
anx6345_i2c_write_p0_reg(client, DP_AUX_CH_CTL_1, &val);
/* Start AUX transaction */
retval = anx6345_start_aux_transaction(client);
if (retval < 0)
dev_dbg(&client->dev, "Aux Transaction fail!\n");
/* Check if Rx sends defer */
anx6345_i2c_read_p0_reg(client, DP_AUX_RX_COMM, &val);
if (val == AUX_RX_COMM_AUX_DEFER ||
val == AUX_RX_COMM_I2C_DEFER) {
dev_err(&client->dev, "Defer: %d\n\n", val);
defer = 1;
}
for (cur_data_idx = 0; cur_data_idx < cur_data_cnt; cur_data_idx++) {
anx6345_i2c_read_p0_reg(client, BUF_DATA_0 + cur_data_idx, &val);
edid[i + cur_data_idx] = val;
dev_dbg(&client->dev, "0x%02x : 0x%02x\n", i + cur_data_idx, val);
}
}
return retval;
}
static int anx6345_read_edid(struct i2c_client *client)
{
unsigned char edid[EDID_LENGTH * 2];
unsigned char extend_block = 0;
unsigned char sum;
unsigned char test_vector;
int retval;
char addr;
struct edp_anx6345 *anx6345 = i2c_get_clientdata(client);
/* Read Extension Flag, Number of 128-byte EDID extension blocks */
retval = anx6345_edid_read_bytes(client, EDID_ADDR,
EDID_EXTENSION_FLAG,1,&extend_block);
if (retval < 0) {
dev_err(&client->dev, "EDID extension flag failed!\n");
return -EIO;
}
if (extend_block > 0) {
dev_dbg(&client->dev, "EDID data includes a single extension!\n");
/* Read EDID data */
retval = anx6345_edid_read_bytes(client, EDID_ADDR,
EDID_HEADER,
EDID_LENGTH,
&edid[EDID_HEADER]);
if (retval != 0) {
dev_err(&client->dev, "EDID Read failed!\n");
return -EIO;
}
sum = edp_calc_edid_check_sum(edid);
if (sum != 0) {
dev_warn(&client->dev, "EDID bad checksum!\n");
return 0;
}
/* Read additional EDID data */
retval = anx6345_edid_read_bytes(client, EDID_ADDR, EDID_LENGTH,
EDID_LENGTH, &edid[EDID_LENGTH]);
if (retval != 0) {
dev_err(&client->dev, "EDID Read failed!\n");
return -EIO;
}
sum = edp_calc_edid_check_sum(&edid[EDID_LENGTH]);
if (sum != 0) {
dev_warn(&client->dev, "EDID bad checksum!\n");
return 0;
}
retval = anx6345_dpcd_read_bytes(client, DPCD_TEST_REQUEST,
1, &test_vector);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID Read failed!\n");
return retval;
}
if (test_vector & DPCD_TEST_EDID_READ) {
retval = anx6345_dpcd_write_bytes(client,
DPCD_TEST_EDID_CHECKSUM,1,
&edid[EDID_LENGTH + EDID_CHECKSUM]);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID Write failed!\n");
return retval;
}
addr = DPCD_TEST_EDID_CHECKSUM_WRITE;
retval = anx6345_dpcd_write_bytes(client,
DPCD_TEST_RESPONSE, 1, &addr);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID checksum failed!\n");
return retval;
}
}
} else {
dev_info(&client->dev, "EDID data does not include any extensions.\n");
/* Read EDID data */
retval = anx6345_edid_read_bytes(client, EDID_ADDR, EDID_HEADER,
EDID_LENGTH, &edid[EDID_HEADER]);
if (retval != 0) {
dev_err(&client->dev, "EDID Read failed!\n");
return -EIO;
}
sum = edp_calc_edid_check_sum(edid);
if (sum != 0) {
dev_warn(&client->dev, "EDID bad checksum!\n");
return 0;
}
retval = anx6345_dpcd_read_bytes(client, DPCD_TEST_REQUEST,
1,&test_vector);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID Read failed!\n");
return retval;
}
if (test_vector & DPCD_TEST_EDID_READ) {
retval = anx6345_dpcd_write_bytes(client,
DPCD_TEST_EDID_CHECKSUM, 1,
&edid[EDID_CHECKSUM]);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID Write failed!\n");
return retval;
}
addr = DPCD_TEST_EDID_CHECKSUM_WRITE;
retval = anx6345_dpcd_write_bytes(client, DPCD_TEST_RESPONSE,
1, &addr);
if (retval < 0) {
dev_err(&client->dev, "DPCD EDID checksum failed!\n");
return retval;
}
}
}
fb_edid_to_monspecs(edid, &anx6345->specs);
dev_info(&client->dev, "EDID Read success!\n");
return 0;
}
static int anx6345_init(struct i2c_client *client)
{
@@ -744,7 +1084,8 @@ static int anx6345_init(struct i2c_client *client)
char i = 0;
char lc,bw;
char cnt = 50;
u8 buf[12];
val = 0x30;
anx6345_i2c_write_p1_reg(client,SP_POWERD_CTRL_REG,&val);
@@ -752,10 +1093,10 @@ static int anx6345_init(struct i2c_client *client)
for(i=0;i<50;i++)
{
anx6345_i2c_read_p0_reg(client, SP_TX_SYS_CTRL1_REG, &val);
anx6345_i2c_write_p0_reg(client, SP_TX_SYS_CTRL1_REG, &val);
anx6345_i2c_read_p0_reg(client, SP_TX_SYS_CTRL1_REG, &val);
if((val&SP_TX_SYS_CTRL1_DET_STA)!=0)
anx6345_i2c_read_p0_reg(client, SYS_CTRL1_REG, &val);
anx6345_i2c_write_p0_reg(client, SYS_CTRL1_REG, &val);
anx6345_i2c_read_p0_reg(client, SYS_CTRL1_REG, &val);
if((val&SYS_CTRL1_DET_STA)!=0)
{
break;
}
@@ -768,10 +1109,10 @@ static int anx6345_init(struct i2c_client *client)
//check whether clock is stable
for(i=0;i<50;i++)
{
anx6345_i2c_read_p0_reg(client, SP_TX_SYS_CTRL2_REG, &val);
anx6345_i2c_write_p0_reg(client,SP_TX_SYS_CTRL2_REG, &val);
anx6345_i2c_read_p0_reg(client, SP_TX_SYS_CTRL2_REG, &val);
if((val&SP_TX_SYS_CTRL2_CHA_STA)==0)
anx6345_i2c_read_p0_reg(client, SYS_CTRL2_REG, &val);
anx6345_i2c_write_p0_reg(client,SYS_CTRL2_REG, &val);
anx6345_i2c_read_p0_reg(client, SYS_CTRL2_REG, &val);
if((val&SYS_CTRL2_CHA_STA)==0)
{
break;
}
@@ -779,49 +1120,52 @@ static int anx6345_init(struct i2c_client *client)
}
if(i>49)
printk("clk is not stable\n");
anx6345_dpcd_read_bytes(client, DPCD_REV, 12, buf);
anx6345_read_edid(client);
//VESA range, 6bits BPC, RGB
val = 0x00;
anx6345_i2c_write_p1_reg(client, SP_TX_VID_CTRL2_REG, &val);
anx6345_i2c_write_p1_reg(client, VID_CTRL2_REG, &val);
//ANX6345 chip pll setting
val = 0x00;
anx6345_i2c_write_p0_reg(client, SP_TX_PLL_CTRL_REG, &val); //UPDATE: FROM 0X07 TO 0X00
anx6345_i2c_write_p0_reg(client, PLL_CTRL_REG, &val); //UPDATE: FROM 0X07 TO 0X00
//ANX chip analog setting
val = 0x70;
anx6345_i2c_write_p1_reg(client, ANALOG_DEBUG_REG1, &val); //UPDATE: FROM 0XF0 TO 0X70
val = 0x30;
anx6345_i2c_write_p0_reg(client, SP_TX_LINK_DEBUG_REG, &val);
anx6345_i2c_write_p0_reg(client, LINK_DEBUG_REG, &val);
//force HPD
//anx6345_i2c_write_p0_reg(client, SP_TX_SYS_CTRL3_REG, &val);
//anx6345_i2c_write_p0_reg(client, SYS_CTRL3_REG, &val);
//reset AUX
anx6345_i2c_read_p1_reg(client, SP_TX_RST_CTRL2_REG, &val);
val |= SP_TX_AUX_RST;
anx6345_i2c_write_p1_reg(client, SP_TX_RST_CTRL2_REG, &val);
val &= ~SP_TX_AUX_RST;
anx6345_i2c_write_p1_reg(client, SP_TX_RST_CTRL2_REG, &val);
anx6345_i2c_read_p1_reg(client, RST_CTRL2_REG, &val);
val |= AUX_RST;
anx6345_i2c_write_p1_reg(client, RST_CTRL2_REG, &val);
val &= ~AUX_RST;
anx6345_i2c_write_p1_reg(client, RST_CTRL2_REG, &val);
//Select 2.7G
val = 0x0a;
anx6345_i2c_write_p0_reg(client, SP_TX_LINK_BW_SET_REG, &val);
anx6345_i2c_write_p0_reg(client, LINK_BW_SET_REG, &val);
//Select 2 lanes
val = 0x02;
anx6345_i2c_write_p0_reg(client,SP_TX_LANE_COUNT_SET_REG,&val);
anx6345_i2c_write_p0_reg(client,LANE_COUNT_SET_REG,&val);
val = SP_TX_LINK_TRAINING_CTRL_EN;
anx6345_i2c_write_p0_reg(client, SP_TX_LINK_TRAINING_CTRL_REG, &val);
val = LINK_TRAINING_CTRL_EN;
anx6345_i2c_write_p0_reg(client, LINK_TRAINING_CTRL_REG, &val);
mdelay(5);
anx6345_i2c_read_p0_reg(client, SP_TX_LINK_TRAINING_CTRL_REG, &val);
anx6345_i2c_read_p0_reg(client, LINK_TRAINING_CTRL_REG, &val);
while((val&0x80)&&(cnt)) //UPDATE: FROM 0X01 TO 0X80
{
printk("Waiting...\n");
mdelay(5);
anx6345_i2c_read_p0_reg(client,SP_TX_LINK_TRAINING_CTRL_REG,&val);
anx6345_i2c_read_p0_reg(client,LINK_TRAINING_CTRL_REG,&val);
cnt--;
}
if(cnt <= 0)
@@ -842,15 +1186,15 @@ static int anx6345_init(struct i2c_client *client)
#else
val = 0x81;
#endif
anx6345_i2c_write_p1_reg(client,SP_TX_VID_CTRL1_REG,&val);
anx6345_i2c_write_p1_reg(client,VID_CTRL1_REG,&val);
anx_video_map_config(client);
//force HPD and stream valid
val = 0x33;
anx6345_i2c_write_p0_reg(client,SP_TX_SYS_CTRL3_REG,&val);
anx6345_i2c_write_p0_reg(client,SYS_CTRL3_REG,&val);
anx6345_i2c_read_p0_reg(client,SP_TX_LANE_COUNT_SET_REG, &lc);
anx6345_i2c_read_p0_reg(client,SP_TX_LINK_BW_SET_REG, &bw);
anx6345_i2c_read_p0_reg(client,LANE_COUNT_SET_REG, &lc);
anx6345_i2c_read_p0_reg(client,LINK_BW_SET_REG, &bw);
printk("%s..lc:%d--bw:%d\n",__func__,lc,bw);
return 0;

View File

@@ -0,0 +1,134 @@
#ifndef __DPCD_EDID_H
#define __DPCD_EDID_H
#include "../../edid.h"
#define DPCD_REV 0x00
#define DPCD_MAX_LINK_RATE 0x01
#define DPCD_MAX_LANE_CNT 0x02
#define DPCD_MAX_DOWNSPREAD 0x03
#define DPCD_NORP 0x04
#define DPCD_DOWNSTREAMPORT_PRESENT 0x05
#define DPCD_RECEIVE_PORT0_CAP_0 0x08
#define DPCD_RECEIVE_PORT0_CAP_1 0x09
#define DPCD_RECEIVE_PORT0_CAP_2 0x0a
#define DPCD_RECEIVE_PORT0_CAP_3 0x0b
#define DPCD_LINK_BW_SET 0x100
#define DPCD_LANE_CNT_SET 0x101
#define DPCD_TRAINING_PATTERN_SET 0x102
#define DPCD_TRAINING_LANE0_SET 0x103
#define DPCD_TRAINING_LANE1_SET 0x104
#define DPCD_TRAINING_LANE2_SET 0x105
#define DPCD_TRAINING_LANE3_SET 0x106
#define DPCD_DOWNSPREAD_CTRL 0x107
#define DPCD_SINK_COUNT 0x200
#define DPCD_DEVICE_SERVICE_IRQ_VECTOR 0x201
#define DPCD_LANE0_1_STATUS 0x202
#define DPCD_LANE2_3_STATUS 0x203
#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204
#define DPCD_SINK_STATUS 0x205
#define DPCD_ADJUST_REQUEST_LANE0_1 0x206
#define DPCD_ADJUST_REQUEST_LANE2_3 0x207
#define DPCD_TRAINING_SCORE_LANE0 0x208
#define DPCD_TRAINING_SCORE_LANE1 0x209
#define DPCD_TRAINING_SCORE_LANE2 0x20a
#define DPCD_TRAINING_SCORE_LANE3 0x20b
#define DPCD_SINK_POWER_STATE 0x0600
/* DPCD_ADDR_MAX_LANE_COUNT */
#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
/* DPCD_ADDR_LANE_COUNT_SET */
#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
/* DPCD_ADDR_TRAINING_PATTERN_SET */
#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
/* DPCD_ADDR_TRAINING_LANE0_SET */
#define DPCD_MAX_PRE_EMPHASIS_REACHED (0x1 << 5)
#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 (0x0 << 3)
#define DPCD_MAX_SWING_REACHED (0x1 << 2)
#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0 (0x0 << 0)
/* DPCD_ADDR_LANE0_1_STATUS */
#define DPCD_LANE_SYMBOL_LOCKED (0x1 << 2)
#define DPCD_LANE_CHANNEL_EQ_DONE (0x1 << 1)
#define DPCD_LANE_CR_DONE (0x1 << 0)
#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE| \
DPCD_LANE_CHANNEL_EQ_DONE|\
DPCD_LANE_SYMBOL_LOCKED)
#define DPCD_TEST_REQUEST 0x218
#define DPCD_TEST_LINK_RATE 0x219
#define DPCD_TEST_LANE_COUNT 0x220
#define DPCD_TEST_RESPONSE 0x260
#define DPCD_TEST_EDID_CHECKSUM 0x261
#define TEST_ACK 0x01
#define DPCD_TEST_EDID_Checksum_Write 0x04//bit position
#define DPCD_TEST_EDID_Checksum 0x261
#define DPCD_SPECIFIC_INTERRUPT 0x10
#define DPCD_USER_COMM1 0x22//define for downstream HDMI Rx sense detection
#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
/* DPCD_ADDR_TEST_REQUEST */
#define DPCD_TEST_EDID_READ (0x1 << 2)
/* DPCD_ADDR_TEST_RESPONSE */
#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
/* DPCD_ADDR_SINK_POWER_STATE */
#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
/*
* EDID device address is 0x50.
* However, if necessary, you must have set upper address
* into E-EDID in I2C device, 0x30.
*/
#define EDID_ADDR 0x50
#define E_EDID_ADDR 0x30
#define EDID_EXTENSION_FLAG 0x7e
#define EDID_CHECKSUM 0x7f
static unsigned char edp_calc_edid_check_sum(unsigned char *edid_data)
{
int i;
unsigned char sum = 0;
for (i = 0; i < EDID_LENGTH; i++)
sum = sum + edid_data[i];
return sum;
}
#endif