HDMI: modify code about reading EDID and add HDCP register define at rk3288 hdmi driver

This commit is contained in:
zwl
2014-03-12 21:27:17 +08:00
parent 35f085632d
commit eafd5f9be3
5 changed files with 178 additions and 55 deletions

View File

@@ -5,4 +5,4 @@
ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
obj-y += rk3288_hdmi_hw.o rk3288_hdmi.o
obj-$(CONFIG_HDCP_RK3288) += hdcp/
#obj-$(CONFIG_HDCP_RK3288) += hdcp/

View File

@@ -120,6 +120,27 @@ static const struct file_operations rk3288_hdmi_reg_fops = {
};
#endif
struct hdmi* rk3288_hdmi_register_hdcp_callbacks(
void (*hdcp_cb)(void),
void (*hdcp_irq_cb)(int status),
int (*hdcp_power_on_cb)(void),
void (*hdcp_power_off_cb)(void))
{
struct hdmi *hdmi_drv = NULL;
if(hdmi_dev == NULL)
return NULL;
hdmi_drv = &hdmi_dev->driver;
hdmi_drv->hdcp_cb = hdcp_cb;
hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
return hdmi_drv;
}
static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
{
int ret = 0;

View File

@@ -7,5 +7,11 @@
#define ENABLE 16
#define HDMI_SEL_LCDC(x) ((((x)&1)<<4)|(1<<(4+ENABLE)))
extern struct hdmi* rk3288_hdmi_register_hdcp_callbacks(
void (*hdcp_cb)(void),
void (*hdcp_irq_cb)(int status),
int (*hdcp_power_on_cb)(void),
void (*hdcp_power_off_cb)(void));
#endif /* __RK3288_HDMI_H__ */

View File

@@ -79,7 +79,8 @@ int rk3288_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
{
int i = 0,index = 0,interrupt = 0,ret = -1,trytime = 2;
int i = 0, n = 0, index = 0, interrupt = 0, ret = -1, trytime = 2;
int offset = (block%2)*0x80;
unsigned long flags;
struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
@@ -94,57 +95,65 @@ int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
hdmi_msk_reg(hdmi_dev, I2CM_DIV, m_I2CM_FAST_STD_MODE, v_I2CM_FAST_STD_MODE(STANDARD_MODE)); //Set Standard Mode
//Enable edid interrupt
hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, v_SCDC_READREQ_MUTE(0) | v_I2CM_DONE_MUTE(0) | v_I2CM_ERR_MUTE(0));
//hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, v_SCDC_READREQ_MUTE(0) | v_I2CM_DONE_MUTE(0) | v_I2CM_ERR_MUTE(0));
//hdmi_writel(hdmi_dev, I2CM_SLAVE,); //TODO Daisen wait to add!!
hdmi_writel(hdmi_dev, I2CM_SLAVE, DDC_I2C_EDID_ADDR);
hdmi_writel(hdmi_dev, I2CM_SEGADDR, DDC_I2C_SEG_ADDR);
while(trytime--) {
// Config EDID block and segment addr
hdmi_writel(hdmi_dev, I2CM_SEGADDR, (block%2) * 0x80);
hdmi_writel(hdmi_dev, I2CM_SEGPTR, block/2);
//enable Extended sequential read operation
hdmi_msk_reg(hdmi_dev, I2CM_OPERATION, m_I2CM_RD8_EXT, v_I2CM_RD8_EXT(1));
for(n = 0; n < HDMI_EDID_BLOCK_SIZE/8; n++) {
// Config EDID block and segment addr
hdmi_writel(hdmi_dev, I2CM_SEGPTR, block/2);
hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset + 8*n);
//enable extend sequential read operation
hdmi_msk_reg(hdmi_dev, I2CM_OPERATION, m_I2CM_RD8_EXT, v_I2CM_RD8_EXT(1));
i = 100;
while(i--)
{
spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
interrupt = hdmi_dev->edid_status;
hdmi_dev->edid_status = 0;
spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR))
i = 200;
while(i--)
{
spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
interrupt = hdmi_dev->edid_status;
hdmi_dev->edid_status = 0;
spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR))
break;
msleep(5);
}
if((i == 0) || (interrupt & m_I2CM_ERROR)) {
hdmi_err(hdmi_drv->dev, "[%s] edid read error\n", __FUNCTION__);
rk3288_hdmi_i2cm_reset(hdmi_dev);
break;
msleep(10);
}
if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE)) {
for(i = 0; i < HDMI_EDID_BLOCK_SIZE/8; i++) {
for(index = 0; index < 8; index++)
buff[i] = hdmi_readl(hdmi_dev, I2CM_READ_BUFF0 + index);
}
ret = 0;
hdmi_dbg(hdmi_drv->dev, "[%s] edid read sucess\n", __FUNCTION__);
#ifdef HDMI_DEBUG
for(i = 0; i < 128; i++) {
printk("%02x ,", buff[i]);
if( (i + 1) % 16 == 0)
printk("\n");
}
#endif
break;
}
if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE)) {
for(index = 0; index < 8; index++) {
buff[8*n + index] = hdmi_readl(hdmi_dev, I2CM_READ_BUFF0 + index);
}
continue;
if(interrupt & m_I2CM_ERROR) {
hdmi_err(hdmi_drv->dev, "[%s] edid read error\n", __FUNCTION__);
rk3288_hdmi_i2cm_reset(hdmi_dev);
if(n == HDMI_EDID_BLOCK_SIZE/8 - 1) {
ret = 0;
hdmi_dbg(hdmi_drv->dev, "[%s] edid read sucess\n", __FUNCTION__);
#ifdef HDMI_DEBUG
for(i = 0; i < 128; i++) {
printk("%02x ,", buff[i]);
if( (i + 1) % 16 == 0)
printk("\n");
}
#endif
goto exit;
}
}
}
hdmi_dbg(hdmi_drv->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
msleep(100);
}
exit:
// Disable edid interrupt
hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, v_SCDC_READREQ_MUTE(1) | v_I2CM_DONE_MUTE(1) | v_I2CM_ERR_MUTE(1)); //TODO Daisen HDCP enable it??
//hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, v_SCDC_READREQ_MUTE(1) | v_I2CM_DONE_MUTE(1) | v_I2CM_ERR_MUTE(1));
return ret;
}

View File

@@ -10,9 +10,25 @@ enum {
OUTPUT_DVI = 0,
OUTPUT_HDMI,
};
enum{
INPUT_IIS,
INPUT_SPDIF
};
/* Color Space Convertion Mode */
enum {
CSC_RGB_0_255_TO_ITU601_16_235 = 0, //RGB 0-255 input to YCbCr 16-235 output according BT601
CSC_RGB_0_255_TO_ITU709_16_235, //RGB 0-255 input to YCbCr 16-235 output accroding BT709
CSC_ITU601_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT601
CSC_ITU709_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT709
CSC_ITU601_16_235_TO_RGB_0_255, //YCbCr 16-235 input to RGB 0-255 output according BT601
CSC_ITU709_16_235_TO_RGB_0_255 //YCbCr 16-235 input to RGB 0-255 output according BT709
};
#define HDMI_SCL_RATE (100*1000)
#define HDMI_SCL_RATE (100*1000)
#define DDC_I2C_EDID_ADDR 0x50 // 0xA0/2 = 0x50
#define DDC_I2C_SEG_ADDR 0x30 // 0x60/2 = 0x30
/*Register and Field Descriptions*/
/*Identification Registers*/
@@ -994,19 +1010,96 @@ enum {
#define HDCP_ENCRYPTION_ENGINE_BASE 0x5000
#define A_HDCPCFG0 0x5000
#define m_HDCP_ENHANCE_LIKE (1 << 7)
#define v_HDCP_ENHANCE_LIKE(n) (((n)&0x01) << 7)
#define m_I2C_FAST_MODE (1 << 6)
#define v_I2C_FAST_MODE(n) (((n)&0x01) << 6)
#define m_ENCRYPT_BYPASS (1 << 5)
#define v_ENCRYPT_BYPASS(n) (((n)&0x01) << 5)
#define m_SYNC_RI_CHECK (1 << 4)
#define v_SYNC_RI_CHECK(n) (((n)&0x01) << 4)
#define m_AVMUTE (1 << 3)
#define m_RX_DETECT (1 << 2)
#define v_RX_DETECT(n) (((n)&0x01) << 2)
#define m_FEATURE11_EN (1 << 1)
#define v_FEATURE11_EN(n) (((n)&0x01) << 1)
#define m_HDMI_DVI (1 << 0)
#define v_HDMI_DVI(n) (((n)&0x01) << 0)
#define A_HDCPCFG1 0x5001
#define m_HDCP_LOCK (1 << 4)
#define v_HDCP_LOCK(n) (((n)&0x01) << 4)
#define m_SHA1_CHECK_DISABLE (1 << 3)
#define v_SHA1_CHECK_DISBALE(n) (((n)&0x01) << 3)
#define m_PH2UPSHFTENC (1 << 2)
#define v_PH2UPSHFTENC(n) (((n)&0x01) << 2)
#define m_ENCRYPT_DISBALE (1 << 1)
#define v_ENCRYPT_DISBALE(n) (((n)&0x01) << 1)
#define m_HDCP_SW_RST (1 << 0)
#define v_HDCP_SW_RST(n) (((n)&0x01) << 0)
#define A_HDCPOBS0 0x5002
#define m_STATE_AUTH (0x0f << 4)
#define m_SUB_STATE_AUTH (0x07 << 1)
#define m_STATE_HDCP_ENGAGED (1 << 0)
#define A_HDCPOBS1 0x5003
#define m_STATE_OESS (0x07 << 3)
#define m_STATE_REVO (0x07 << 0)
#define A_HDCPOBS2 0x5004
#define m_STATE_CIPHER (0x07 << 3)
#define m_STATE_EESS (0x07 << 0)
#define A_HDCPOBS3 0x5005
#define m_BCAP_REPEATER (1 << 6)
#define m_BCAP_KSVFIFO_READY (1 << 5)
#define m_BCAP_FAST_I2C (1 << 4)
#define m_BCAP_HDMI_MODE (1 << 2)
#define m_BCAP_FEATURES11 (1 << 1)
#define m_BCAP_FAST_REAUTH (1 << 0)
#define A_APIINTCLR 0x5006
#define A_APIINTSTAT 0x5007
#define A_APIINTMSK 0x5008
#define m_HDCP_ENGAGED (1 << 7)
#define m_HDCP_FAILED (1 << 6)
#define m_HDCP_I2C_NOACK (1 << 4)
#define m_HDCP_LOST_ARBI (1 << 3)
#define m_KEEP_ERR_INT (1 << 2)
#define m_KSVSHA1_CALC_INT (1 << 1)
#define m_KSV_ACCESS_INT (1 << 0)
#define v_HDCP_ENGAGED(n) (((n)&0x01) << 7)
#define v_HDCP_FAILED(n) (((n)&0x01) << 6)
#define v_HDCP_I2C_NOACK(n) (((n)&0x01) << 4)
#define v_HDCP_LOST_ARBI(n) (((n)&0x01) << 3)
#define v_KEEP_ERR_INT(n) (((n)&0x01) << 1)
#define v_KSVSHA1_CALC_INT(n) (((n)&0x01) << 1)
#define v_KSV_ACCESS_INT(n) (((n)&0x01) << 0)
#define A_VIDPOLCFG 0x5009
#define m_UNENCRYT_CONF (0x03 << 5)
#define v_UNENCRYT_CONF(n) (((n)&0x03) << 5)
#define m_DATAEN_POL (1 << 4)
#define v_DATAEN_POL(n) (((n)&0x01) << 4)
#define m_VSYNC_POL (1 << 3)
#define v_VSYNC_POL(n) (((n)&0x01) << 3)
#define m_HSYNC_POL (1 << 1)
#define v_HSYNC_POL(n) (((n)&0x01) << 1)
#define A_OESSWCFG 0x500a
#define A_COREVERLSB 0x5014
#define A_COREVERMSB 0x5015
#define A_KSVMEMCTRL 0x5016
#define m_SHA1_FAIL (1 << 3)
#define v_SHA1_FAIL(n) (((n)&0x01) << 3)
#define m_KSV_UPDATE (1 << 2)
#define v_KSV_UPDATE(n) (((n)&0x01) << 2)
#define m_KSV_MEM_ACCESS (1 << 1)
#define m_KSV_MEM_REQ (1 << 0)
#define v_KSV_MEM_REQ(n) (((n)&0x01) << 0)
#define HDCP_BSTATUS_0 0x5020
#define HDCP_BSTATUS_1 0x5021
#define HDCP_M0_0 0x5022
@@ -1038,6 +1131,9 @@ enum {
#define HDCP_AN_BASE 0x7805
#define HDCPREG_ANCONF 0x7805
#define m_OAN_BYPASS (1 << 0)
#define v_OAN_BYPASS(n) (((n)&0x01) << 0)
#define HDCPREG_AN0 0x7806
#define HDCPREG_AN1 0x7807
#define HDCPREG_AN2 0x7808
@@ -1052,7 +1148,13 @@ enum {
#define ENCRYPTED_DPK_EMBEDDED_BASE 0x780e
#define HDCPREG_RMCTL 0x780e
#define m_DPK_DECRYPT_EN (1 << 0)
#define v_DPK_DECRYPT_EN(n) (((n)&0x01) <<0)
#define HDCPREG_RMSTS 0x780f
#define m_DPK_WR_OK_STS (1 << 6)
#define m_DPK_DATA_INDEX (0x3f << 6)
#define HDCPREG_SEED0 0x7810
#define HDCPREG_SEED1 0x7811
#define HDCPREG_DPK0 0x7812
@@ -1235,21 +1337,6 @@ struct phy_mpll_config_tab {
enum{
INPUT_IIS,
INPUT_SPDIF
};
/* Color Space Convertion Mode */
enum {
CSC_RGB_0_255_TO_ITU601_16_235 = 0, //RGB 0-255 input to YCbCr 16-235 output according BT601
CSC_RGB_0_255_TO_ITU709_16_235, //RGB 0-255 input to YCbCr 16-235 output accroding BT709
CSC_ITU601_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT601
CSC_ITU709_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT709
CSC_ITU601_16_235_TO_RGB_0_255, //YCbCr 16-235 input to RGB 0-255 output according BT601
CSC_ITU709_16_235_TO_RGB_0_255 //YCbCr 16-235 input to RGB 0-255 output according BT709
};
struct rk3288_hdmi_reg_table {
int reg_base;
int reg_end;