mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk30: hdmi sometimes read edid failed, fix it.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include "rk30_hdmi.h"
|
||||
#include "rk30_hdmi_hw.h"
|
||||
|
||||
static char interrupt1 = 0, interrupt2 = 0, interrupt3 = 0, interrupt4 = 0;
|
||||
static char edid_result = 0;
|
||||
|
||||
static inline void delay100us(void)
|
||||
{
|
||||
@@ -61,13 +61,15 @@ int rk30_hdmi_read_edid(int block, unsigned char *buff)
|
||||
char interrupt = 0, trytime = 2;
|
||||
|
||||
hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
|
||||
|
||||
//Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
|
||||
// disable_irq(hdmi->irq);
|
||||
spin_lock(&hdmi->irq_lock);
|
||||
edid_result = 0;
|
||||
spin_unlock(&hdmi->irq_lock);
|
||||
//Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 24MHz.
|
||||
//Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
|
||||
ddc_bus_freq = (30000000/HDMI_EDID_DDC_CLK)/4;
|
||||
ddc_bus_freq = (24000000/HDMI_EDID_DDC_CLK)/4;
|
||||
HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
|
||||
HDMIWrReg(DDC_BUS_FREQ_L, (ddc_bus_freq >> 8) & 0xFF);
|
||||
msleep(10);
|
||||
HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
|
||||
|
||||
// Enable edid interrupt
|
||||
HDMIMskReg(value, INTR_MASK1, (m_INT_EDID_ERR | m_INT_EDID_READY), (m_INT_EDID_ERR | m_INT_EDID_READY));
|
||||
@@ -81,14 +83,12 @@ int rk30_hdmi_read_edid(int block, unsigned char *buff)
|
||||
while(value--)
|
||||
{
|
||||
spin_lock(&hdmi->irq_lock);
|
||||
interrupt = interrupt1;
|
||||
interrupt = edid_result;
|
||||
// interrupt = HDMIRdReg(INTR_STATUS1);
|
||||
spin_unlock(&hdmi->irq_lock);
|
||||
// hdmi_dbg(hdmi->dev, "[%s] interrupt %02x value %d\n", __FUNCTION__, interrupt, value);
|
||||
if(interrupt & (m_INT_EDID_ERR | m_INT_EDID_READY))
|
||||
{
|
||||
interrupt1 &= ~(m_INT_EDID_ERR | m_INT_EDID_READY);
|
||||
break;
|
||||
}
|
||||
msleep(10);
|
||||
}
|
||||
hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
|
||||
@@ -114,7 +114,8 @@ int rk30_hdmi_read_edid(int block, unsigned char *buff)
|
||||
}
|
||||
// Disable edid interrupt
|
||||
HDMIMskReg(value, INTR_MASK1, (m_INT_EDID_ERR|m_INT_EDID_READY), 0);
|
||||
|
||||
msleep(100);
|
||||
// enable_irq(hdmi->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -426,10 +427,11 @@ int rk30_hdmi_removed(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
{
|
||||
char interrupt1 = 0, interrupt2 = 0, interrupt3 = 0, interrupt4 = 0;
|
||||
|
||||
spin_lock(&hdmi->irq_lock);
|
||||
if(hdmi->pwr_mode == PWR_SAVE_MODE_A)
|
||||
{
|
||||
hdmi_dbg(hdmi->dev, "hdmi irq wake up\n");
|
||||
@@ -438,15 +440,12 @@ irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
|
||||
// HDMI was inserted when system is sleeping, irq was triggered only once
|
||||
// when wake up. So we need to check hotplug status.
|
||||
if((rk30_hdmi_detect_hotplug() == HDMI_HPD_INSERT)) {
|
||||
if(hdmi->state == HDMI_SLEEP)
|
||||
hdmi->state = WAIT_HOTPLUG;
|
||||
if((rk30_hdmi_detect_hotplug() == HDMI_HPD_INSERT)) {
|
||||
queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spin_lock(&hdmi->irq_lock);
|
||||
interrupt1 = HDMIRdReg(INTR_STATUS1);
|
||||
interrupt2 = HDMIRdReg(INTR_STATUS2);
|
||||
interrupt3 = HDMIRdReg(INTR_STATUS3);
|
||||
@@ -455,7 +454,7 @@ irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
HDMIWrReg(INTR_STATUS2, interrupt2);
|
||||
HDMIWrReg(INTR_STATUS3, interrupt3);
|
||||
HDMIWrReg(INTR_STATUS4, interrupt4);
|
||||
#if 1
|
||||
#if 0
|
||||
hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x interrupt2 %02x interrupt3 %02x interrupt4 %02x\n",\
|
||||
__FUNCTION__, interrupt1, interrupt2, interrupt3, interrupt4);
|
||||
#endif
|
||||
@@ -466,13 +465,15 @@ irqreturn_t hdmi_irq(int irq, void *priv)
|
||||
interrupt1 &= ~(m_INT_HOTPLUG | m_INT_MSENS);
|
||||
queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
|
||||
}
|
||||
else if(interrupt1 & (m_INT_EDID_READY | m_INT_EDID_ERR))
|
||||
edid_result = interrupt1;
|
||||
else if(hdmi->state == HDMI_SLEEP) {
|
||||
hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
|
||||
HDMIWrReg(SYS_CTRL, 0x10);
|
||||
hdmi->pwr_mode = PWR_SAVE_MODE_A;
|
||||
}
|
||||
spin_unlock(&hdmi->irq_lock);
|
||||
}
|
||||
spin_unlock(&hdmi->irq_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,16 +124,17 @@ static int hdmi_process_command(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if(state == HDMI_SLEEP)
|
||||
state = WAIT_HOTPLUG;
|
||||
return state;
|
||||
}
|
||||
|
||||
void hdmi_work(struct work_struct *work)
|
||||
{
|
||||
int hotplug, state_last, state;
|
||||
int hotplug, state_last;
|
||||
int rc = HDMI_ERROR_SUCESS, trytimes = 0;
|
||||
/* Process hdmi command */
|
||||
state = hdmi_process_command();
|
||||
hdmi->state = hdmi_process_command();
|
||||
|
||||
if(!hdmi->enable)
|
||||
return;
|
||||
@@ -144,7 +145,7 @@ void hdmi_work(struct work_struct *work)
|
||||
{
|
||||
hdmi->hotplug = hotplug;
|
||||
if(hdmi->hotplug == HDMI_HPD_INSERT)
|
||||
state = READ_PARSE_EDID;
|
||||
hdmi->state = READ_PARSE_EDID;
|
||||
else {
|
||||
hdmi_sys_remove();
|
||||
kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
|
||||
@@ -152,14 +153,14 @@ void hdmi_work(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
do {
|
||||
state_last = state;
|
||||
switch(state)
|
||||
state_last = hdmi->state;
|
||||
switch(hdmi->state)
|
||||
{
|
||||
case READ_PARSE_EDID:
|
||||
rc = hdmi_sys_parse_edid(hdmi);
|
||||
if(rc == HDMI_ERROR_SUCESS)
|
||||
{
|
||||
state = SYSTEM_CONFIG;
|
||||
hdmi->state = SYSTEM_CONFIG;
|
||||
kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
|
||||
}
|
||||
break;
|
||||
@@ -170,23 +171,23 @@ void hdmi_work(struct work_struct *work)
|
||||
hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
|
||||
rc = hdmi_switch_fb(hdmi, hdmi->vic);
|
||||
if(rc == HDMI_ERROR_SUCESS)
|
||||
state = CONFIG_VIDEO;
|
||||
hdmi->state = CONFIG_VIDEO;
|
||||
break;
|
||||
case CONFIG_VIDEO:
|
||||
rc = rk30_hdmi_config_video(hdmi->vic, VIDEO_OUTPUT_RGB444, hdmi->edid.sink_hdmi);
|
||||
if(rc == HDMI_ERROR_SUCESS)
|
||||
{
|
||||
if(hdmi->edid.sink_hdmi)
|
||||
state = CONFIG_AUDIO;
|
||||
hdmi->state = CONFIG_AUDIO;
|
||||
else
|
||||
state = PLAY_BACK;
|
||||
hdmi->state = PLAY_BACK;
|
||||
}
|
||||
break;
|
||||
case CONFIG_AUDIO:
|
||||
rc = rk30_hdmi_config_audio(&(hdmi->audio));
|
||||
|
||||
if(rc == HDMI_ERROR_SUCESS)
|
||||
state = PLAY_BACK;
|
||||
hdmi->state = PLAY_BACK;
|
||||
break;
|
||||
case PLAY_BACK:
|
||||
rk30_hdmi_control_output(1);
|
||||
@@ -203,16 +204,15 @@ void hdmi_work(struct work_struct *work)
|
||||
trytimes++;
|
||||
msleep(10);
|
||||
}
|
||||
if(state != state_last)
|
||||
if(hdmi->state != state_last)
|
||||
trytimes = 0;
|
||||
|
||||
hdmi_sys_show_state(state);
|
||||
}while((state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
|
||||
hdmi_sys_show_state(hdmi->state);
|
||||
}while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
|
||||
|
||||
if(trytimes == HDMI_MAX_TRY_TIMES)
|
||||
{
|
||||
if(hdmi->hotplug)
|
||||
hdmi_sys_remove();
|
||||
}
|
||||
hdmi->state = state;
|
||||
}
|
||||
Reference in New Issue
Block a user