* pwm_on_delay(ms), pwm_off_delay(ms)
*/
bl_pwm_power = <0 0 10 10>;
+ bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */
};
backlight_1{
index = <1>;
* on_delay(ms), off_delay(ms)
*/
bl_power_attr = <1 1 0 200 200>;
+ bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */
bl_extern_index = <1>;
};
};
module_param(bl_off_policy, uint, 0664);
MODULE_PARM_DESC(bl_off_policy, "bl_off_policy");
+static unsigned int bl_level;
+module_param(bl_level, uint, 0664);
+MODULE_PARM_DESC(bl_level, "bl_level");
+
static unsigned int bl_level_uboot;
static unsigned int brightness_bypass;
module_param(brightness_bypass, uint, 0664);
bl_power_en_ctrl(bconf, 1);
break;
case BL_CTRL_PWM:
- /* step 1: power on pwm */
- bl_pwm_ctrl(bconf->bl_pwm, 1);
- if (bconf->pwm_on_delay > 0)
- mdelay(bconf->pwm_on_delay);
- /* step 2: power on enable */
- bl_power_en_ctrl(bconf, 1);
+ if (bconf->pwm_en_sequence_reverse) {
+ /* step 1: power on enable */
+ bl_power_en_ctrl(bconf, 1);
+ if (bconf->pwm_on_delay > 0)
+ msleep(bconf->pwm_on_delay);
+ /* step 2: power on pwm */
+ bl_pwm_ctrl(bconf->bl_pwm, 1);
+ } else {
+ /* step 1: power on pwm */
+ bl_pwm_ctrl(bconf->bl_pwm, 1);
+ if (bconf->pwm_on_delay > 0)
+ msleep(bconf->pwm_on_delay);
+ /* step 2: power on enable */
+ bl_power_en_ctrl(bconf, 1);
+ }
break;
case BL_CTRL_PWM_COMBO:
- /* step 1: power on pwm_combo */
- bl_pwm_ctrl(bconf->bl_pwm_combo0, 1);
- bl_pwm_ctrl(bconf->bl_pwm_combo1, 1);
- if (bconf->pwm_on_delay > 0)
- mdelay(bconf->pwm_on_delay);
- /* step 2: power on enable */
- bl_power_en_ctrl(bconf, 1);
+ if (bconf->pwm_en_sequence_reverse) {
+ /* step 1: power on enable */
+ bl_power_en_ctrl(bconf, 1);
+ if (bconf->pwm_on_delay > 0)
+ msleep(bconf->pwm_on_delay);
+ /* step 2: power on pwm_combo */
+ bl_pwm_ctrl(bconf->bl_pwm_combo0, 1);
+ bl_pwm_ctrl(bconf->bl_pwm_combo1, 1);
+ } else {
+ /* step 1: power on pwm_combo */
+ bl_pwm_ctrl(bconf->bl_pwm_combo0, 1);
+ bl_pwm_ctrl(bconf->bl_pwm_combo1, 1);
+ if (bconf->pwm_on_delay > 0)
+ msleep(bconf->pwm_on_delay);
+ /* step 2: power on enable */
+ bl_power_en_ctrl(bconf, 1);
+ }
break;
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
case BL_CTRL_LOCAL_DIMING:
bl_power_en_ctrl(bconf, 0);
break;
case BL_CTRL_PWM:
- /* step 1: power off enable */
- bl_power_en_ctrl(bconf, 0);
- /* step 2: power off pwm */
- if (bconf->pwm_off_delay > 0)
- mdelay(bconf->pwm_off_delay);
- bl_pwm_ctrl(bconf->bl_pwm, 0);
+ if (bconf->pwm_en_sequence_reverse) {
+ /* step 1: power off pwm */
+ bl_pwm_ctrl(bconf->bl_pwm, 0);
+ if (bconf->pwm_off_delay > 0)
+ msleep(bconf->pwm_off_delay);
+ /* step 2: power off enable */
+ bl_power_en_ctrl(bconf, 0);
+ } else {
+ /* step 1: power off enable */
+ bl_power_en_ctrl(bconf, 0);
+ /* step 2: power off pwm */
+ if (bconf->pwm_off_delay > 0)
+ msleep(bconf->pwm_off_delay);
+ bl_pwm_ctrl(bconf->bl_pwm, 0);
+ }
break;
case BL_CTRL_PWM_COMBO:
- /* step 1: power off enable */
- bl_power_en_ctrl(bconf, 0);
- /* step 2: power off pwm_combo */
- if (bconf->pwm_off_delay > 0)
- mdelay(bconf->pwm_off_delay);
- bl_pwm_ctrl(bconf->bl_pwm_combo0, 0);
- bl_pwm_ctrl(bconf->bl_pwm_combo1, 0);
+ if (bconf->pwm_en_sequence_reverse) {
+ /* step 1: power off pwm_combo */
+ bl_pwm_ctrl(bconf->bl_pwm_combo0, 0);
+ bl_pwm_ctrl(bconf->bl_pwm_combo1, 0);
+ if (bconf->pwm_off_delay > 0)
+ msleep(bconf->pwm_off_delay);
+ /* step 2: power off enable */
+ bl_power_en_ctrl(bconf, 0);
+ } else {
+ /* step 1: power off enable */
+ bl_power_en_ctrl(bconf, 0);
+ /* step 2: power off pwm_combo */
+ if (bconf->pwm_off_delay > 0)
+ msleep(bconf->pwm_off_delay);
+ bl_pwm_ctrl(bconf->bl_pwm_combo0, 0);
+ bl_pwm_ctrl(bconf->bl_pwm_combo1, 0);
+ }
break;
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
case BL_CTRL_LOCAL_DIMING:
break;
}
if (bconf->power_off_delay > 0)
- mdelay(bconf->power_off_delay);
+ msleep(bconf->power_off_delay);
bl_drv->state &= ~BL_STATE_BL_ON;
BLPR("backlight power off\n");
case BL_CTRL_PWM:
BLPR("pwm_on_delay = %dms\n", bconf->pwm_on_delay);
BLPR("pwm_off_delay = %dms\n", bconf->pwm_off_delay);
+ BLPR("pwm_en_sequence_reverse = %d\n",
+ bconf->pwm_en_sequence_reverse);
if (bconf->bl_pwm) {
bl_pwm = bconf->bl_pwm;
BLPR("pwm_index = %d\n", bl_pwm->index);
case BL_CTRL_PWM_COMBO:
BLPR("pwm_on_delay = %dms\n", bconf->pwm_on_delay);
BLPR("pwm_off_delay = %dms\n", bconf->pwm_off_delay);
+ BLPR("pwm_en_sequence_reverse = %d\n",
+ bconf->pwm_en_sequence_reverse);
/* pwm_combo_0 */
if (bconf->bl_pwm_combo0) {
bl_pwm = bconf->bl_pwm_combo0;
/* ensure string ending */
bconf->name[BL_NAME_MAX-1] = '\0';
- ret = of_property_read_u32_array(child, "bl_level_default_uboot_kernel",
- &bl_para[0], 2);
+ ret = of_property_read_u32_array(child,
+ "bl_level_default_uboot_kernel", &bl_para[0], 2);
if (ret) {
BLERR("failed to get bl_level_default_uboot_kernel\n");
bl_level_uboot = BL_LEVEL_DEFAULT;
bl_level_uboot = bl_para[0];
bconf->level_default = bl_para[1];
}
+
ret = of_property_read_u32_array(child, "bl_level_attr",
&bl_para[0], 4);
if (ret) {
bconf->pwm_on_delay = bl_para[2];
bconf->pwm_off_delay = bl_para[3];
}
+ ret = of_property_read_u32(child,
+ "bl_pwm_en_sequence_reverse", &val);
+ if (ret) {
+ BLPR("don't find bl_pwm_en_sequence_reverse\n");
+ bconf->pwm_en_sequence_reverse = 0;
+ } else
+ bconf->pwm_en_sequence_reverse = val;
bl_pwm->pwm_duty = bl_pwm->pwm_duty_min;
/* init pwm config */
bconf->pwm_on_delay = bl_para[4];
bconf->pwm_off_delay = bl_para[5];
}
+ ret = of_property_read_u32(child,
+ "bl_pwm_en_sequence_reverse", &val);
+ if (ret) {
+ BLPR("don't find bl_pwm_en_sequence_reverse\n");
+ bconf->pwm_en_sequence_reverse = 0;
+ } else
+ bconf->pwm_en_sequence_reverse = val;
pwm_combo0->pwm_duty = pwm_combo0->pwm_duty_min;
pwm_combo1->pwm_duty = pwm_combo1->pwm_duty_min;
break;
}
- return ret;
+ return 0;
}
#endif
return -1;
}
- /* check backlight unifykey length */
- len = 10 + 30 + 12 + 8 + 32;
+ /* step 1: check header */
+ len = LCD_UKEY_HEAD_SIZE;
ret = lcd_unifykey_len_check(key_len, len);
if (ret < 0) {
- BLERR("unifykey length is not correct\n");
+ BLERR("unifykey header length is incorrect\n");
kfree(para);
return -1;
}
- /* header: 10byte */
lcd_unifykey_header_check(para, &bl_header);
+ BLPR("unifykey version: 0x%04x\n", bl_header.version);
+ switch (bl_header.version) {
+ case 2:
+ len = 10 + 30 + 12 + 8 + 32 + 10;
+ break;
+ default:
+ len = 10 + 30 + 12 + 8 + 32;
+ break;
+ }
if (bl_debug_print_flag) {
BLPR("unifykey header:\n");
BLPR("crc32 = 0x%08x\n", bl_header.crc32);
BLPR("data_len = %d\n", bl_header.data_len);
- BLPR("version = 0x%04x\n", bl_header.version);
BLPR("reserved = 0x%04x\n", bl_header.reserved);
}
+ /* step 2: check backlight parameters */
+ ret = lcd_unifykey_len_check(key_len, len);
+ if (ret < 0) {
+ BLERR("unifykey length is incorrect\n");
+ kfree(para);
+ return -1;
+ }
+
/* basic: 30byte */
p = para + LCD_UKEY_HEAD_SIZE;
str = (const char *)p;
bl_level_uboot = (*p | ((*(p + 1)) << 8));
p += LCD_UKEY_BL_LEVEL_UBOOT;
bconf->level_default = (*p | ((*(p + 1)) << 8));
- p += LCD_UKEY_BL_LEVEL_KERNEL; /* dummy pointer */
+ p += LCD_UKEY_BL_LEVEL_KERNEL;
bconf->level_max = (*p | ((*(p + 1)) << 8));
p += LCD_UKEY_BL_LEVEL_MAX;
bconf->level_min = (*p | ((*(p + 1)) << 8));
p += LCD_UKEY_BL_PWM_GPIO;
p += LCD_UKEY_BL_PWM_GPIO_OFF;
+ if (bl_header.version == 2) {
+ bconf->pwm_en_sequence_reverse =
+ (*p | ((*(p + 1)) << 8));
+ p += LCD_UKEY_BL_CUST_VAL_0;
+ /* dummy pointer */
+ p += LCD_UKEY_BL_CUST_VAL_1;
+ p += LCD_UKEY_BL_CUST_VAL_2;
+ p += LCD_UKEY_BL_CUST_VAL_3;
+ p += LCD_UKEY_BL_CUST_VAL_4;
+ } else
+ bconf->pwm_en_sequence_reverse = 0;
+
bl_pwm->pwm_duty = bl_pwm->pwm_duty_min;
bl_pwm_config_init(bl_pwm);
break;
pwm_combo1->level_min = (*p | ((*(p + 1)) << 8));
p += LCD_UKEY_BL_PWM2_LEVEL_MIN;
+ if (bl_header.version == 2) {
+ bconf->pwm_en_sequence_reverse =
+ (*p | ((*(p + 1)) << 8));
+ p += LCD_UKEY_BL_CUST_VAL_0;
+ /* dummy pointer */
+ p += LCD_UKEY_BL_CUST_VAL_1;
+ p += LCD_UKEY_BL_CUST_VAL_2;
+ p += LCD_UKEY_BL_CUST_VAL_3;
+ p += LCD_UKEY_BL_CUST_VAL_4;
+ } else
+ bconf->pwm_en_sequence_reverse = 0;
+
pwm_combo0->pwm_duty = pwm_combo0->pwm_duty_min;
pwm_combo1->pwm_duty = pwm_combo1->pwm_duty_min;
bl_pwm_config_init(pwm_combo0);
ret = aml_bl_config_load_from_dts(bconf, pdev);
#endif
}
-
+ if (bl_level) {
+ bl_level_uboot = bl_level;
+ bconf->level_default = bl_level;
+ }
aml_bl_config_print(bconf);
switch (bconf->method) {
msleep(bconf->power_on_delay);
aml_bl_on_function();
}
- } else {
+ } else
BLERR("wrong backlight control method\n");
- }
return NOTIFY_OK;
}
if (brightness_bypass) {
if (bl_drv->state & BL_STATE_BL_ON)
bl_power_off();
- } else {
+ } else
aml_bl_update_status(bl_drv->bldev);
- }
return NOTIFY_OK;
}
"pwm_duty_max: %d\n"
"pwm_duty_min: %d\n"
"pwm_on_delay: %d\n"
- "pwm_off_delay: %d\n\n",
+ "pwm_off_delay: %d\n"
+ "pwm_en_sequence_reverse: %d\n\n",
bl_pwm->pwm_method, bl_pwm->pwm_port, bl_pwm->pwm_freq,
bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min,
- bconf->pwm_on_delay, bconf->pwm_off_delay);
+ bconf->pwm_on_delay, bconf->pwm_off_delay,
+ bconf->pwm_en_sequence_reverse);
break;
case BL_CTRL_PWM_COMBO:
pwm_combo0 = bconf->bl_pwm_combo0;
"pwm_1_duty_max: %d\n"
"pwm_1_duty_min: %d\n"
"pwm_on_delay: %d\n"
- "pwm_off_delay: %d\n\n",
+ "pwm_off_delay: %d\n"
+ "pwm_en_sequence_reverse: %d\n\n",
pwm_combo0->level_max, pwm_combo0->level_min,
pwm_combo0->pwm_method, pwm_combo0->pwm_port,
pwm_combo0->pwm_freq,
pwm_combo1->pwm_method, pwm_combo1->pwm_port,
pwm_combo1->pwm_freq,
pwm_combo1->pwm_duty_max, pwm_combo1->pwm_duty_min,
- bconf->pwm_on_delay, bconf->pwm_off_delay);
+ bconf->pwm_on_delay, bconf->pwm_off_delay,
+ bconf->pwm_en_sequence_reverse);
break;
#ifdef CONFIG_AMLOGIC_LOCAL_DIMMING
case BL_CTRL_LOCAL_DIMING:
}
__setup("bl_off=", aml_bl_boot_para_setup);
+static int __init aml_bl_level_setup(char *str)
+{
+ int ret = 0;
+
+ if (str != NULL) {
+ ret = kstrtouint(str, 10, &bl_level);
+ BLPR("bl_level: %d\n", bl_level);
+ }
+
+ return ret;
+}
+__setup("bl_level=", aml_bl_level_setup);
+
+
MODULE_DESCRIPTION("AML Backlight Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Amlogic, Inc.");
unsigned int lcd_clk, sync_duration;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
struct lcd_config_s *pconf;
+ struct vbyone_config_s *vx1_conf;
pconf = lcd_drv->lcd_config;
lcd_clk = (pconf->lcd_timing.lcd_clk / 1000);
pconf->lcd_control.lvds_config->phy_clk_preem);
break;
case LCD_VBYONE:
+ vx1_conf = pconf->lcd_control.vbyone_config;
pr_info("lane_count %u\n"
"region_num %u\n"
"byte_mode %u\n"
"phy_vswing 0x%x\n"
"phy_preemphasis 0x%x\n"
"intr_en %u\n"
- "vsync_intr_en %u\n\n",
+ "vsync_intr_en %u\n"
+ "ctrl_flag 0x%x\n\n",
pconf->lcd_control.vbyone_config->lane_count,
pconf->lcd_control.vbyone_config->region_num,
pconf->lcd_control.vbyone_config->byte_mode,
pconf->lcd_control.vbyone_config->phy_vswing,
pconf->lcd_control.vbyone_config->phy_preem,
pconf->lcd_control.vbyone_config->intr_en,
- pconf->lcd_control.vbyone_config->vsync_intr_en);
+ pconf->lcd_control.vbyone_config->vsync_intr_en,
+ pconf->lcd_control.vbyone_config->ctrl_flag);
+ if (vx1_conf->ctrl_flag & 0x1) {
+ pr_info("power_on_reset_en %u\n"
+ "power_on_reset_delay %ums\n\n",
+ (vx1_conf->ctrl_flag & 0x1),
+ vx1_conf->power_on_reset_delay);
+ }
+ if (vx1_conf->ctrl_flag & 0x2) {
+ pr_info("hpd_data_delay_en %u\n"
+ "hpd_data_delay %ums\n\n",
+ ((vx1_conf->ctrl_flag >> 1) & 0x1),
+ vx1_conf->hpd_data_delay);
+ }
+ if (vx1_conf->ctrl_flag & 0x4) {
+ pr_info("cdr_training_hold_en %u\n"
+ "cdr_training_hold %ums\n\n",
+ ((vx1_conf->ctrl_flag >> 2) & 0x1),
+ vx1_conf->cdr_training_hold);
+ }
break;
case LCD_MIPI:
#ifdef CONFIG_AMLOGIC_LCD_TABLET
"data format:\n"
" <en> : 0=disable vsync monitor intr, 1=enable vsync monitor intr\n"
"\n"
+" echo ctrl <ctrl_flag> <power_on_reset_delay> <hpd_data_delay> <cdr_training_hold> > vbyone; set ctrl adjust\n"
+"data format:\n"
+" <ctrl_flag> : bit[0]:power_on_reset_en, bit[1]:hpd_data_delay_en, bit[2]:cdr_training_hold_en\n"
+" others : unit in ms\n"
+"\n"
};
static const char *lcd_mipi_debug_usage_str = {
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
struct vbyone_config_s *vx1_conf;
#ifdef CONFIG_AMLOGIC_LCD_TV
- int val[2];
+ int val[5];
#endif
vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config;
#else
return -EINVAL;
#endif
+ } else if (buf[0] == 'c') { /* ctrl */
+#ifdef CONFIG_AMLOGIC_LCD_TV
+ ret = sscanf(buf, "ctrl %x %d %d %d",
+ &val[0], &val[1], &val[2], &val[3]);
+ if (ret == 4) {
+ pr_info("set vbyone ctrl_flag: 0x%x\n", val[0]);
+ pr_info("power_on_reset_delay: %dms\n", val[1]);
+ pr_info("hpd_data_delay: %dms\n", val[2]);
+ pr_info("cdr_training_hold: %dms\n", val[3]);
+ vx1_conf->ctrl_flag = val[0];
+ vx1_conf->power_on_reset_delay = val[1];
+ vx1_conf->hpd_data_delay = val[2];
+ vx1_conf->cdr_training_hold = val[3];
+ lcd_debug_config_update();
+ } else {
+ pr_info("set vbyone ctrl_flag: 0x%x\n",
+ vx1_conf->ctrl_flag);
+ pr_info("power_on_reset_delay: %dms\n",
+ vx1_conf->power_on_reset_delay);
+ pr_info("hpd_data_delay: %dms\n",
+ vx1_conf->hpd_data_delay);
+ pr_info("cdr_training_hold: %dms\n",
+ vx1_conf->cdr_training_hold);
+ return -EINVAL;
+ }
+#else
+ return -EINVAL;
+#endif
} else {
ret = sscanf(buf, "%d %d %d", &vx1_conf->lane_count,
&vx1_conf->region_num, &vx1_conf->byte_mode);
lcd_vcbus_write(ENCL_VIDEO_EN, 0);
lcd_vcbus_write(VPU_VIU_VENC_MUX_CTRL, ((0 << 0) | (0 << 2)));
- lcd_vcbus_write(ENCL_VIDEO_MODE, 0);
+ lcd_vcbus_write(ENCL_VIDEO_MODE, 0x8000);/*bit[15] shadown en*/
lcd_vcbus_write(ENCL_VIDEO_MODE_ADV, 0x0418); /* Sampling rate: 1 */
lcd_vcbus_write(ENCL_VIDEO_FILT_CTRL, 0x1000); /* bypass filter */
mdelay(2);
}
+static void lcd_vbyone_cdr_training_hold(struct vbyone_config_s *vx1_conf,
+ int flag)
+{
+ if (flag) {
+ LCDPR("ctrl_flag for cdr_training_hold\n");
+ lcd_vcbus_setb(VBO_FSM_HOLDER_H, 0xffff, 0, 16);
+ } else {
+ msleep(vx1_conf->cdr_training_hold);
+ lcd_vcbus_setb(VBO_FSM_HOLDER_H, 0, 0, 16);
+ }
+}
+
static void lcd_vbyone_control_set(struct lcd_config_s *pconf)
{
int lane_count, byte_mode, region_num, hsize, vsize, color_fmt;
lcd_vbyone_wait_timing_stable();
lcd_vbyone_sw_reset();
+
+ /* training hold */
+ if ((pconf->lcd_control.vbyone_config->ctrl_flag) & 0x4) {
+ lcd_vbyone_cdr_training_hold(
+ pconf->lcd_control.vbyone_config, 1);
+ }
}
static void lcd_vbyone_disable(void)
}
}
-static void lcd_vbyone_interrupt_init(void)
+static void lcd_vbyone_interrupt_init(struct aml_lcd_drv_s *lcd_drv)
{
+ /* release sw filter ctrl in uboot */
+ switch (lcd_drv->chip_type) {
+ case LCD_CHIP_TXL:
+ case LCD_CHIP_TXLX:
+ lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 1);
+ lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1);
+ break;
+ default:
+ break;
+ }
+
/* set hold in FSM_ACQ */
lcd_vcbus_setb(VBO_FSM_HOLDER_L, 0xffff, 0, 16);
/* set hold in FSM_CDR */
LCDPR("%s\n", __func__);
}
+#define VX1_LOCKN_WAIT_TIMEOUT 5000 /* 250ms */
void lcd_vbyone_wait_stable(void)
{
- int i = 5000;
+ int i = VX1_LOCKN_WAIT_TIMEOUT;
while (((lcd_vcbus_read(VBO_STATUS_L) & 0x3f) != 0x20) && (i > 0)) {
udelay(50);
i--;
}
LCDPR("%s status: 0x%x, i=%d\n",
- __func__, lcd_vcbus_read(VBO_STATUS_L), (5000 - i));
+ __func__, lcd_vcbus_read(VBO_STATUS_L),
+ (VX1_LOCKN_WAIT_TIMEOUT - i));
+ vx1_training_wait_cnt = 0;
+ vx1_training_stable_cnt = 0;
+ vx1_fsm_acq_st = 0;
+ lcd_vbyone_interrupt_enable(1);
+}
+
+static void lcd_vbyone_power_on_wait_stable(struct lcd_config_s *pconf)
+{
+ int i = VX1_LOCKN_WAIT_TIMEOUT;
+
+ /* training hold release */
+ if ((pconf->lcd_control.vbyone_config->ctrl_flag) & 0x4) {
+ lcd_vbyone_cdr_training_hold(
+ pconf->lcd_control.vbyone_config, 0);
+ }
+ while (((lcd_vcbus_read(VBO_STATUS_L) & 0x3f) != 0x20) && (i > 0)) {
+ udelay(50);
+ i--;
+ }
+ LCDPR("%s status: 0x%x, i=%d\n",
+ __func__, lcd_vcbus_read(VBO_STATUS_L),
+ (VX1_LOCKN_WAIT_TIMEOUT - i));
+
+ /* power on reset */
+ if ((pconf->lcd_control.vbyone_config->ctrl_flag) & 0x1) {
+ LCDPR("ctrl_flag for power on reset\n");
+ msleep(pconf->lcd_control.vbyone_config->power_on_reset_delay);
+ lcd_vbyone_sw_reset();
+ i = VX1_LOCKN_WAIT_TIMEOUT;
+ while (((lcd_vcbus_read(VBO_STATUS_L) & 0x3f) != 0x20) &&
+ (i > 0)) {
+ udelay(50);
+ i--;
+ }
+ LCDPR("%s status: 0x%x, i=%d\n",
+ __func__, lcd_vcbus_read(VBO_STATUS_L),
+ (VX1_LOCKN_WAIT_TIMEOUT - i));
+ }
+
vx1_training_wait_cnt = 0;
vx1_training_stable_cnt = 0;
vx1_fsm_acq_st = 0;
#define LCD_VX1_WAIT_STABLE_DELAY 300 /* ms */
static void lcd_vx1_wait_stable_delayed(struct work_struct *work)
{
+ struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+
if (lcd_vx1_intr_request == 0)
return;
- lcd_vbyone_wait_stable();
+ lcd_vbyone_power_on_wait_stable(lcd_drv->lcd_config);
}
-static void lcd_vx1_wait_hpd(void)
+static void lcd_vbyone_wait_hpd(struct lcd_config_s *pconf)
{
int i = 0;
break;
udelay(50);
}
- mdelay(10); /* add 10ms delay for compatibility */
- if (lcd_vcbus_read(VBO_STATUS_L) & 0x40)
+ if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) {
LCDPR("%s: hpd=%d\n", __func__,
((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1));
- else
+ } else {
LCDPR("%s: hpd=%d, i=%d\n", __func__,
((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1), i);
+ }
+
+ if ((pconf->lcd_control.vbyone_config->ctrl_flag) & 0x2) {
+ LCDPR("ctrl_flag for hpd_data delay\n");
+ msleep(pconf->lcd_control.vbyone_config->hpd_data_delay);
+ } else
+ usleep_range(10000, 10500);
+ /* add 10ms delay for compatibility */
}
#define LCD_PCLK_TOLERANCE 2000000 /* 2M */
return IRQ_HANDLED;
}
-#define VX1_LOCKN_WAIT_TIMEOUT 50
+#define VX1_LOCKN_WAIT_CNT_MAX 50
static int vx1_lockn_wait_cnt;
#define VX1_FSM_ACQ_NEXT_STEP_CONTINUE 0
LCDPR("vx1 lockn fall occurred\n");
vx1_fsm_acq_st = 0;
lcd_vcbus_setb(VBO_INTR_STATE_CTRL, 0, 15, 1);
- if (vx1_lockn_wait_cnt++ > VX1_LOCKN_WAIT_TIMEOUT) {
+ if (vx1_lockn_wait_cnt++ > VX1_LOCKN_WAIT_CNT_MAX) {
#if 0
LCDPR("vx1 sw reset for lockn timeout\n");
/* force PHY to 0 */
/* Enable Hsync and equalization pulse switch in center;
* bit[14] cfg_de_v = 1
*/
- lcd_vcbus_write(ENCL_VIDEO_MODE, 40);
+ lcd_vcbus_write(ENCL_VIDEO_MODE, 0x8000);/*bit[15] shadown en*/
lcd_vcbus_write(ENCL_VIDEO_MODE_ADV, 0x18); /* Sampling rate: 1 */
/* bypass filter */
case LCD_VBYONE:
lcd_vbyone_pinmux_set(1);
lcd_vbyone_control_set(pconf);
- lcd_vx1_wait_hpd();
+ lcd_vbyone_wait_hpd(pconf);
lcd_vbyone_phy_set(pconf, 1);
lcd_vx1_intr_request = 1;
queue_delayed_work(lcd_drv->workqueue,
case LCD_VBYONE:
lcd_vbyone_pinmux_set(1);
lcd_vbyone_control_set(pconf);
- lcd_vx1_wait_hpd();
+ lcd_vbyone_wait_hpd(pconf);
lcd_vbyone_phy_set(pconf, 1);
- lcd_vbyone_wait_stable();
+ lcd_vbyone_power_on_wait_stable(pconf);
break;
default:
break;
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
- lcd_vbyone_interrupt_init();
+ lcd_vbyone_interrupt_init(lcd_drv);
vx1_lockn_wait_cnt = 0;
vx1_training_wait_cnt = 0;
vx1_timeout_reset_flag = 0;
{
int ret = 0;
const char *str;
- unsigned int para[10];
+ unsigned int para[10], val;
struct device_node *child;
struct lvds_config_s *lvdsconf;
+ struct vbyone_config_s *vx1_conf;
child = of_get_child_by_name(dev->of_node, pconf->lcd_propname);
if (child == NULL) {
}
break;
case LCD_VBYONE:
+ vx1_conf = pconf->lcd_control.vbyone_config;
ret = of_property_read_u32_array(child, "vbyone_attr",
¶[0], 4);
if (ret) {
LCDERR("failed to get vbyone_attr\n");
} else {
- pconf->lcd_control.vbyone_config->lane_count = para[0];
- pconf->lcd_control.vbyone_config->region_num = para[1];
- pconf->lcd_control.vbyone_config->byte_mode = para[2];
- pconf->lcd_control.vbyone_config->color_fmt = para[3];
+ vx1_conf->lane_count = para[0];
+ vx1_conf->region_num = para[1];
+ vx1_conf->byte_mode = para[2];
+ vx1_conf->color_fmt = para[3];
}
ret = of_property_read_u32_array(child, "vbyone_intr_enable",
¶[0], 2);
if (ret) {
LCDERR("failed to get vbyone_intr_enable\n");
} else {
- pconf->lcd_control.vbyone_config->intr_en = para[0];
- pconf->lcd_control.vbyone_config->vsync_intr_en =
- para[1];
+ vx1_conf->intr_en = para[0];
+ vx1_conf->vsync_intr_en = para[1];
}
ret = of_property_read_u32_array(child, "phy_attr",
¶[0], 2);
if (lcd_debug_print_flag)
LCDPR("failed to get phy_attr\n");
} else {
- pconf->lcd_control.vbyone_config->phy_vswing = para[0];
- pconf->lcd_control.vbyone_config->phy_preem = para[1];
+ vx1_conf->phy_vswing = para[0];
+ vx1_conf->phy_preem = para[1];
if (lcd_debug_print_flag) {
LCDPR("phy vswing=0x%x, preemphasis=0x%x\n",
- pconf->lcd_control.vbyone_config->phy_vswing,
- pconf->lcd_control.vbyone_config->phy_preem);
+ vx1_conf->phy_vswing, vx1_conf->phy_preem);
+ }
+ }
+ ret = of_property_read_u32(child, "vbyone_ctrl_flag", &val);
+ if (ret) {
+ if (lcd_debug_print_flag)
+ LCDPR("failed to get vbyone_ctrl_flag\n");
+ } else {
+ vx1_conf->ctrl_flag = val;
+ LCDPR("vbyone ctrl_flag=0x%x\n", vx1_conf->ctrl_flag);
+ }
+ if (vx1_conf->ctrl_flag & 0x7) {
+ ret = of_property_read_u32_array(child,
+ "vbyone_ctrl_timing", ¶[0], 3);
+ if (ret)
+ LCDPR("failed to get vbyone_ctrl_timing\n");
+ else {
+ vx1_conf->power_on_reset_delay = para[0];
+ vx1_conf->hpd_data_delay = para[1];
+ vx1_conf->cdr_training_hold = para[2];
+ }
+ if (lcd_debug_print_flag) {
+ LCDPR("power_on_reset_delay: %d\n",
+ vx1_conf->power_on_reset_delay);
+ LCDPR("hpd_data_delay: %d\n",
+ vx1_conf->hpd_data_delay);
+ LCDPR("cdr_training_hold: %d\n",
+ vx1_conf->cdr_training_hold);
}
}
break;
if (lcd_header.version == 2) {
/* ctrl: 44byte */ /* v2 */
- p += LCD_UKEY_CTRL_FLAG;
- p += LCD_UKEY_CTRL_ATTR_0;
- p += LCD_UKEY_CTRL_ATTR_1;
- p += LCD_UKEY_CTRL_ATTR_2;
- p += LCD_UKEY_CTRL_ATTR_3;
- p += LCD_UKEY_CTRL_ATTR_4;
- p += LCD_UKEY_CTRL_ATTR_5;
- p += LCD_UKEY_CTRL_ATTR_6;
- p += LCD_UKEY_CTRL_ATTR_7;
- p += LCD_UKEY_CTRL_ATTR_8;
- p += LCD_UKEY_CTRL_ATTR_9;
- p += LCD_UKEY_CTRL_ATTR_10;
- p += LCD_UKEY_CTRL_ATTR_11;
- p += LCD_UKEY_CTRL_ATTR_12;
- p += LCD_UKEY_CTRL_ATTR_13;
- p += LCD_UKEY_CTRL_ATTR_14;
- p += LCD_UKEY_CTRL_ATTR_15;
- p += LCD_UKEY_CTRL_ATTR_16;
- p += LCD_UKEY_CTRL_ATTR_17;
- p += LCD_UKEY_CTRL_ATTR_18;
- p += LCD_UKEY_CTRL_ATTR_19;
+ if (pconf->lcd_basic.lcd_type == LCD_VBYONE) {
+ vx1_conf->ctrl_flag = (*p | ((*(p + 1)) << 8) |
+ ((*(p + 2)) << 16) | ((*(p + 3)) << 24));
+ p += LCD_UKEY_CTRL_FLAG;
+ vx1_conf->power_on_reset_delay =
+ (*p | ((*(p + 1)) << 8));
+ p += LCD_UKEY_CTRL_ATTR_0;
+ vx1_conf->hpd_data_delay = (*p | ((*(p + 1)) << 8));
+ p += LCD_UKEY_CTRL_ATTR_1;
+ vx1_conf->cdr_training_hold = (*p | ((*(p + 1)) << 8));
+ p += LCD_UKEY_CTRL_ATTR_2;
+ /* dummy pointer */
+ p += LCD_UKEY_CTRL_ATTR_3;
+ p += LCD_UKEY_CTRL_ATTR_4;
+ p += LCD_UKEY_CTRL_ATTR_5;
+ p += LCD_UKEY_CTRL_ATTR_6;
+ p += LCD_UKEY_CTRL_ATTR_7;
+ p += LCD_UKEY_CTRL_ATTR_8;
+ p += LCD_UKEY_CTRL_ATTR_9;
+ p += LCD_UKEY_CTRL_ATTR_10;
+ p += LCD_UKEY_CTRL_ATTR_11;
+ p += LCD_UKEY_CTRL_ATTR_12;
+ p += LCD_UKEY_CTRL_ATTR_13;
+ /* dummy pointer */
+ p += LCD_UKEY_CTRL_ATTR_14;
+ p += LCD_UKEY_CTRL_ATTR_15;
+ p += LCD_UKEY_CTRL_ATTR_16;
+ p += LCD_UKEY_CTRL_ATTR_17;
+ p += LCD_UKEY_CTRL_ATTR_18;
+ p += LCD_UKEY_CTRL_ATTR_19;
+ } else {
+ p += LCD_UKEY_CTRL_FLAG;
+ p += LCD_UKEY_CTRL_ATTR_0;
+ p += LCD_UKEY_CTRL_ATTR_1;
+ p += LCD_UKEY_CTRL_ATTR_2;
+ p += LCD_UKEY_CTRL_ATTR_3;
+ p += LCD_UKEY_CTRL_ATTR_4;
+ p += LCD_UKEY_CTRL_ATTR_5;
+ p += LCD_UKEY_CTRL_ATTR_6;
+ p += LCD_UKEY_CTRL_ATTR_7;
+ p += LCD_UKEY_CTRL_ATTR_8;
+ p += LCD_UKEY_CTRL_ATTR_9;
+ p += LCD_UKEY_CTRL_ATTR_10;
+ p += LCD_UKEY_CTRL_ATTR_11;
+ p += LCD_UKEY_CTRL_ATTR_12;
+ p += LCD_UKEY_CTRL_ATTR_13;
+ p += LCD_UKEY_CTRL_ATTR_14;
+ p += LCD_UKEY_CTRL_ATTR_15;
+ p += LCD_UKEY_CTRL_ATTR_16;
+ p += LCD_UKEY_CTRL_ATTR_17;
+ p += LCD_UKEY_CTRL_ATTR_18;
+ p += LCD_UKEY_CTRL_ATTR_19;
+ }
/* phy: 10byte */ /* v2 */
if (pconf->lcd_basic.lcd_type == LCD_VBYONE) {
.phy_preem = VX1_PHY_PREEM_DFT,
.intr_en = 1,
.vsync_intr_en = 1,
+
+ .ctrl_flag = 0,
+ .power_on_reset_delay = VX1_PWR_ON_RESET_DLY_DFT,
+ .hpd_data_delay = VX1_HPD_DATA_DELAY_DFT,
+ .cdr_training_hold = VX1_CDR_TRAINING_HOLD_DFT,
};
static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff};
struct bl_pwm_config_s *bl_pwm_combo1;
unsigned int pwm_on_delay;
unsigned int pwm_off_delay;
+ unsigned int pwm_en_sequence_reverse;
struct bl_gpio_s bl_gpio[BL_GPIO_NUM_MAX];
struct pinctrl *pin;
unsigned int phy_clk_preem;
};
-#define VX1_PHY_VSWING_DFT 3
-#define VX1_PHY_PREEM_DFT 0
+#define VX1_PHY_VSWING_DFT 3
+#define VX1_PHY_PREEM_DFT 0
+
+#define VX1_PWR_ON_RESET_DLY_DFT 500 /* 500ms */
+#define VX1_HPD_DATA_DELAY_DFT 10 /* 10ms */
+#define VX1_CDR_TRAINING_HOLD_DFT 200 /* 200ms */
+
struct vbyone_config_s {
unsigned int lane_count;
unsigned int region_num;
unsigned int phy_preem;
unsigned int intr_en;
unsigned int vsync_intr_en;
+
+ unsigned int ctrl_flag;
+ /* bit[0]:power_on_reset_en
+ * bit[1]:hpd_data_delay_en
+ * bit[2]:cdr_training_hold_en
+ * bit[3]:hw_filter_en
+ * bit[5:4]:sw_filter
+ */
+
+ /* ctrl timing */
+ unsigned int power_on_reset_delay; /* ms */
+ unsigned int hpd_data_delay; /* ms */
+ unsigned int cdr_training_hold; /* ms */
+ /* hw filter */
+ unsigned int hpd_hw_filter_time; /* ms */
+ unsigned int hpd_hw_filter_cnt;
+ unsigned int lockn_hw_filter_time; /* ms */
+ unsigned int lockn_hw_filter_cnt;
};
/* mipi-dsi config */