lichee/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp
做以下修改即可
diff --git a/de/disp_display.c b/de/disp_display.c
index 45cb431..e3261f2 100644
--- a/de/disp_display.c
+++ b/de/disp_display.c
@@ -1313,11 +1313,10 @@ s32 bsp_disp_lcd_set_panel_funs(char *name, disp_lcd_panel_fun *lcd_cfg)
}
/*now only support lcd0*/
num_compat_cnt = disp_get_compat_lcd_panel_num(0);
- for (screen_id = 0; screen_id < num_compat_cnt; screen_id++) {
- lcd = disp_get_lcd_compat(0, screen_id);
+ for (screen_id = 1; screen_id <= num_compat_cnt; screen_id++) {
+ lcd = disp_get_direct_lcd_compat(0, screen_id);
if (lcd && (lcd->set_panel_func)) {
if (!lcd->set_panel_func(lcd, name, lcd_cfg)) {
- gdisp.lcd_registered[screen_id] = 1;
registered_cnt++;
DE_INF("panel driver %s register for compatible usage\n", name);
}
diff --git a/de/disp_lcd.c b/de/disp_lcd.c
index 6dc6447..afe600f 100644
--- a/de/disp_lcd.c
+++ b/de/disp_lcd.c
@@ -20,8 +20,8 @@ struct disp_lcd_private_data
{
disp_lcd_flow open_flow;
disp_lcd_flow close_flow;
- /*0 for using this panel, other for index of compat_panel*/
u32 compat_panel_index;
+ u32 switch_to_compat_panel_index;
disp_panel_para panel_info;
panel_extend_para panel_extend_info;
disp_lcd_cfg lcd_cfg;
@@ -67,51 +67,66 @@ static void disp_lcd_post_disable_ex(unsigned int disp);
s32 disp_lcd_set_bright(struct disp_device *lcd, u32 bright);
s32 disp_lcd_get_bright(struct disp_device *lcd);
int disp_update_lcd_param(int lcd_param_index);
-/*now only lcd0 index is the index for var lcds_compat*/
-struct disp_device *disp_get_lcd_compat(u32 disp, u32 index)
+
+static struct disp_lcd_private_data *disp_lcd_get_priv(struct disp_device *lcd)
{
- u32 num_compat;
- u32 num_screens;
+ if (NULL == lcd) {
+ DE_WRN("param is NULL!\n");
+ return NULL;
+ }
+ return (struct disp_lcd_private_data *)lcd->priv_data;
+}
+
+struct disp_device *disp_get_direct_lcd_compat(u32 disp, u32 index)
+{
+ /*
+ * if g_compat_index is set, means not first boot, lcd_compat is NULL.
+ * disp_lcd_compat_set_panel_funs may try to get lcd_compat, so return NULL
+ * to prevent access NULL pointer.
+ */
if (g_compat_index)
- return NULL;/* if g_compat_index is set, means not first boot, lcd_compat is NULL.
- * disp_lcd_compat_set_panel_funs may try to get lcd_compat, so return NULL.
- */
- num_screens = bsp_disp_feat_get_num_screens();
- num_compat = disp_get_compat_lcd_panel_num(0);
- if (disp >= num_screens || !bsp_disp_feat_is_supported_output_types(disp, DISP_OUTPUT_TYPE_LCD)) {
- DE_INF("disp %d not support lcd output\n", disp);
return NULL;
- }
- if (index >= num_compat) {
- DE_INF("not find %d lcd_compatible param for disp%d \n", index, disp);
+ return &lcds_compat[index - 1];
+}
+/*now only lcd0 index is the index for var lcds_compat*/
+static struct disp_device *disp_get_lcd_compat(u32 disp, u32 index)
+{
+ static int count;
+ struct disp_lcd_private_data *lcd_compatp = &lcd_compat_private[index - 1];
+ u32 next_index = lcd_compatp->switch_to_compat_panel_index;
+ count++;
+ if (count > 100) {
+ DE_WRN("disp_get_lcd_compat endless loop ?\n");
return NULL;
}
- return &lcds_compat[index];
+ if (next_index)
+ return disp_get_lcd_compat(disp, next_index);
+ else {
+ count = 0;
+ return &lcds_compat[index - 1];
+ }
}
struct disp_device* disp_get_lcd(u32 disp)
{
- u32 num_screens;
+ u32 num_screens = bsp_disp_feat_get_num_screens();
+ u32 num_compat = disp_get_compat_lcd_panel_num(0);
+ u32 index = ((struct disp_lcd_private_data *)(lcds[disp].priv_data))->switch_to_compat_panel_index;
- num_screens = bsp_disp_feat_get_num_screens();
if (disp >= num_screens || !bsp_disp_feat_is_supported_output_types(disp, DISP_OUTPUT_TYPE_LCD)) {
DE_INF("disp %d not support lcd output\n", disp);
return NULL;
}
- if (!((struct disp_lcd_private_data *)(lcds[disp].priv_data))->compat_panel_index)
- return &lcds[disp];
- else
- return disp_get_lcd_compat(disp, (((struct disp_lcd_private_data *)(lcds[disp].priv_data))->compat_panel_index) - 1);
-}
-static struct disp_lcd_private_data *disp_lcd_get_priv(struct disp_device *lcd)
-{
- if (NULL == lcd) {
- DE_WRN("param is NULL!\n");
- return NULL;
- }
- return (struct disp_lcd_private_data *)lcd->priv_data;
+ if (index) {
+ if (index > num_compat) {
+ DE_WRN("not find %d lcd_compatible param for disp%d \n", index, disp);
+ return NULL;
+ }
+ return disp_get_lcd_compat(disp, index);
+ } else
+ return &lcds[disp];
}
static s32 disp_lcd_is_used(struct disp_device* lcd)
@@ -869,6 +884,7 @@ static s32 lcd_clk_exit(struct disp_device* lcd)
static s32 lcd_clk_config(struct disp_device* lcd)
{
struct disp_lcd_private_data *lcdp = disp_lcd_get_priv(lcd);
+ disp_panel_para *panel = &lcdp->panel_info;
struct lcd_clk_info clk_info;
unsigned long pll_rate = 297000000, lcd_rate = 33000000, dclk_rate = 33000000, dsi_rate = 0;//hz
unsigned long pll_rate_set = 297000000, lcd_rate_set = 33000000, dclk_rate_set = 33000000, dsi_rate_set = 0;//hz
@@ -939,8 +955,19 @@ static s32 lcd_clk_config(struct disp_device* lcd)
dclk_rate_set = lcd_rate_set / clk_info.tcon_div;
if ((pll_rate_set != pll_rate) || (lcd_rate_set != lcd_rate)
|| (dclk_rate_set != dclk_rate)) {
- DE_WRN("disp %d, clk: pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n clk real:pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n",
- lcd->disp, pll_rate, lcd_rate, dclk_rate, dsi_rate, pll_rate_set, lcd_rate_set, dclk_rate_set, dsi_rate_set);
+ /* ajust the tcon_div to fix the real pll */
+ if (pll_rate_set > pll_rate) {
+ panel->tcon_clk_div_ajust.clk_div_increase_or_decrease = INCREASE;
+ panel->tcon_clk_div_ajust.div_multiple = pll_rate_set / pll_rate;
+ dclk_rate_set /= panel->tcon_clk_div_ajust.div_multiple;
+ } else {
+ panel->tcon_clk_div_ajust.clk_div_increase_or_decrease = DECREASE;
+ panel->tcon_clk_div_ajust.div_multiple = pll_rate / pll_rate_set;
+ dclk_rate_set *= panel->tcon_clk_div_ajust.div_multiple;
+ }
+
+ DE_WRN("disp %d, clk: pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n clk real:pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n",
+ lcd->disp, pll_rate, lcd_rate, dclk_rate, dsi_rate, pll_rate_set, lcd_rate_set, dclk_rate_set, dsi_rate_set);
}
return 0;
@@ -1889,8 +1916,11 @@ s32 disp_lcd_switch_compat_panel(struct disp_device *lcd, unsigned int index)
disp_lcd_post_disable_ex(lcd->disp);
lcd->exit(lcd);
lcdp = disp_lcd_get_priv(lcd);
- lcdp->compat_panel_index = index;
- lcd_compat = disp_get_lcd_compat(lcd->disp, index - 1);
+
+ /*this flag make disp_get_lcd get correct compat_panel*/
+ lcdp->switch_to_compat_panel_index = index;
+
+ lcd_compat = disp_get_lcd_compat(lcd->disp, index);
lcdp = disp_lcd_get_priv(lcd_compat);
lcdp->need_open_again = true;
@@ -51,7 +51,7 @@
#endif
struct disp_device *disp_get_lcd(u32 disp);
-struct disp_device *disp_get_lcd_compat(u32 disp, u32 index);
+struct disp_device *disp_get_direct_lcd_compat(u32 disp, u32 index);
struct disp_device *disp_get_hdmi(u32 disp);
diff --git a/de/include.h b/de/include.h
index 57c5db6..5e81f37 100644
--- a/de/include.h
+++ b/de/include.h
@@ -658,6 +658,16 @@ enum disp_lcd_dsi_port {
DISP_LCD_DSI_DUAL_PORT,
};
+enum div_flag {
+ INCREASE = 1,
+ DECREASE = -1,
+};
+
+struct clk_div_ajust {
+ enum div_flag clk_div_increase_or_decrease;
+ int div_multiple;
+};
+
typedef struct {
disp_lcd_if lcd_if;
@@ -737,6 +747,7 @@ typedef struct {
unsigned int ccir_clk_div; /*not need to config for user*/
unsigned int input_csc;
unsigned int lcd_hv_data_polarity;
+ struct clk_div_ajust tcon_clk_div_ajust;
} disp_panel_para;
typedef enum {
diff --git a/de/lowlevel_v2x/de_dsi.c b/de/lowlevel_v2x/de_dsi.c
index 6d629c5..3bb405d 100644
--- a/de/lowlevel_v2x/de_dsi.c
+++ b/de/lowlevel_v2x/de_dsi.c
@@ -454,8 +454,11 @@ s32 dsi_dcs_rd(u32 sel, u8 cmd, u8 *para_p, u32 *num_p)
count++;
dsi_delay_us(100);
}
- if (count >= 50)
+ if (count >= 50) {
dsi_dev[sel]->dsi_basic_ctl0.bits.inst_st = 0;
+ dsi_dev[sel]->dsi_gctl.bits.dsi_en = 0;
+ dsi_dev[sel]->dsi_gctl.bits.dsi_en = 1;
+ }
if (dsi_dev[sel]->dsi_cmd_ctl.bits.rx_flag) {
if (dsi_dev[sel]->dsi_cmd_ctl.bits.rx_overflow)
@@ -920,7 +923,6 @@ static s32 dsi_basic_cfg(u32 sel, disp_panel_para *panel)
dsi_dev[sel]->dsi_trans_zero.bits.hs_zero_reduce_set = 0;
} else {
s32 start_delay = panel->lcd_vt - panel->lcd_y - 10;
- u32 vfp = panel->lcd_vt - panel->lcd_y - panel->lcd_vbp;
u32 dsi_start_delay;
/*
@@ -928,8 +930,7 @@ static s32 dsi_basic_cfg(u32 sel, disp_panel_para *panel)
* set ready sync early to dramfreq, so set start_delay 1
*/
start_delay = 1;
-
- dsi_start_delay = panel->lcd_vt - vfp + start_delay;
+ dsi_start_delay = start_delay;
if (dsi_start_delay > panel->lcd_vt)
dsi_start_delay -= panel->lcd_vt;
if (dsi_start_delay == 0)
@@ -942,7 +943,7 @@ static s32 dsi_basic_cfg(u32 sel, disp_panel_para *panel)
dsi_start_delay;
dsi_dev[sel]->dsi_basic_ctl1.bits.video_precision_mode_align =
1;
- dsi_dev[sel]->dsi_basic_ctl1.bits.video_frame_start = 0; /* 1 */
+ dsi_dev[sel]->dsi_basic_ctl1.bits.video_frame_start = 1;
dsi_dev[sel]->dsi_trans_start.bits.trans_start_set = 10;
dsi_dev[sel]->dsi_trans_zero.bits.hs_zero_reduce_set = 0;
dsi_dev[sel]->dsi_basic_ctl1.bits.dsi_mode = 1;
diff --git a/de/lowlevel_v2x/de_lcd_sun50iw10.c b/de/lowlevel_v2x/de_lcd_sun50iw10.c
index 203e8a3..5a4cdf6 100644
--- a/de/lowlevel_v2x/de_lcd_sun50iw10.c
+++ b/de/lowlevel_v2x/de_lcd_sun50iw10.c
@@ -393,7 +393,7 @@ s32 lvds_open(u32 sel, disp_panel_para *panel)
#if defined(SUPPORT_COMBO_DPHY)
if (sel == 0) {
lvds_combphy_open(sel, panel);
- } else {
+ } else if (sel < DEVICE_NUM) {
lcd_dev[sel]->tcon0_lvds_ana[0].bits.c = 2;
lcd_dev[sel]->tcon0_lvds_ana[0].bits.v = 3;
lcd_dev[sel]->tcon0_lvds_ana[0].bits.pd = 2;
@@ -774,6 +774,7 @@ static s32 tcon0_cfg_mode_tri(u32 sel, disp_panel_para *panel)
{
u32 start_delay = 0;
u32 de_clk_rate = de_get_clk_rate() / 1000000;
+ u32 delay_line = 0;
de_clk_rate = (de_clk_rate == 0) ? 250 : de_clk_rate;
@@ -783,8 +784,30 @@ static s32 tcon0_cfg_mode_tri(u32 sel, disp_panel_para *panel)
lcd_dev[sel]->tcon0_cpu_tri1.bits.block_num = panel->lcd_y - 1;
lcd_dev[sel]->tcon0_cpu_tri2.bits.trans_start_mode = 0;
lcd_dev[sel]->tcon0_cpu_tri2.bits.sync_mode = 0;
- start_delay = (panel->lcd_vt - panel->lcd_y - 8 - 1)
- * panel->lcd_ht * de_clk_rate / panel->lcd_dclk_freq / 8;
+
+ /**
+ * When the blanking area of LCD is too small, the following formula is
+ * not applicable, that calculates the start_ Delay is too large.
+ *
+ * The formula is
+ * start_delay = (panel->lcd_vt - panel->lcd_y - 8 - 1)
+ * * panel->lcd_ht * de_clk_rate / panel->lcd_dclk_freq / 8;
+ *
+ * Therefore, the following formula is obtained by balancing the
+ * requirements of DE, TCON and PANEL modules for pixel data speed
+ *
+ */
+ if (panel->lcd_vbp > 10)
+ delay_line = 10;
+ else if (panel->lcd_vbp <= 10 && panel->lcd_vbp > 4)
+ delay_line = panel->lcd_vbp - 1;
+ else {
+ DE_WRN("vbp is too small, please readjust the timing parameters to increase vbp. \n");
+ delay_line = panel->lcd_vbp;
+ }
+
+ start_delay = delay_line * panel->lcd_ht * de_clk_rate / panel->lcd_dclk_freq / 8;
+
lcd_dev[sel]->tcon0_cpu_tri2.bits.start_delay = start_delay;
lcd_dev[sel]->tcon0_cpu_ctl.bits.trigger_fifo_en = 1;
diff --git a/de/lowlevel_v2x/disp_al.c b/de/lowlevel_v2x/disp_al.c
index 635db57..cf76927 100644
--- a/de/lowlevel_v2x/disp_al.c
+++ b/de/lowlevel_v2x/disp_al.c
@@ -746,10 +746,6 @@ int disp_al_lcd_get_clk_info(u32 screen_id, struct lcd_clk_info *info,
}
#endif
- if (panel->lcd_dclk_freq < 48 && panel->lcd_dclk_freq >= 3) {
- tcon_div = 300 / panel->lcd_dclk_freq;
- }
-
info->tcon_div = tcon_div;
info->lcd_div = lcd_div;
info->dsi_div = dsi_div;
@@ -773,6 +769,11 @@ int disp_al_lcd_cfg(u32 screen_id, disp_panel_para *panel,
tcon_init(screen_id);
disp_al_lcd_get_clk_info(screen_id, &info, panel);
+ if (panel->tcon_clk_div_ajust.clk_div_increase_or_decrease == INCREASE) {
+ info.tcon_div = info.tcon_div * panel->tcon_clk_div_ajust.div_multiple;
+ } else if (panel->tcon_clk_div_ajust.clk_div_increase_or_decrease == DECREASE) {
+ info.tcon_div = info.tcon_div / panel->tcon_clk_div_ajust.div_multiple;
+ }
tcon0_set_dclk_div(screen_id, info.tcon_div);
#if !defined(TCON1_DRIVE_PANEL)
diff --git a/dev_disp.c b/dev_disp.c
index b850d96..1fcd080 100644
--- a/dev_disp.c
+++ b/dev_disp.c
@@ -992,6 +992,17 @@ long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
//----layer----
case DISP_LAYER_SET_CONFIG:
{
+
+ const unsigned int lyr_cfg_size = ARRAY_SIZE(lyr_cfg);
+
+ if (IS_ERR_OR_NULL((void __user *)ubuffer[1])) {
+ __wrn("incoming pointer of user is ERR or NULL");
+ return -EFAULT;
+ }
+ if (ubuffer[2] == 0 || ubuffer[2] > lyr_cfg_size) {
+ __wrn("layer number need to be set from 1 to %d\n", lyr_cfg_size);
+ return -EFAULT;
+ }
if (copy_from_user(lyr_cfg,
(void __user *)ubuffer[1],
sizeof(struct disp_layer_config) * ubuffer[2])) {
@@ -1005,6 +1016,17 @@ long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case DISP_LAYER_GET_CONFIG:
{
+
+ const unsigned int lyr_cfg_size = ARRAY_SIZE(lyr_cfg);
+
+ if (IS_ERR_OR_NULL((void __user *)ubuffer[1])) {
+ __wrn("incoming pointer of user is ERR or NULL");
+ return -EFAULT;
+ }
+ if (ubuffer[2] == 0 || ubuffer[2] > lyr_cfg_size) {
+ __wrn("layer number need to be set from 1 to %d\n", lyr_cfg_size);
+ return -EFAULT;
+ }
if (copy_from_user(lyr_cfg,
(void __user *)ubuffer[1],
sizeof(struct disp_layer_config) * ubuffer[2])) {
@@ -1026,6 +1048,17 @@ long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case DISP_LAYER_SET_CONFIG2:
{
+
+ const unsigned int lyr_cfg_size = ARRAY_SIZE(lyr_cfg2);
+
+ if (IS_ERR_OR_NULL((void __user *)ubuffer[1])) {
+ __wrn("incoming pointer of user is ERR or NULL");
+ return -EFAULT;
+ }
+ if (ubuffer[2] == 0 || ubuffer[2] > lyr_cfg_size) {
+ __wrn("layer number need to be set from 1 to %d\n", lyr_cfg_size);
+ return -EFAULT;
+ }
if (copy_from_user(lyr_cfg2,
(void __user *)ubuffer[1],
sizeof(struct disp_layer_config2) * ubuffer[2])) {
@@ -1040,6 +1073,17 @@ long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case DISP_LAYER_GET_CONFIG2:
{
+
+ const unsigned int lyr_cfg_size = ARRAY_SIZE(lyr_cfg2);
+
+ if (IS_ERR_OR_NULL((void __user *)ubuffer[1])) {
+ __wrn("incoming pointer of user is ERR or NULL");
+ return -EFAULT;
+ }
+ if (ubuffer[2] == 0 || ubuffer[2] > lyr_cfg_size) {
+ __wrn("layer number need to be set from 1 to %d\n", lyr_cfg_size);
+ return -EFAULT;
+ }
if (copy_from_user(lyr_cfg2,
(void __user *)ubuffer[1],
sizeof(struct disp_layer_config2) * ubuffer[2])) {
diff --git a/disp_sys_intf.c b/disp_sys_intf.c
index a8032b5..5afccf1 100644
--- a/disp_sys_intf.c
+++ b/disp_sys_intf.c
@@ -378,6 +378,7 @@ int disp_get_set_lcd_param_index_from_flash(bool is_set, int idx)
ret = -1;
}
} else {
+#ifdef CONFIG_COMPATIBLE_PANEL_RECORD
#ifdef CONFIG_FAT_WRITE
if (idx < 0 || idx > 9) {
ret = -1;
@@ -399,6 +400,9 @@ int disp_get_set_lcd_param_index_from_flash(bool is_set, int idx)
pr_error("please enable FAT_WRITE for lcd compatible first\n");
ret = -1;
#endif
+#else
+ ret = idx_get = idx;
+#endif
}
exit_free:
kfree(buf);
--