From e8c67fc8741245c34c770598d7666c75229bffa1 Mon Sep 17 00:00:00 2001 From: yzq Date: Wed, 2 May 2012 01:03:56 -0700 Subject: [PATCH] rk610 hdmi fix some problem --- drivers/video/hdmi/chips/rk610/rk610_hdmi.c | 2 + .../video/hdmi/chips/rk610/rk610_hdmi_hw.c | 76 ++++++++++++------- .../video/hdmi/chips/rk610/rk610_hdmi_hw.h | 9 ++- drivers/video/hdmi/hdmi-codec.c | 2 +- drivers/video/rk29_fb.c | 10 ++- include/linux/rk_screen.h | 11 ++- 6 files changed, 76 insertions(+), 34 deletions(-) diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi.c b/drivers/video/hdmi/chips/rk610/rk610_hdmi.c index 72b29189e941..d9c6fcaa5006 100644 --- a/drivers/video/hdmi/chips/rk610/rk610_hdmi.c +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi.c @@ -64,6 +64,7 @@ static int rk610_hdmi_insert(struct hdmi *hdmi) RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); if(rk610_hdmi->init == 1) return -1; + Rk610_hdmi_plug(rk610_hdmi->client); rk610_hdmi_param_chg(rk610_hdmi); hdmi_set_spk(HDMI_DISABLE); printk("rk610_hdmi_insert hdmi->display_on=%d\n",hdmi->display_on); @@ -78,6 +79,7 @@ static int rk610_hdmi_remove(struct hdmi *hdmi) return -1; hdmi_set_spk(HDMI_ENABLE); hdmi_switch_fb(hdmi, HDMI_DISABLE); + Rk610_hdmi_unplug(rk610_hdmi->client); printk("rk610_hdmi_remove hdmi->display_on=%d\n",hdmi->display_on); return 0; } diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c index ac8c3984c47d..d3c72aca9e09 100644 --- a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c @@ -9,8 +9,8 @@ static struct edid_result Rk610_edid_result; byte DoEdidRead (struct i2c_client *client); static int RK610_hdmi_soft_reset(struct i2c_client *client); static int Rk610_hdmi_Display_switch(struct i2c_client *client); -static void Rk610_hdmi_plug(struct i2c_client *client); -static void Rk610_hdmi_unplug(struct i2c_client *client); +static int Rk610_hdmi_sys_power_up(struct i2c_client *client); +static int Rk610_hdmi_sys_power_down(struct i2c_client *client); static int Rk610_hdmi_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val) { @@ -20,25 +20,42 @@ static int Rk610_hdmi_i2c_write_p0_reg(struct i2c_client *client, char reg, char { return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; } - +static int RK610_hdmi_audio_mute(struct i2c_client *client,bool enable) +{ + char c; + int ret=0; + c = ((~enable)&1)<<1; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x05, &c); +} static int Rk610_hdmi_pwr_mode(struct i2c_client *client, int mode) { char c; int ret=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); switch(mode){ case NORMAL: + Rk610_hdmi_sys_power_down(client); + c=0x82; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); c=0x00; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c); c=0x00; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c); c=0x8e; - ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c); - c=0x00; - ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); - c=0x82; - ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); - break; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xce, &c); + c=0x01; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xce, &c); + RK610_hdmi_audio_mute(client,1); + Rk610_hdmi_sys_power_up(client); + g_hw_inf.analog_sync = 1; + break; case LOWER_PWR: + RK610_hdmi_audio_mute(client,0); + Rk610_hdmi_sys_power_down(client); c=0x02; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); c=0x1c; @@ -49,7 +66,7 @@ static int Rk610_hdmi_pwr_mode(struct i2c_client *client, int mode) ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c); c=0x03; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c); - break; + break; default: RK610_ERR(&client->dev,"unkown rk610 hdmi pwr mode %d\n",mode); } @@ -84,21 +101,21 @@ int Rk610_hdmi_resume(struct i2c_client *client) return ret; } #endif -static int Rk610_hdmi_sys_power_down(struct i2c_client *client) +static int Rk610_hdmi_sys_power_up(struct i2c_client *client) { char c = 0; int ret = 0; RK610_DBG(&client->dev,"%s \n",__FUNCTION__); - c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_OFF<<1 |RK610_INT_POL; + c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_ON<<1 |RK610_INT_POL; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c); return ret; } -static int Rk610_hdmi_sys_power_up(struct i2c_client *client) +static int Rk610_hdmi_sys_power_down(struct i2c_client *client) { char c = 0; int ret = 0; RK610_DBG(&client->dev,"%s \n",__FUNCTION__); - c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_ON<<1 |RK610_INT_POL; + c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_OFF<<1 |RK610_INT_POL; ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c); return ret; } @@ -1106,15 +1123,14 @@ static int RK610_hdmi_PLL_mode(struct i2c_client *client) ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); return 0; } -static void Rk610_hdmi_plug(struct i2c_client *client) +void Rk610_hdmi_plug(struct i2c_client *client) { RK610_DBG(&client->dev,">>> hdmi plug \n"); DoEdidRead(client); Rk610_hdmi_Display_switch(client); - Rk610_hdmi_pwr_mode(client,LOWER_PWR); Rk610_hdmi_pwr_mode(client,NORMAL); } -static void Rk610_hdmi_unplug(struct i2c_client *client) +void Rk610_hdmi_unplug(struct i2c_client *client) { RK610_DBG(&client->dev,">>> hdmi unplug \n"); g_edid.edidDataValid = FALSE; @@ -1138,11 +1154,11 @@ void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd) ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c); ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c); if(c & RK610_HPD_PLUG ){ - Rk610_hdmi_plug(client); + // Rk610_hdmi_plug(client); g_hw_inf.hpd=1; } else{ - Rk610_hdmi_unplug(client); + // Rk610_hdmi_unplug(client); g_hw_inf.hpd=0; } @@ -1162,7 +1178,7 @@ int Rk610_hdmi_Config_Done(struct i2c_client *client) int ret=0; RK610_DBG(&client->dev,"%s \n",__FUNCTION__); - ret =Rk610_hdmi_sys_power_up(client); + ret =Rk610_hdmi_sys_power_down(client); if(g_hw_inf.config_param != 0){ c=0x08; @@ -1178,9 +1194,16 @@ int Rk610_hdmi_Config_Done(struct i2c_client *client) g_hw_inf.config_param &= (~AUDIO_CHANGE); } } - ret =Rk610_hdmi_sys_power_down(client); ret =Rk610_hdmi_sys_power_up(client); ret =Rk610_hdmi_sys_power_down(client); + ret =Rk610_hdmi_sys_power_up(client); + if(g_hw_inf.analog_sync){ + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xce, &c); + c=0x01; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xce, &c); + g_hw_inf.analog_sync = 0; + } return ret; } @@ -1220,7 +1243,7 @@ static void Rk610_hdmi_Variable_Initial(void) g_hw_inf.config_param = AUDIO_CHANGE | VIDEO_CHANGE; g_hw_inf.hpd = 0; g_hw_inf.suspend_flag = 0; - + g_hw_inf.analog_sync = 0; } int Rk610_hdmi_init(struct i2c_client *client) { @@ -1233,14 +1256,13 @@ int Rk610_hdmi_init(struct i2c_client *client) Rk610_hdmi_Set_Video(g_hw_inf.video_format); Rk610_hdmi_Set_Audio(g_hw_inf.audio_fs); Rk610_hdmi_Config_Done(client); - Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c); - if(c & RK610_HPD_PLUG ){ + if(c & RK610_HPD_PLUG ){ Rk610_hdmi_plug(client); - g_hw_inf.hpd=1; + g_hw_inf.hpd=1; }else{ - Rk610_hdmi_unplug(client); - g_hw_inf.hpd=0; + Rk610_hdmi_unplug(client); + g_hw_inf.hpd=0; } return 0; } diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h index e14e19ada6a6..bc84f151fa30 100644 --- a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h @@ -100,8 +100,8 @@ enum{ //0x00 #define RK610_INT_POL 1 -#define RK610_SYS_PWR_ON 1 -#define RK610_SYS_PWR_OFF 0 +#define RK610_SYS_PWR_ON 0 +#define RK610_SYS_PWR_OFF 1 #define RK610_PHY_CLK 0 #define RK610_SYS_CLK 1 @@ -239,13 +239,16 @@ struct rk610_hdmi_hw_inf{ u8 audio_fs; u8 config_param; bool suspend_flag; - bool hpd; + bool hpd; + bool analog_sync; }; #ifdef CONFIG_HAS_EARLYSUSPEND extern int Rk610_hdmi_suspend(struct i2c_client *client); extern int Rk610_hdmi_resume(struct i2c_client *client); #endif +extern void Rk610_hdmi_plug(struct i2c_client *client); +extern void Rk610_hdmi_unplug(struct i2c_client *client); extern int Rk610_hdmi_Set_Video(u8 video_format); extern int Rk610_hdmi_Set_Audio(u8 audio_fs); extern int Rk610_hdmi_Config_Done(struct i2c_client *client); diff --git a/drivers/video/hdmi/hdmi-codec.c b/drivers/video/hdmi/hdmi-codec.c index e0360ceb7fd6..a42b0228442f 100755 --- a/drivers/video/hdmi/hdmi-codec.c +++ b/drivers/video/hdmi/hdmi-codec.c @@ -1,5 +1,5 @@ #include -#if defined CONFIG_SND_SOC_WM8900 || defined CONFIG_SND_SOC_RT5631 || defined CONFIG_SND_SOC_RT5621 +#if defined CONFIG_SND_SOC_WM8900 || defined CONFIG_SND_SOC_RT5631 || defined CONFIG_SND_SOC_RT5621 || defined CONFIG_SND_RK29_SOC_RK610 /* sound/soc/codecs/wm8900.c */ extern void codec_set_spk(bool on); #else diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index 1d39f93a7bb7..c1d1981e871e 100644 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -2935,8 +2935,14 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ) if(inf->cur_screen->standby) inf->cur_screen->standby(1); // operate the display_on pin to power down the lcd #ifdef CONFIG_HDMI_DUAL_DISP - inf->panel1_info.sscreen_get(&inf->panel1_info,inf->panel2_info.hdmi_resolution); - inf->panel1_info.sscreen_set(&inf->panel1_info,enable); + if(inf->panel1_info.sscreen_get!=NULL) + inf->panel1_info.sscreen_get(&inf->panel1_info,inf->panel2_info.hdmi_resolution); + else + printk("warnig : LCD driver do not support dual display"); + if(inf->panel1_info.sscreen_set!=NULL) + inf->panel1_info.sscreen_set(&inf->panel1_info,enable); + else + printk("warnig : LCD driver do not support dual display"); #else if(enable && mach_info->io_disable)mach_info->io_disable(); //close lcd out else if (mach_info->io_enable)mach_info->io_enable(); //open lcd out diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h index ef404c609752..2409ddc0938e 100644 --- a/include/linux/rk_screen.h +++ b/include/linux/rk_screen.h @@ -25,18 +25,24 @@ enum{ enum{ SCALE_PLL(148500000, 66000000, 16, 9, 4), - SCALE_PLL(148500000, 54000000, 16, 11, 4), + SCALE_PLL(148500000, 57375000, 17, 11, 4), + SCALE_PLL(148500000, 54000000, 16, 11, 4), SCALE_PLL(148500000, 33000000, 16, 9, 8), SCALE_PLL(148500000, 30375000, 18, 11, 8), SCALE_PLL(148500000, 29700000, 16, 10, 8), SCALE_PLL(148500000, 25312500, 15, 11, 8), SCALE_PLL(74250000, 66000000, 32, 9, 4), + SCALE_PLL(74250000, 57375000, 34, 11, 4), SCALE_PLL(74250000, 54000000, 32, 11, 4), SCALE_PLL(74250000, 33000000, 32, 9, 8), SCALE_PLL(74250000, 30375000, 36, 11, 8), SCALE_PLL(74250000, 25312500, 30, 11, 8), + SCALE_PLL(27000000, 75000000, 100, 9, 4), + SCALE_PLL(27000000, 72000000, 32, 3, 4), + SCALE_PLL(27000000, 63281250, 75, 4, 8), + SCALE_PLL(27000000, 54375000, 145, 9, 8), SCALE_PLL(27000000, 31500000, 28, 3, 8), SCALE_PLL(27000000, 30000000, 80, 9, 8), }; @@ -125,6 +131,9 @@ typedef struct rk29fb_screen { u16 s_vsync_len; u16 s_hsync_st; u16 s_vsync_st; + bool s_den_inv; + bool s_hv_sync_inv; + bool s_clk_inv; #endif u8 hdmi_resolution; /* mcu need */ -- 2.34.1