#include <linux/clk.h>
#include <mach/iomux.h>
#include <linux/err.h>
+#include <linux/slab.h>
#ifdef CONFIG_ARCH_RK30
#define RK610_RESET_PIN RK30_PIN0_PC6
static struct i2c_client *rk610_control_client = NULL;
#ifdef CONFIG_RK610_LCD
-extern int rk610_lcd_init(struct i2c_client *client);
+extern int rk610_lcd_init(struct rk610_core_info *rk610_core_info);
#else
-int rk610_lcd_init(struct i2c_client *client){}
+int rk610_lcd_init(struct rk610_core_info *rk610_core_info){}
#endif
int rk610_control_send_byte(const char reg, const char data)
{
__ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs),
};
#endif
+
static int rk610_control_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct clk *iis_clk;
-
+ struct rk610_core_info *core_info = NULL;
DBG("[%s] start\n", __FUNCTION__);
-
+ core_info = kmalloc(sizeof(struct rk610_core_info), GFP_KERNEL);
+ if(!core_info)
+ {
+ dev_err(&client->dev, ">> rk610 core inf kmalloc fail!");
+ return -ENOMEM;
+ }
+ memset(core_info, 0, sizeof(struct rk610_core_info));
+
iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
if (IS_ERR(iis_clk)) {
printk("failed to get i2s clk\n");
else {
DBG("rk610_control_probe request gpio ok\n");
gpio_direction_output(RK610_RESET_PIN, GPIO_HIGH);
- msleep(100);
gpio_direction_output(RK610_RESET_PIN, GPIO_LOW);
msleep(100);
gpio_set_value(RK610_RESET_PIN, GPIO_HIGH);
}
}
- rk610_lcd_init(client);
+ core_info->client = client;
+ rk610_lcd_init(core_info);
#ifdef RK610_DEBUG
device_create_file(&(client->dev), &rk610_attrs[0]);
#endif
#include "rk610_lcd.h"\r
#include <linux/mfd/rk610_core.h>\r
#include "../../rk29_fb.h"\r
-static struct i2c_client *rk610_g_lcd_client=NULL;\r
+static struct rk610_lcd_info *g_lcd_inf = NULL;\r
//static int rk610_scaler_read_p0_reg(struct i2c_client *client, char reg, char *val)\r
//{\r
//return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;\r
{\r
char c;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+\r
+ g_lcd_inf->scl_inf.pll_pwr = ENABLE;\r
+ \r
c = S_PLL_PWR(0)|S_PLL_RESET(0)|S_PLL_BYPASS(0);\r
rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);\r
}\r
{\r
char c;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+ \r
+ g_lcd_inf->scl_inf.pll_pwr = DISABLE;\r
+\r
c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);\r
rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);\r
}\r
static void rk610_scaler_enable(struct i2c_client *client)\r
{\r
char c;\r
+ bool den_inv = 0,hv_sync_inv = 0,clk_inv = 0;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
- \r
- c= SCL_BYPASS(0) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(ENABLE); \r
+ g_lcd_inf->scl_inf.scl_pwr = ENABLE;\r
+ #ifdef CONFIG_HDMI_DUAL_DISP\r
+ if(g_lcd_inf->screen !=NULL){\r
+ den_inv = g_lcd_inf->screen->s_den_inv;\r
+ hv_sync_inv = g_lcd_inf->screen->s_hv_sync_inv;\r
+ clk_inv = g_lcd_inf->screen->s_clk_inv;\r
+ }\r
+ #endif\r
+ c= SCL_BYPASS(0) |SCL_DEN_INV(den_inv) |SCL_H_V_SYNC_INV(hv_sync_inv) |SCL_OUT_CLK_INV(clk_inv) |SCL_ENABLE(ENABLE); \r
rk610_scaler_write_p0_reg(client, SCL_CON0, &c);\r
}\r
static void rk610_scaler_disable(struct i2c_client *client)\r
{\r
char c;\r
+ bool den_inv = 0,hv_sync_inv = 0,clk_inv = 0;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
\r
- c= SCL_BYPASS(1) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(DISABLE); \r
+ g_lcd_inf->scl_inf.scl_pwr = DISABLE;\r
+ #ifdef CONFIG_HDMI_DUAL_DISP\r
+ if(g_lcd_inf->screen !=NULL){\r
+ den_inv = g_lcd_inf->screen->s_den_inv;\r
+ hv_sync_inv = g_lcd_inf->screen->s_hv_sync_inv;\r
+ clk_inv = g_lcd_inf->screen->s_clk_inv;\r
+ }\r
+ #endif\r
+ c= SCL_BYPASS(1) |SCL_DEN_INV(den_inv) |SCL_H_V_SYNC_INV(hv_sync_inv) |SCL_OUT_CLK_INV(clk_inv) |SCL_ENABLE(DISABLE); \r
rk610_scaler_write_p0_reg(client, SCL_CON0, &c);\r
}\r
-static int rk610_output_config(struct i2c_client *client,struct rk29fb_screen *screen,bool enable)\r
+\r
+static int rk610_output_config(struct i2c_client *client,struct rk29fb_screen *screen,int mode)\r
{\r
char c=0;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
if(SCREEN_LVDS == screen->type){\r
- c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(1) |LVDS_PLL_PWR_PIN(0) \\r
- |LVDS_LANE_IN_FORMAT(DATA_D0_MSB) |LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL) \\r
- |LVDS_OUTPUT_FORMAT(screen->hw_format) | LVDS_BIASE_PWR(1); \r
- rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);\r
- c = LVDS_OUT_ENABLE(0x0) |LVDS_TX_PWR_ENABLE(0x0); \r
- rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);\r
+ if(mode == LCD_OUT_SCL || mode == LCD_OUT_BYPASS){\r
+ c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(1) |LVDS_PLL_PWR_PIN(0) \\r
+ |LVDS_LANE_IN_FORMAT(DATA_D0_MSB) |LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL) \\r
+ |LVDS_OUTPUT_FORMAT(screen->hw_format) | LVDS_BIASE_PWR(1); \r
+ rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);\r
+ c = LVDS_OUT_ENABLE(0x0) |LVDS_TX_PWR_ENABLE(0x0); \r
+ rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);\r
+ }\r
+ else{\r
+ c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(0) |LVDS_PLL_PWR_PIN(1) \\r
+ |LVDS_LANE_IN_FORMAT(DATA_D0_MSB) |LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL) \\r
+ |LVDS_OUTPUT_FORMAT(screen->hw_format) | LVDS_BIASE_PWR(0); \r
+ rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);\r
+ c = LVDS_OUT_ENABLE(0xf) |LVDS_TX_PWR_ENABLE(0xf); \r
+ rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);\r
+ \r
+ }\r
}else if(SCREEN_RGB == screen->type){\r
- c = LCD1_OUT_ENABLE(LCD1_AS_OUT) | LCD1_OUT_SRC(enable?LCD1_FROM_SCL : LCD1_FROM_LCD0);\r
- rk610_scaler_write_p0_reg(client, LCD1_CON, &c);\r
+ if(mode == LCD_OUT_SCL || mode == LCD_OUT_BYPASS){\r
+ c = LCD1_OUT_ENABLE(LCD1_AS_OUT) | LCD1_OUT_SRC((mode == LCD_OUT_SCL)?LCD1_FROM_SCL : LCD1_FROM_LCD0);\r
+ rk610_scaler_write_p0_reg(client, LCD1_CON, &c);\r
+ }\r
+ else {\r
+ c = LCD1_OUT_ENABLE(LCD1_AS_IN);\r
+ rk610_scaler_write_p0_reg(client, LCD1_CON, &c);\r
+ }\r
}\r
return 0;\r
}\r
{\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
\r
+ rk610_scaler_disable(client); \r
rk610_scaler_pll_disable(client);\r
- rk610_scaler_disable(client);\r
- \r
+ \r
return 0;\r
}\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+static void rk610_lcd_early_suspend(struct early_suspend *h)\r
+{\r
+ struct i2c_client *client = g_lcd_inf->client;\r
+ char c;\r
+ RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+ if(g_lcd_inf->screen != NULL){\r
+ rk610_output_config(client,g_lcd_inf->screen,LCD_OUT_DISABLE);\r
+ }\r
+\r
+ if(ENABLE == g_lcd_inf->scl_inf.scl_pwr){\r
+ c= SCL_BYPASS(1) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(DISABLE); \r
+ rk610_scaler_write_p0_reg(client, SCL_CON0, &c);\r
+ }\r
+ if(ENABLE == g_lcd_inf->scl_inf.pll_pwr ){\r
+ c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);\r
+ rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);\r
+ }\r
+}\r
+\r
+static void rk610_lcd_early_resume(struct early_suspend *h)\r
+{\r
+ struct i2c_client *client = g_lcd_inf->client;\r
+ char c;\r
+ RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+\r
+ if(g_lcd_inf->screen != NULL){\r
+ rk610_output_config(client,g_lcd_inf->screen,g_lcd_inf->disp_mode);\r
+ }\r
+ if(ENABLE == g_lcd_inf->scl_inf.scl_pwr){\r
+ c= SCL_BYPASS(0) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(ENABLE); \r
+ rk610_scaler_write_p0_reg(client, SCL_CON0, &c);\r
+ }\r
+ if(ENABLE == g_lcd_inf->scl_inf.pll_pwr ){\r
+ c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);\r
+ rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);\r
+ }\r
+}\r
+#endif\r
int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable )//enable:0 bypass 1: scale\r
{\r
int ret=0;\r
- struct i2c_client *client = rk610_g_lcd_client;\r
- RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+ struct i2c_client *client = g_lcd_inf->client;\r
if(client == NULL){\r
- RK610_ERR(&client->dev,"%s client == NULL FAIL\n",__FUNCTION__);\r
- return -1;\r
+ printk("%s client == NULL FAIL\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ if(screen == NULL){\r
+ printk("%s screen == NULL FAIL\n",__FUNCTION__);\r
+ return -1;\r
}\r
+ RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
+ \r
+ g_lcd_inf->screen = screen;\r
\r
#ifdef CONFIG_HDMI_DUAL_DISP\r
if(enable == 1){\r
- rk610_output_config(client,screen,1);\r
+ g_lcd_inf->disp_mode = LCD_OUT_SCL;\r
+ rk610_output_config(client,screen,LCD_OUT_SCL);\r
ret = rk610_scaler_chg(client,screen);\r
}\r
else \r
#endif\r
{\r
- rk610_output_config(client,screen,0);\r
+ g_lcd_inf->disp_mode = LCD_OUT_BYPASS;\r
+ rk610_output_config(client,screen,LCD_OUT_BYPASS);\r
ret = rk610_lcd_scaler_bypass(client,enable);\r
}\r
return ret;\r
}\r
-int rk610_lcd_init(struct i2c_client *client)\r
+int rk610_lcd_init(struct rk610_core_info *rk610_core_info)\r
{\r
- RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
- rk610_g_lcd_client = client;\r
+ if(rk610_core_info->client == NULL){\r
+ printk("%s client == NULL FAIL\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ RK610_DBG(&rk610_core_info->client->dev,"%s \n",__FUNCTION__);\r
+\r
+ g_lcd_inf = kmalloc(sizeof(struct rk610_lcd_info), GFP_KERNEL);\r
+ if(!g_lcd_inf)\r
+ {
+ dev_err(&rk610_core_info->client->dev, ">> rk610 inf kmalloc fail!");\r
+ return -ENOMEM;\r
+ }\r
+ memset(g_lcd_inf, 0, sizeof(struct rk610_lcd_info));\r
+\r
+ g_lcd_inf->client= rk610_core_info->client;\r
+ \r
+ rk610_core_info->lcd_pdata = (void *)g_lcd_inf;\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+ g_lcd_inf->early_suspend.suspend = rk610_lcd_early_suspend;\r
+ g_lcd_inf->early_suspend.resume = rk610_lcd_early_resume;\r
+ g_lcd_inf->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1;\r
+ register_early_suspend(&g_lcd_inf->early_suspend);\r
+#endif\r
+ g_lcd_inf->scl_inf.pll_pwr = DISABLE;\r
+ g_lcd_inf->scl_inf.scl_pwr = DISABLE;\r
+ g_lcd_inf->disp_mode = LCD_OUT_BYPASS;\r
return 0;\r
}\r
#ifndef _RK610_LCD_H\r
#define _RK610_LCD_H\r
+#include <linux/mfd/rk610_core.h>\r
#include "../screen/screen.h"\r
+#include <linux/earlysuspend.h>\r
#define ENABLE 1\r
#define DISABLE 0\r
+\r
/* LVDS config */\r
/* LVDS ÍⲿÁ¬Ïß½Ó·¨ */\r
/* LVDS_8BIT_1 LVDS_8BIT_2 LVDS_8BIT_3 LVDS_6BIT\r
#define LCD1_FROM_LCD0 0\r
#define LCD1_FROM_SCL 1\r
\r
+//SCALER config\r
+#define NOBYPASS 0\r
+#define BYPASS 1\r
+\r
+//SCALER PLL config\r
+#define S_PLL_PWR_ON 0\r
+#define S_PLL_PWR_DOWN 1\r
+\r
/* clock config */\r
#define S_PLL_FROM_DIV 0\r
#define S_PLL_FROM_CLKIN 1\r
#define SCL_V_BORD_END_LSB(x) ((x)&0xff) //dsp_vbord_end[7:0]\r
//SCL_CON25\r
#define SCL_V_BORD_END_MSB(x) (((x)>>8)&0xf) //dsp_vbord_end[11:8]\r
-#if 0\r
-/****************LCD STRUCT********/\r
-#define PLL_CLKOD(i) ((i) & 0x03)\r
-#define PLL_NO_1 PLL_CLKOD(0)
-#define PLL_NO_2 PLL_CLKOD(1)
-#define PLL_NO_4 PLL_CLKOD(2)
-#define PLL_NO_8 PLL_CLKOD(3)\r
-#define SCALE_PLL(_parent_rate , _rate, _m, _n, _od) \\r
-{ \
- .parent_rate = _parent_rate, \\r
- .rate = _rate, \\r
- .m = _m, \\r
- .n = _n, \\r
- .od = _od, \\r
-}\r
-#endif\r
+\r
+enum {\r
+ LCD_OUT_SCL,\r
+ LCD_OUT_BYPASS,\r
+ LCD_OUT_DISABLE,\r
+};\r
struct rk610_pll_info{\r
u32 parent_rate;\r
u32 rate;\r
int scl_h ;\r
int scl_v;\r
};\r
+\r
+struct scl_info{\r
+ bool pll_pwr;\r
+ bool scl_pwr;\r
+ struct scl_hv_info scl_hv;\r
+};\r
struct rk610_lcd_info{\r
- int enable;\r
- struct scl_hv_info scl;\r
- struct lcd_mode_inf *lcd_mode;\r
+ int disp_mode;\r
+ \r
+ struct rk29fb_screen *screen;\r
+ struct scl_info scl_inf;\r
+ struct i2c_client *client;\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+ struct early_suspend early_suspend;
+#endif\r
};\r
-extern int rk610_lcd_init(struct i2c_client *client);\r
+extern int rk610_lcd_init(struct rk610_core_info *rk610_core_info);\r
extern int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable );\r
#endif\r
\r
#define S5_H_ST 858\r
#define S5_V_ST 45\r
+\r
+#define S_DCLK_POL 0\r
+\r
/* Other */\r
#define DCLK_POL 0\r
#define SWAP_RB 0 \r
#ifdef CONFIG_HDMI_DUAL_DISP\r
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution)\r
{\r
+ screen->s_clk_inv = S_DCLK_POL;\r
+ screen->s_den_inv = 0;\r
+ screen->s_hv_sync_inv = 0;\r
switch(hdmi_resolution){\r
case HDMI_1920x1080p_60Hz:\r
/* Scaler Timing */\r
/* screen type & face */\r
screen->type = OUT_TYPE;\r
screen->face = OUT_FACE;\r
-\r
+ screen->hw_format = OUT_FORMAT;\r
+ \r
/* Screen size */\r
screen->x_res = H_VD;\r
screen->y_res = V_VD;\r
\r
#define S5_H_ST 476\r
#define S5_V_ST 48\r
+\r
+#define S_DCLK_POL 0\r
+\r
/* Other */\r
#define DCLK_POL 0\r
#define SWAP_RB 0 \r
-\r
#ifdef CONFIG_HDMI_DUAL_DISP\r
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution)\r
{\r
+ screen->s_clk_inv = S_DCLK_POL;\r
+ screen->s_den_inv = 0;\r
+ screen->s_hv_sync_inv = 0;\r
switch(hdmi_resolution){\r
case HDMI_1920x1080p_60Hz:\r
/* Scaler Timing */\r
/* screen type & face */\r
screen->type = OUT_TYPE;\r
screen->face = OUT_FACE;\r
-\r
+ screen->hw_format = OUT_FORMAT;\r
+ \r
/* Screen size */\r
screen->x_res = H_VD;\r
screen->y_res = V_VD;\r
\r
#define S5_H_ST 0\r
#define S5_V_ST 29\r
+\r
+#define S_DCLK_POL 0\r
+\r
/* Other */\r
#define DCLK_POL 0\r
#define SWAP_RB 0 \r
-\r
#ifdef CONFIG_HDMI_DUAL_DISP\r
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution)\r
{\r
+ screen->s_clk_inv = S_DCLK_POL;\r
+ screen->s_den_inv = 0;\r
+ screen->s_hv_sync_inv = 0;\r
switch(hdmi_resolution){\r
case HDMI_1920x1080p_60Hz:\r
/* Scaler Timing */\r
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 */
\r
static int rk610_hdmi_param_chg(struct rk610_hdmi_inf *rk610_hdmi)\r
{\r
+ int resolution_real;\r
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);\r
+ resolution_real = Rk610_Get_Optimal_resolution(rk610_hdmi->hdmi->resolution);\r
+ rk610_hdmi->hdmi->resolution = resolution_real;\r
hdmi_switch_fb(rk610_hdmi->hdmi, rk610_hdmi->hdmi->display_on);\r
Rk610_hdmi_Set_Video(rk610_hdmi->hdmi->resolution);\r
Rk610_hdmi_Set_Audio(rk610_hdmi->hdmi->audio_fs);\r
i2c_del_driver(&rk610_hdmi_i2c_driver);\r
}\r
\r
-late_initcall(rk610_hdmi_module_init);\r
+module_init(rk610_hdmi_module_init);\r
//module_init(rk610_hdmi_module_init);\r
module_exit(rk610_hdmi_module_exit);\r
static struct rk610_hdmi_hw_inf g_hw_inf;\r
static EDID_INF g_edid;\r
static byte edid_buf[EDID_BLOCK_SIZE];\r
+static struct edid_result Rk610_edid_result;\r
+byte DoEdidRead (struct i2c_client *client);\r
static int RK610_hdmi_soft_reset(struct i2c_client *client);\r
+static int Rk610_hdmi_Display_switch(struct i2c_client *client);\r
+static void Rk610_hdmi_plug(struct i2c_client *client);\r
+static void Rk610_hdmi_unplug(struct i2c_client *client);\r
+\r
static int Rk610_hdmi_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val)\r
{\r
return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;\r
char c;\r
int ret=0;\r
switch(mode){\r
- case NORMAL:\r
- c=0x82;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c);\r
- c=0x00;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);\r
- c=0x00;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c);\r
+ case NORMAL:\r
c=0x00;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c);\r
+ c=0x00;\r
+ ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c);\r
c=0x8e;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);\r
- break;\r
- case LOWER_PWR:\r
- c=0x02;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c);\r
- c=0x1c;\r
+ c=0x00;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);\r
+ c=0x82;\r
+ ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); \r
break;\r
- case SHUTDOWN:\r
+ case LOWER_PWR:\r
c=0x02;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c);\r
c=0x1c;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);\r
+ c=0x8c;\r
+ ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);\r
c=0x04;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c);\r
c=0x03;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c);\r
- c=0x8c;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);\r
break;\r
default:\r
RK610_ERR(&client->dev,"unkown rk610 hdmi pwr mode %d\n",mode);\r
{\r
int ret = 0;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
- ret = Rk610_hdmi_pwr_mode(client,SHUTDOWN);\r
+ g_hw_inf.suspend_flag = 1;\r
+ g_hw_inf.hpd = 0;\r
+ Rk610_hdmi_unplug(client);\r
return ret;\r
}\r
int Rk610_hdmi_resume(struct i2c_client *client)\r
{\r
int ret = 0;\r
+ char c = 0;\r
RK610_DBG(&client->dev, "%s \n",__FUNCTION__);\r
- ret = Rk610_hdmi_pwr_mode(client,NORMAL);\r
- RK610_hdmi_soft_reset(client);\r
+ Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);\r
+ if(c & RK610_HPD_PLUG ){\r
+ Rk610_hdmi_plug(client);\r
+ g_hw_inf.hpd=1;\r
+ }\r
+ else{\r
+ Rk610_hdmi_unplug(client);\r
+ g_hw_inf.hpd=0;\r
+ }\r
+ g_hw_inf.suspend_flag = 0;\r
return ret;\r
}\r
#endif\r
c=0xc6;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc0, &c);\r
//wait edid interrupt\r
- msleep(100);\r
+ msleep(10);\r
RK610_DBG(&client->dev,"Interrupt generated\n");\r
c=0x00;\r
ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c);\r
//clear EDID interrupt reg\r
c=0x04;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);\r
- msleep(100);\r
for(i=0; i <EDID_BLOCK_SIZE;i++){\r
c = 0; \r
Rk610_hdmi_i2c_read_p0_reg(client, 0x50, &c);\r
}\r
return EDID_OK;\r
}\r
+\r
+int Rk610_Parse_resolution(void)\r
+{\r
+ int i,vic;\r
+ memset(&Rk610_edid_result,0,sizeof(struct edid_result));\r
+ for(i=0;i < MAX_V_DESCRIPTORS;i++){\r
+ vic = g_edid.VideoDescriptor[i]&0x7f;\r
+ if(vic == HDMI_VIC_1080p_50Hz)\r
+ Rk610_edid_result.supported_1080p_50Hz = 1;\r
+ else if(vic == HDMI_VIC_1080p_60Hz)\r
+ Rk610_edid_result.supported_1080p_60Hz = 1; \r
+ else if(vic == HDMI_VIC_720p_50Hz)\r
+ Rk610_edid_result.supported_720p_50Hz = 1; \r
+ else if(vic == HDMI_VIC_720p_60Hz)\r
+ Rk610_edid_result.supported_720p_60Hz = 1; \r
+ else if(vic == HDMI_VIC_576p_50Hz)\r
+ Rk610_edid_result.supported_576p_50Hz = 1; \r
+ else if(vic == HDMI_VIC_480p_60Hz)\r
+ Rk610_edid_result.supported_720x480p_60Hz = 1; \r
+ }\r
+ #ifdef RK610_DEBUG\r
+ printk("rk610_hdmi:1080p_50Hz %s\n",Rk610_edid_result.supported_1080p_50Hz?"support":"not support");\r
+ printk("rk610_hdmi:1080p_60Hz %s\n",Rk610_edid_result.supported_1080p_60Hz?"support":"not support");\r
+ printk("rk610_hdmi:720p_50Hz %s\n",Rk610_edid_result.supported_720p_50Hz?"support":"not support");\r
+ printk("rk610_hdmi:720p_60Hz %s\n",Rk610_edid_result.supported_720p_60Hz?"support":"not support");\r
+ printk("rk610_hdmi:576p_50Hz %s\n",Rk610_edid_result.supported_576p_50Hz?"support":"not support");\r
+ printk("rk610_hdmi:720x480p_60Hz %s\n",Rk610_edid_result.supported_720x480p_60Hz?"support":"not support");\r
+ #endif\r
+ return 0;\r
+}\r
+\r
+int Rk610_Get_Optimal_resolution(int resolution_set)\r
+{\r
+ int resolution_real;\r
+ int find_resolution = 0;\r
+ \r
+ Rk610_Parse_resolution();\r
+ switch(resolution_set){\r
+ case HDMI_1280x720p_50Hz:\r
+ if(Rk610_edid_result.supported_720p_50Hz){\r
+ resolution_real = HDMI_1280x720p_50Hz;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_1280x720p_60Hz:\r
+ if(Rk610_edid_result.supported_720p_60Hz){\r
+ resolution_real = HDMI_1280x720p_60Hz;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_720x576p_50Hz_4x3:\r
+ if(Rk610_edid_result.supported_576p_50Hz){\r
+ resolution_real = HDMI_720x576p_50Hz_4x3;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_720x576p_50Hz_16x9:\r
+ if(Rk610_edid_result.supported_576p_50Hz){\r
+ resolution_real = HDMI_720x576p_50Hz_16x9;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_720x480p_60Hz_4x3:\r
+ if(Rk610_edid_result.supported_720x480p_60Hz){\r
+ resolution_real = HDMI_720x480p_60Hz_4x3;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_720x480p_60Hz_16x9:\r
+ if(Rk610_edid_result.supported_720x480p_60Hz){\r
+ resolution_real = HDMI_720x480p_60Hz_16x9;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_1920x1080p_50Hz:\r
+ if(Rk610_edid_result.supported_1080p_50Hz){\r
+ resolution_real = HDMI_1920x1080p_50Hz;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ case HDMI_1920x1080p_60Hz:\r
+ if(Rk610_edid_result.supported_1080p_60Hz){\r
+ resolution_real = HDMI_1920x1080p_60Hz;\r
+ find_resolution = 1;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if(find_resolution == 0){\r
+\r
+ if(Rk610_edid_result.supported_720p_50Hz)\r
+ resolution_real = HDMI_1280x720p_50Hz;\r
+ else if(Rk610_edid_result.supported_720p_60Hz)\r
+ resolution_real = HDMI_1280x720p_60Hz;\r
+ else if(Rk610_edid_result.supported_1080p_50Hz)\r
+ resolution_real = HDMI_1920x1080p_50Hz;\r
+ else if(Rk610_edid_result.supported_1080p_60Hz)\r
+ resolution_real = HDMI_1920x1080p_60Hz;\r
+ else if(Rk610_edid_result.supported_576p_50Hz)\r
+ resolution_real = HDMI_720x576p_50Hz_4x3;\r
+ else if(Rk610_edid_result.supported_720x480p_60Hz)\r
+ resolution_real = HDMI_720x480p_60Hz_4x3;\r
+ else\r
+ resolution_real = HDMI_1280x720p_60Hz;\r
+ }\r
+\r
+ return resolution_real;\r
+}\r
+\r
byte DoEdidRead (struct i2c_client *client)\r
{\r
u8 NumOfExtensions=0;\r
memset(edid_buf,0,EDID_BLOCK_SIZE);\r
RK610_read_edid_block(client,EDID_BLOCK0, edid_buf); // read first 128 bytes of EDID ROM\r
RK610_DBG(&client->dev,"/************first block*******/\n");\r
+ #ifdef RK610_DEBUG\r
for (j=0; j<EDID_BLOCK_SIZE; j++)\r
{\r
- if(j%16==0)\r
- printk("\n%x :",j);\r
- printk("%2.2x ", edid_buf[j]);\r
+ if(j%16==0)\r
+ printk("\n%x :",j);\r
+ printk("%2.2x ", edid_buf[j]);\r
}\r
+ #endif\r
Result = ParseEDID(client,edid_buf, &NumOfExtensions);\r
if(Result!=EDID_OK){\r
if(Result==EDID_NO_861_EXTENSIONS){\r
g_edid.HDMI_Sink = FALSE;\r
}\r
- else{\r
- g_edid.HDMI_Sink = TRUE;\r
+ else {\r
+ g_edid.HDMI_Sink = FALSE;\r
+ return FALSE;\r
}\r
}\r
else{\r
- g_edid.HDMI_Sink = TRUE;\r
- }\r
- NumOfExtensions = edid_buf[NUM_OF_EXTEN_ADDR];\r
- for(i=1;i<=NumOfExtensions;i++){\r
- RK610_DBG(&client->dev,"\n/************block %d*******/\n",i);\r
- memset(edid_buf,0,EDID_BLOCK_SIZE);\r
- RK610_read_edid_block(client,i, edid_buf); \r
- Parse861ShortDescriptors(client,edid_buf);\r
- for (j=0; j<EDID_BLOCK_SIZE; j++)\r
- {\r
- if(j%16==0)\r
- printk("\n%x :",j);\r
- printk("%2.2X ", edid_buf[j]);\r
+ NumOfExtensions = edid_buf[NUM_OF_EXTEN_ADDR];\r
+ for(i=1;i<=NumOfExtensions;i++){\r
+ RK610_DBG(&client->dev,"\n/************block %d*******/\n",i);\r
+ memset(edid_buf,0,EDID_BLOCK_SIZE);\r
+ RK610_read_edid_block(client,i, edid_buf); \r
+ Parse861ShortDescriptors(client,edid_buf);\r
+ #ifdef RK610_DEBUG\r
+ for (j=0; j<EDID_BLOCK_SIZE; j++){\r
+ if(j%16==0)\r
+ printk("\n%x :",j);\r
+ printk("%2.2X ", edid_buf[j]);\r
+ }\r
+ #endif\r
}\r
+\r
+ g_edid.HDMI_Sink = TRUE;\r
}\r
+\r
#if 0\r
Result = ParseEDID(edid_buf, &NumOfExtensions);\r
if (Result != EDID_OK)\r
}\r
return TRUE;\r
}\r
+\r
static int Rk610_hdmi_Display_switch(struct i2c_client *client)\r
{\r
char c;\r
switch(video_format){\r
case HDMI_720x480p_60Hz_4x3:\r
case HDMI_720x480p_60Hz_16x9:\r
- vic = 0x02;\r
+ vic = HDMI_VIC_480p_60Hz;\r
break;\r
case HDMI_720x576p_50Hz_4x3:\r
case HDMI_720x576p_50Hz_16x9:\r
- vic = 0x11;\r
+ vic = HDMI_VIC_576p_50Hz;\r
break;\r
case HDMI_1280x720p_50Hz:\r
- vic = 0x13;\r
+ vic = HDMI_VIC_720p_50Hz;\r
break;\r
case HDMI_1280x720p_60Hz:\r
- vic = 0x04;\r
+ vic = HDMI_VIC_720p_60Hz;\r
break;\r
case HDMI_1920x1080p_50Hz:\r
- vic = 0x1f;\r
+ vic = HDMI_VIC_1080p_50Hz;\r
break;\r
case HDMI_1920x1080p_60Hz:\r
- vic = 0x10;\r
+ vic = HDMI_VIC_1080p_60Hz;\r
break;\r
default:\r
vic = 0x04;\r
char c;\r
int ret=0;\r
c=0x10;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe8, &c);\r
+ ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe8, &c);\r
c=0x2c;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe6, &c);\r
+ ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe6, &c);\r
c=0x00;\r
- ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);\r
+ ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);\r
return 0;\r
}\r
+static void Rk610_hdmi_plug(struct i2c_client *client)\r
+{\r
+ RK610_DBG(&client->dev,">>> hdmi plug \n");\r
+ DoEdidRead(client);\r
+ Rk610_hdmi_Display_switch(client);\r
+ Rk610_hdmi_pwr_mode(client,LOWER_PWR);\r
+ Rk610_hdmi_pwr_mode(client,NORMAL);\r
+}\r
+static void Rk610_hdmi_unplug(struct i2c_client *client)\r
+{\r
+ RK610_DBG(&client->dev,">>> hdmi unplug \n");\r
+ g_edid.edidDataValid = FALSE;\r
+ Rk610_hdmi_pwr_mode(client,LOWER_PWR); \r
+}\r
void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd)\r
{\r
char c=0;\r
int ret=0;\r
+ if(g_hw_inf.suspend_flag == 1){\r
+ *hpd = 0;\r
+ return ;\r
+ }\r
\r
c=0x00;\r
ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c);\r
if(c & RK610_HPD_EVENT){\r
RK610_DBG(&client->dev,">>>HPD EVENT\n");\r
/**********clear hpd event******/\r
- c=RK610_HPD_EVENT;\r
+ c = RK610_HPD_EVENT;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);\r
- c=0x00;\r
ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);\r
if(c & RK610_HPD_PLUG ){\r
- RK610_DBG(&client->dev,">>> hdmi plug \n");\r
- DoEdidRead(client);\r
- Rk610_hdmi_Display_switch(client);\r
- Rk610_hdmi_pwr_mode(client,NORMAL);\r
- *hpd=1;\r
+ Rk610_hdmi_plug(client);\r
+ g_hw_inf.hpd=1;\r
}\r
else{\r
- RK610_DBG(&client->dev,">>> hdmi unplug \n");\r
- g_edid.edidDataValid = FALSE;\r
- Rk610_hdmi_pwr_mode(client,LOWER_PWR);\r
- *hpd=0;\r
+ Rk610_hdmi_unplug(client);\r
+ g_hw_inf.hpd=0;\r
}\r
\r
}\r
if(c & RK610_EDID_EVENT){\r
/**********clear hpd event******/\r
- c=RK610_EDID_EVENT;\r
+ c = RK610_EDID_EVENT;\r
ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);\r
RK610_DBG(&client->dev,">>>EDID EVENT\n");\r
/*************clear edid event*********/\r
}\r
+ *hpd = g_hw_inf.hpd;\r
}\r
int Rk610_hdmi_Config_Done(struct i2c_client *client)\r
{\r
g_hw_inf.audio_fs = HDMI_I2S_DEFAULT_Fs;\r
g_hw_inf.video_format = HDMI_DEFAULT_RESOLUTION;\r
g_hw_inf.config_param = AUDIO_CHANGE | VIDEO_CHANGE;\r
+ g_hw_inf.hpd = 0;\r
+ g_hw_inf.suspend_flag = 0;\r
\r
}\r
int Rk610_hdmi_init(struct i2c_client *client)\r
{\r
+ char c;\r
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);\r
Rk610_hdmi_Variable_Initial();\r
RK610_hdmi_soft_reset(client);\r
Rk610_hdmi_Set_Audio(g_hw_inf.audio_fs);\r
Rk610_hdmi_Config_Done(client);\r
\r
+ Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);\r
+ if(c & RK610_HPD_PLUG ){\r
+ Rk610_hdmi_plug(client);\r
+ g_hw_inf.hpd=1;\r
+ }else{\r
+ Rk610_hdmi_unplug(client);\r
+ g_hw_inf.hpd=0;\r
+ }\r
return 0;\r
}\r
#define INTER_PROGRESSIVE(x) (x)<<1 //0: progressive 1:interlace
#define VIDEO_SET_ENABLE(x) (x)<<0 //0:disable 1: enable
\r
+/* 0xe1 */ \r
+//Main-driver strength :0000~1111: the strength from low to high\r
+#define M_DRIVER_STR(x) (((x)&0xf)<<4)\r
+//Pre-driver strength :00~11: the strength from low to high\r
+#define P_DRIVER_STR(x) (((x)&3)<<2)\r
+//TX driver enable 1: enable 0: disable\r
+#define TX_DRIVER_EN(x) (((x)&1)<<1)\r
+/* 0xe2 */ \r
+//Pre-emphasis strength 00~11: the strength from 0 to high\r
+#define P_EMPHASIS_STR(x) (((x)&3)<<4)\r
+//Power down TMDS driver 1: power down. 0: not\r
+#define PWR_DOWN_TMDS(x) (((x)&1)<<0)\r
+/* 0xe3 */ \r
+//PLL out enable. Just for test. need set to 1¡¯b0\r
+#define PLL_OUT_EN(x) (((x)&1)<<7)\r
+/* 0xe4 */\r
+// Band-Gap power down 11: power down 00: not\r
+#define BAND_PWR(x) (((x)&3)<<0)\r
+/* 0xe5 */ \r
+//PLL disable 1: disable 0: enable\r
+#define PLL_PWR(x) (((x)&1)<<4)\r
+// PLL reset 1: reset 0: not\r
+#define PLL_RST(x) (((x)&1)<<3)\r
+//PHY TMDS channels reset 1: reset 0: not\r
+#define TMDS_RST(x) (((x)&1)<<2)\r
+/* 0xe7 */ \r
+// PLL LDO power down 1: power down 0: not\r
+#define PLL_LDO_PWR(x) (((x)&1)<<2) \r
+\r
+\r
/**********CONFIG CHANGE ************/\r
#define VIDEO_CHANGE 1<<0\r
#define AUDIO_CHANGE 1<<1\r
\r
#define byte u8\r
\r
+#define HDMI_VIC_1080p_50Hz 0x1f\r
+#define HDMI_VIC_1080p_60Hz 0x10\r
+#define HDMI_VIC_720p_50Hz 0x13\r
+#define HDMI_VIC_720p_60Hz 0x04\r
+#define HDMI_VIC_576p_50Hz 0x11\r
+#define HDMI_VIC_480p_60Hz 0x02\r
+\r
+struct edid_result{\r
+ bool supported_720p_50Hz;\r
+ bool supported_720p_60Hz;\r
+ bool supported_576p_50Hz;\r
+ bool supported_720x480p_60Hz;\r
+ bool supported_1080p_50Hz;\r
+ bool supported_1080p_60Hz;\r
+};\r
typedef struct edid_info\r
{ // for storing EDID parsed data\r
byte edidDataValid;\r
enum PWR_MODE{\r
NORMAL,\r
LOWER_PWR,\r
- SHUTDOWN,\r
};\r
struct rk610_hdmi_hw_inf{\r
struct i2c_client *client;\r
u8 video_format;\r
u8 audio_fs;\r
u8 config_param;\r
+ bool suspend_flag;\r
+ bool hpd;\r
};\r
\r
#ifdef CONFIG_HAS_EARLYSUSPEND\r
extern int Rk610_hdmi_Set_Video(u8 video_format);\r
extern int Rk610_hdmi_Set_Audio(u8 audio_fs);\r
extern int Rk610_hdmi_Config_Done(struct i2c_client *client);\r
+extern int Rk610_Get_Optimal_resolution(int resolution_set);\r
extern void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd);\r
extern int Rk610_hdmi_init(struct i2c_client *client);\r
-#endif
\ No newline at end of file
+#endif\r
*/
}
#endif
+#ifdef CONFIG_FB_RK29 && CONFIG_HDMI_DUAL_DISP
+extern void rk29_lcd_set(bool on);
+#else
+void rk29_lcd_set(bool on){}
+#endif
void hdmi_set_backlight(int on)
{
rk29_backlight_set(on);
+ rk29_lcd_set(on);
}
#endif
};
-#ifdef CONFIG_BACKLIGHT_RK29_BL
-/* drivers/video/backlight/rk29_backlight.c */
-extern void rk29_backlight_set(bool on);
-#else
-void rk29_backlight_set(bool on)
-{
- /* please add backlight switching-related code here or on your backlight driver
- parameter: on=1 ==> open spk
- on=0 ==> close spk
- */
-}
-#endif
+
typedef enum _TRSP_MODE
{
TRSP_CLOSE = 0,
{
return blocking_notifier_call_chain(&rk29fb_notifier_list, event, inf->cur_screen);
}
+void rk29_lcd_set(bool on)
+{
+ struct rk29fb_info *mach_info = g_pdev->dev.platform_data;
+ if(on == 1 &&mach_info->io_enable)
+ mach_info->io_enable(); //open lcd out
+ else if(mach_info->io_disable)
+ mach_info->io_disable(); //close lcd out
+}
int mcu_do_refresh(struct rk29fb_inf *inf)
{
if(inf->mcu_stopflush) return 0;
#ifdef CONFIG_CLOSE_WIN1_DYNAMIC
cancel_delayed_work_sync(&rk29_win1_check_work);
#endif
-
+#ifdef CONFIG_HDMI_DUAL_DISP
+ if(mach_info->io_disable) // close lcd pwr when output screen is lcd
+ mach_info->io_disable(); //close lcd out
+#else
if((inf->cur_screen != &inf->panel2_info) && mach_info->io_disable) // close lcd pwr when output screen is lcd
mach_info->io_disable(); //close lcd out
-
+#endif
if(inf->cur_screen->standby)
{
fbprintk(">>>>>> power down the screen! \n");
usleep_range(10*1000, 10*1000);
memcpy((u8*)inf->preg, (u8*)&inf->regbak, 0xa4); //resume reg
usleep_range(40*1000, 40*1000);
-
+ #ifdef CONFIG_HDMI_DUAL_DISP
+ if(mach_info->io_enable) // open lcd pwr when output screen is lcd
+ mach_info->io_enable(); //close lcd out
+ #else
if((inf->cur_screen != &inf->panel2_info) && mach_info->io_enable) // open lcd pwr when output screen is lcd
mach_info->io_enable(); //close lcd out
-
+ #endif
}
static struct suspend_info suspend_info = {
#define CODEC_CON 0x2e
#define I2C_CON 0x2f
+struct rk610_core_info{
+ struct i2c_client *client;
+ void *lcd_pdata;
+};
extern int rk610_control_send_byte(const char reg, const char data);