rk32-hdmi: add support use poll mode to check interrupt

This commit is contained in:
zwl
2014-03-23 21:05:16 +08:00
parent e63ea49ded
commit e8d191fda0
4 changed files with 54 additions and 27 deletions

View File

@@ -359,7 +359,7 @@
};
&i2c5 {
status = "okay";
status = "disable";
};
&fb {

View File

@@ -141,6 +141,22 @@ struct hdmi* rk3288_hdmi_register_hdcp_callbacks(
return hdmi_drv;
}
#ifdef HDMI_INT_USE_POLL
static void rk3288_poll_delay_work(struct work_struct *work)
{
struct hdmi *hdmi_drv = &hdmi_dev->driver;
if(hdmi_drv->suspend == 0) {
if(hdmi_drv->enable == 1) {
hdmi_irq(0, hdmi_drv);
}
if(hdmi_dev->irq == 0) {
queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->delay_work, 100);
}
}
}
#endif
static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
{
int ret = 0;
@@ -253,6 +269,7 @@ static int rk3288_hdmi_probe(struct platform_device *pdev)
switch_dev_register(&(dev_drv->switch_hdmi));
#endif
#ifndef HDMI_INT_USE_POLL
/* get and request the IRQ */
dev_drv->irq = platform_get_irq(pdev, 0);
if(dev_drv->irq <= 0) {
@@ -261,11 +278,16 @@ static int rk3288_hdmi_probe(struct platform_device *pdev)
goto err2;
}
//ret = devm_request_irq(hdmi_dev->dev, dev_drv->irq, hdmi_irq, 0, dev_name(hdmi_dev->dev), dev_drv);
ret = devm_request_irq(hdmi_dev->dev, dev_drv->irq, hdmi_irq, 0, dev_name(hdmi_dev->dev), dev_drv);
if (ret) {
dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
goto err2;
}
#else
hdmi_dev->irq = 0;
INIT_DELAYED_WORK(&hdmi_dev->delay_work, rk3288_poll_delay_work);
queue_delayed_work(dev_drv->workqueue, &hdmi_dev->delay_work, msecs_to_jiffies(1));
#endif
#if defined(CONFIG_DEBUG_FS)
hdmi_dev->debugfs_dir = debugfs_create_dir("rk3288-hdmi", NULL);
@@ -277,9 +299,6 @@ static int rk3288_hdmi_probe(struct platform_device *pdev)
#endif
dev_info(hdmi_dev->dev, "rk3288 hdmi probe sucess.\n");
dev_drv->state = WAIT_HOTPLUG;
dev_drv->tmdsclk = 74250000;
queue_delayed_work(dev_drv->workqueue, &dev_drv->delay_work, msecs_to_jiffies(5));
return 0;
err2:

View File

@@ -59,8 +59,8 @@ static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
hdmi_writel(hdmi_dev, MC_CLKDIS, 0x00);
break;
case LOWER_PWR:
//hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE,
//v_AUDCLK_DISABLE(1) | v_PREPCLK_DISABLE(1) | v_TMDSCLK_DISABLE(1) | v_PIXELCLK_DISABLE(1));
hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE,
v_AUDCLK_DISABLE(1) | v_PREPCLK_DISABLE(1) | v_TMDSCLK_DISABLE(1) | v_PIXELCLK_DISABLE(1));
//hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(0));
break;
default:
@@ -73,7 +73,7 @@ static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
void rk3288_hdmi_i2cm_reset(struct rk3288_hdmi_device *hdmi_dev)
{
hdmi_msk_reg(hdmi_dev, I2CM_SOFTRSTZ, m_I2CM_SOFTRST, v_I2CM_SOFTRST(0));
udelay(200);
udelay(100);
}
void rk3288_hdmi_reset(struct hdmi *hdmi_drv)
@@ -86,28 +86,31 @@ void rk3288_hdmi_reset(struct hdmi *hdmi_drv)
hdmi_writel(hdmi_dev, MC_SWRSTZREQ_2, 0x00);
udelay(100);
hdmi_writel(hdmi_dev, MC_SWRSTZREQ_2, 0x01);
rk3288_hdmi_i2cm_reset(hdmi_dev);
//hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(1));
hdmi_msk_reg(hdmi_dev, PHY_I2CM_DIV, m_PHY_I2CM_FAST_STD, v_PHY_I2CM_FAST_STD(0));
#if 0
//reset PHY
hdmi_writel(hdmi_dev, PHY_CONF0, 0x3a);
hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
msleep(5);
udelay(100);
hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
hdmi_writel(hdmi_dev, PHY_CONF0, 0x6e);
#endif
rk3288_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
}
int rk3288_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
{
//struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
//u32 value = hdmi_readl(hdmi_dev,PHY_STAT0);
struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
u32 value = hdmi_readl(hdmi_dev, PHY_STAT0);
//hdmi_dbg(hdmi_drv->dev, "[%s] reg%x value %02x\n", __FUNCTION__, PHY_STAT0, value);
hdmi_dbg(hdmi_drv->dev, "[%s] reg%x value %02x\n", __FUNCTION__, PHY_STAT0, value);
//if(value & m_PHY_HPD)
if((value & m_PHY_HPD) || ((value & 0xf0) == 0xf0))
return HDMI_HPD_ACTIVED;
//else
//return HDMI_HPD_REMOVED;
else
return HDMI_HPD_REMOVED;
}
int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
@@ -119,9 +122,9 @@ int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
return -1;
hdmi_dbg(hdmi_drv->dev, "[%s] block %d\n", __FUNCTION__, block);
spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
//spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
hdmi_dev->i2cm_int = 0;
spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
//spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
//Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
hdmi_writel(hdmi_dev, I2CM_SS_SCL_HCNT_0_ADDR, 0x7a);
@@ -146,10 +149,10 @@ int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
i = 200;
while(i--)
{
spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
//spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
interrupt = hdmi_dev->i2cm_int;
hdmi_dev->i2cm_int = 0;
spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
//spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR))
break;
msleep(5);
@@ -237,6 +240,8 @@ static int rk3288_hdmi_video_frameComposer(struct hdmi *hdmi_drv, struct hdmi_vi
}
hdmi_drv->tmdsclk = mode->pixclock;
rk3288_hdmi_config_phy(hdmi_drv);
if(hdmi_drv->tmdsclk > 340000000) { //used for HDMI 2.0 TX //TODO Daisen wait to modify HDCP KEEPOUT
hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_HDCP_KEEPOUT, v_FC_HDCP_KEEPOUT(1));
hdmi_msk_reg(hdmi_dev, FC_SCRAMBLER_CTRL, m_FC_SCRAMBLE_EN, v_FC_SCRAMBLE_EN(1));
@@ -475,7 +480,7 @@ static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_ad
return -1;
}
static int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
{
int stat = 0, i = 0;
char pix_repet = NO_PIXEL_REPET;
@@ -759,7 +764,6 @@ int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpar
hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __FUNCTION__);
}
rk3288_hdmi_config_phy(hdmi_drv);
rk3288_hdmi_control_output(hdmi_drv, 0);
return 0;
}
@@ -992,10 +996,8 @@ irqreturn_t hdmi_irq(int irq, void *priv)
hdmi_writel(hdmi_dev, IH_AHBDMAAUD_STAT0, aud_dma_int);
//hdmi_writel(hdmi_dev, A_APIINTCLR, hdcp_int);
//HPD
if((phy_int & m_HPD)
//|| ((phy_int & 0x3c) == 0x3c)
) {
//HPD or RX_SENSE
if((phy_int & m_HPD) || ((phy_int & 0x3c) == 0x3c)) {
if(hdmi_drv->state == HDMI_SLEEP)
hdmi_drv->state = WAIT_HOTPLUG;
queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, msecs_to_jiffies(5));

View File

@@ -2,6 +2,8 @@
#define _RK3288_HDMI_HW_H
#include "../../rk_hdmi.h"
#define HDMI_INT_USE_POLL 1 //TODO Daisen wait to modify
enum PWR_MODE{
NORMAL,
LOWER_PWR,
@@ -1409,6 +1411,9 @@ struct rk3288_hdmi_device {
struct clk *pclk; //HDMI AHP clk
struct hdmi driver;
struct dentry *debugfs_dir;
#ifdef HDMI_INT_USE_POLL
struct delayed_work delay_work;
#endif
};
@@ -1436,6 +1441,7 @@ static inline int hdmi_msk_reg(struct rk3288_hdmi_device *hdmi_dev, u16 offset,
int rk3288_hdmi_initial(struct hdmi *hdmi_drv);
void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable);
int rk3288_hdmi_config_phy(struct hdmi * hdmi_drv);
#endif