This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi team,
customer use 947/948, find some boards have flicker issues in PP stage.
below is test reslut:
1. when flicker, the lock is high
2. use 947 pattern mode:
a. 947 internal clock and internal video timing, display is ok.
b. use SOC external clock, 947 internal video timing, display is ok.
c. use SOC extranl clock and external video timing, display flicker.
3. customer use APL margin analysis, attached file margin_20201209; also attched 947 configur code, file name isp_fpglink.c
4. base on pattern mode test reslut, this issue maybe is SOC video data. but customer don't have any idea how to check it. could you give some suggestions.
also attached issue video, file name is 947 splash. thanks.
#include <common.h> #define UBOOT_TCON #include "drivers/tcon/hal_SPHE8388_tcon.h" #undef UBOOT_TCON #include "drivers/gpio/sp_gpio.h" #define DEBUG_ON_OFF #if defined(DEBUG_ON_OFF) #define ds90ub947_dbg(fmt, arg...) \ printf(fmt, ##arg) #else #define ds90ub947_dbg(...) #endif typedef unsigned char u8; static u8 s3_panel = 1; #define I2C_START_STOP_DELAY_TIME 20 #define I2C_DATA_DELAY_TIME 20 #define I2C_ACK_DELAY_TIME 100 static void delay_i2c(int cnt) { udelay(cnt); } static void msleep(int ms) { delay_i2c(ms * 1000); } #define ADDR_DS90UB947 (0x0C << 1) /*7 bit i2c addr*/ #define ADDR_DS90UB947_2 ((0x0C + 1) << 1) /*7 bit i2c addr*/ #define ADDR_DS90UB948 (0x2C << 1) /*7 bit i2c addr*/ #define ADDR_LP8860 (0x2D << 1) /*7 bit i2c addr*/ #define ADDR_TP 0x24 /*7 bit i2c addr*/ #define DS90UB947_I2C_DEVICE_ID_REG 0x00 #define DS90UB947_I2C_DEVICE_ID 0x18 #define DS90UB948_I2C_DEVICE_ID_REG 0x00 #define DS90UB948_I2C_DEVICE_ID 0x58 #define SCL_PIN 22 #define SDA_PIN 23 #define I2C_SCL_OUT() GPIO_E_SET(SCL_PIN, eHW_GPIO_OUT) #define I2C_SDA_OUT() GPIO_E_SET(SDA_PIN, eHW_GPIO_OUT) #define I2C_SDA_IN() GPIO_E_SET(SDA_PIN, eHW_GPIO_IN) #define I2C_SCL_IN() GPIO_E_SET(SCL_PIN, eHW_GPIO_IN) #if 0 #define I2C_SCL_H() I2C_SCL_OUT();GPIO_O_SET(SCL_PIN, 1) #define I2C_SDA_H() I2C_SDA_OUT();GPIO_O_SET(SDA_PIN, 1) #else #define I2C_SCL_H() I2C_SCL_IN();{ \ int i; \ for (i = 0; i < 2000; i ++) { \ if (I2C_SCL_GET()){ \ delay_i2c(1); \ if (I2C_SCL_GET()) { \ break; \ } \ }\ } \ } #define I2C_SDA_H() I2C_SDA_IN();{ \ int i; \ for (i = 0; i < 2000; i ++) { \ if (I2C_SDA_GET()){ \ delay_i2c(1); \ if (I2C_SDA_GET()) { \ break; \ } \ }\ } \ } #endif #define I2C_SCL_L() I2C_SCL_OUT();GPIO_O_SET(SCL_PIN, 0) #define I2C_SDA_L() I2C_SDA_OUT();GPIO_O_SET(SDA_PIN, 0) #define I2C_SDA_GET() GPIO_I_GET(SDA_PIN) #define I2C_SCL_GET() GPIO_I_GET(SCL_PIN) // SCL: -- // SDA: -\_ void i2c_start_sig(void) { // I2C_SCL_OUT(); // I2C_SDA_OUT(); I2C_SCL_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); } // SCL: _/- // SDA: __/ // void i2c_stop_sig(void) { // I2C_SDA_OUT(); I2C_SCL_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); } // SCL: _/---\__/-- // SDA: __/-------- void i2c_stop2(void) { I2C_SCL_L(); I2C_SDA_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_H(); I2C_SDA_H(); } void i2c_nak_stop(void) { I2C_SCL_L(); I2C_SDA_L(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SCL_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); I2C_SDA_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); } void init_i2c(void) { I2C_SCL_OUT(); I2C_SDA_OUT(); I2C_SCL_H(); I2C_SDA_H(); delay_i2c(I2C_START_STOP_DELAY_TIME); i2c_stop2(); } void i2c_byte_w_8bit(unsigned char data) { unsigned char i; #if 0 //wuzhj add it for STM32F103 I2C. I2C_SCL_OUT(); I2C_SDA_OUT(); #endif //printf("=========w8bit=====%d\n", (int)data); I2C_SCL_L(); /*if use "for" ,the fast bitrate is up to 178k(5.6us); no "for",the fast bitrate is up to 250k(4us) */ //write one byte data for(i=8;i;i--) { if(data&0x80) { I2C_SDA_H(); } else { I2C_SDA_L(); } delay_i2c(I2C_DATA_DELAY_TIME); I2C_SCL_H(); #if 1//def SUPPORT_TOUCH_PANEL delay_i2c(I2C_DATA_DELAY_TIME); //if adjust SCL high level time ,open it #endif data<<=1; I2C_SCL_L(); delay_i2c(I2C_DATA_DELAY_TIME); } delay_i2c(I2C_DATA_DELAY_TIME); } unsigned char i2c_byte_r_8bit(void) { unsigned char r_data = 0; unsigned char i = 0; I2C_SDA_IN(); for(i=8;i!=0;i--) { r_data = r_data<<1; I2C_SDA_IN(); if(I2C_SDA_GET()) { r_data |= 0x01; } I2C_SCL_H(); delay_i2c(I2C_DATA_DELAY_TIME); I2C_SCL_L(); delay_i2c(I2C_DATA_DELAY_TIME); } return r_data; } void i2c_release_bus(void) { I2C_SDA_OUT(); I2C_SDA_H(); I2C_SCL_H(); #ifdef DEBUG_I2C_FLOW //uart_print_str("release i2c bus...."); #endif } unsigned char i2c_test_ack(void) { unsigned char ack = 0; I2C_SDA_IN(); delay_i2c(I2C_ACK_DELAY_TIME); I2C_SCL_IN(); delay_i2c(I2C_ACK_DELAY_TIME); delay_i2c(I2C_ACK_DELAY_TIME); ack = I2C_SDA_GET(); delay_i2c(I2C_ACK_DELAY_TIME); I2C_SCL_L(); delay_i2c(I2C_ACK_DELAY_TIME); if(ack) { return 1; } return 0; } void i2c_set_ack(unsigned char level) { I2C_SDA_OUT(); if(level) { I2C_SDA_H(); } else { I2C_SDA_L(); } I2C_SCL_H(); delay_i2c(I2C_DATA_DELAY_TIME); I2C_SCL_L(); delay_i2c(I2C_DATA_DELAY_TIME); } unsigned char i2c_wite_data(unsigned char addr,unsigned char *BufferP,unsigned char Num) { unsigned char write_success = 1; i2c_start_sig(); i2c_byte_w_8bit((char)addr); //send device address if(0 == i2c_test_ack()) { for(;Num>0;Num--) { i2c_byte_w_8bit(*BufferP); //write data BufferP++; if(0 == i2c_test_ack()) { continue; } else { write_success = 0; break; } } } else { write_success = 0; } if(write_success) { i2c_stop_sig(); #ifdef DEBUG_I2C_FLOW dbg_printf("===TEA685X_WriteData ok!!!\r\n"); #endif } else { // i2c_release_bus(); i2c_nak_stop(); #ifdef DEBUG_I2C_FLOW dbg_printf("===TEA685X_WriteData fail!!!\r\n"); #endif } return write_success; } unsigned char i2c_wite_2byte(unsigned char addr, unsigned char byte1, unsigned char byte2) { unsigned char data[2] = {byte1, byte2}; return i2c_wite_data(addr, &data[0], 2); } unsigned char i2c_read_data(unsigned char addr, unsigned char reg) { unsigned char read_success = 0; unsigned char ddata=0; i2c_start_sig(); i2c_byte_w_8bit((char)(addr&0xfe)); //send device address if(!i2c_test_ack()) { i2c_byte_w_8bit((char)reg);//send data address if(!i2c_test_ack()) { // Read DATA i2c_start_sig(); i2c_byte_w_8bit((char)(addr|1)); //bit0:1->read command if(!i2c_test_ack()) { ddata=i2c_byte_r_8bit(); //read one byte data i2c_stop_sig(); #ifdef DEBUG_I2C_FLOW dbg_printf("===Read eeprom Ok!\r\n"); #endif // break; } } i2c_set_ack(1); read_success = 1; } if(read_success) { i2c_stop_sig(); #ifdef DEBUG_I2C_FLOW dbg_printf("===TEA685X_ReadData ok!!!\r\n"); #endif return ddata; } else { i2c_release_bus(); #ifdef DEBUG_I2C_FLOW dbg_printf("===TEA685X_ReadData fail!!!\r\n"); #endif return ddata; } return ddata; } unsigned char i2c_read_byte(unsigned char addr,unsigned char reg) { return i2c_read_data(addr, reg); } static unsigned char ds90ub948_read_reg(void *unused, u8 reg) { return i2c_read_byte(ADDR_DS90UB948, reg); } static int ds90ub948_write_reg(void *i2c, u8 reg, u8 val) { i2c_wite_2byte(ADDR_DS90UB948, reg, val); } static inline int ds90ub947_read_reg(void *i2c, u8 reg) { return i2c_read_byte(ADDR_DS90UB947, reg); } static inline int ds90ub947_read_reg2(void *i2c, u8 reg) { return i2c_read_byte(ADDR_DS90UB947_2, reg); } static int ds90ub947_write_reg(void *i2c, u8 reg, u8 val) { i2c_wite_2byte(ADDR_DS90UB947, reg, val); } static int ds90ub947_write_reg2(void *i2c, u8 reg, u8 val) { i2c_wite_2byte(ADDR_DS90UB947_2, reg, val); } static int lp8860_write_reg2(void *i2c, u8 reg, u8 val) { i2c_wite_2byte(ADDR_LP8860, reg, val); } static void backlight_on(void) { panel_set_gpio(1 , 26 , 1); panel_set_gpio(1 , 84 , 1); if (s3_panel) { panel_set_gpio(1 , 81 , 1); panel_set_gpio(1 , 36 , 1); } } static void ds90ub947_chip_init_b(void) { ds90ub947_dbg("==>func = %s ,line = %d\n", __func__, __LINE__); #if 0 ds90ub947_write_reg(0, 0x40, 0x10); ds90ub947_write_reg(0, 0x41, 0x4a); ds90ub947_write_reg(0, 0x42, 0x3f); ds90ub947_write_reg(0, 0x41, 0x4b); ds90ub947_write_reg(0, 0x42, 0x89); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x10); msleep(10); ds90ub947_write_reg(0, 0x42, 0x00); ds90ub947_write_reg(0, 0x40, 0x14); ds90ub947_write_reg(0, 0x41, 0x4A); ds90ub947_write_reg(0, 0x42, 0x3F); ds90ub947_write_reg(0, 0x41, 0x4B); ds90ub947_write_reg(0, 0x42, 0x89); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x10); msleep(10); ds90ub947_write_reg(0, 0x42, 0x00); #endif #if 1 ds90ub947_dbg("==>func = %s ,add new patch\n", __func__); ds90ub947_write_reg(0, 0x40, 0x10); ds90ub947_write_reg(0, 0x41, 0x4a); ds90ub947_write_reg(0, 0x42, 0x3f); ds90ub947_write_reg(0, 0x41, 0x4b); ds90ub947_write_reg(0, 0x42, 0x88); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x10); msleep(10); ds90ub947_write_reg(0, 0x42, 0x00); ds90ub947_write_reg(0, 0x40, 0x14); ds90ub947_write_reg(0, 0x41, 0x4a); ds90ub947_write_reg(0, 0x42, 0x3f); ds90ub947_write_reg(0, 0x41, 0x4b); ds90ub947_write_reg(0, 0x42, 0x88); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x10); msleep(15); ds90ub947_write_reg(0, 0x42, 0x00); /* The system display has a red or blue background with flicker imposed on the video image at power up. Note this symptom has a very low occurrence rate (in the region of ~1/1000 power cycles). A reset of the PLL divider block is required. */ msleep(10); ds90ub947_write_reg(0, 0x40, 0x10); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x16); ds90ub947_write_reg(0, 0x41, 0x47); ds90ub947_write_reg(0, 0x42, 0x20); // msleep(5); ds90ub947_write_reg(0, 0x42, 0xA0); // msleep(5); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); msleep(5); ds90ub947_write_reg(0, 0x42, 0x00); msleep(5); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x00); msleep(10); ds90ub947_write_reg(0, 0x40, 0x10); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x16); ds90ub947_write_reg(0, 0x41, 0x47); ds90ub947_write_reg(0, 0x42, 0x20); // msleep(5); ds90ub947_write_reg(0, 0x42, 0xA0); // msleep(5); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); ds90ub947_write_reg(0, 0x42, 0x20); msleep(5); ds90ub947_write_reg(0, 0x42, 0x00); msleep(5); ds90ub947_write_reg(0, 0x41, 0x49); ds90ub947_write_reg(0, 0x42, 0x00); #endif ds90ub947_dbg("==>func = %s end\n", __func__); } int ds90ub948_chip_init(void) { int reg_data; ds90ub947_dbg("==>func = %s ,line = %d\n", __func__, __LINE__); msleep(200); /*reset 948*/ ds90ub948_write_reg(0, 0x01, 0x03); msleep(20); reg_data = ds90ub948_read_reg(0, DS90UB948_I2C_DEVICE_ID_REG); ds90ub947_dbg("==>func = %s read device id is 0x%x\n", __func__, reg_data); /*ds90ub948_write_reg(ds90ub947->client, 0x49, 0x02);*/ /*ds90ub948_write_reg(ds90ub947->client, 0x4B, 0x01);*/ /* PORT1_SEL : 1 PORT0_SEL:1 */ ds90ub948_write_reg(0, 0x34, 0x03); if (s3_panel) { /* GPIO0 for BACKLIGHT_EN. Function : enable, Direction : output */ ds90ub948_write_reg(0, 0x1D, 0x05); /* D_GPIO0 for TS_RST. Function : enable, Direction : output */ ds90ub948_write_reg(0, 0x1D, 0x05); /* GPIO1 for TFT_STANDBY. Function : enable, Output Value :947 GPIO1 input */ /* D_GPIO2 for TS_PW. Function : enable, Output Value : HIGH */ ds90ub948_write_reg(0, 0x1E, 0x05 | 0x90); } else { /* D_GPIO0 for ARM_RESET. Function : enable, Direction : input */ ds90ub948_write_reg(0, 0x1D, 0x03); /* GPIO1 for KEY_PWM. Function : enable, Output Value :947 GPIO1 input */ /* GPIO2 for BL_EN. Function : enable, Output Value : 947 GPIO2 input */ ds90ub948_write_reg(0, 0x1E, 0x55); /* GPIO3 for BL_PWM. Function : enable, Output Value : 947 GPIO3 input */ ds90ub948_write_reg(0, 0x1F, 0x05); /* GPIO_REG8 for F_AIR. Function : enable, Output Value : Low */ ds90ub948_write_reg(0, 0x21, 0x10); /* GPIO_REG6 for R_AIR. Function : enable, Output Value : Low */ ds90ub948_write_reg(0, 0x20, 0x10); } /*I2C fast mode*/ ds90ub948_write_reg(0, 0x26, 0x30); ds90ub948_write_reg(0, 0x27, 0x30); #ifdef AUTO_SCROLLING_TEST /*Auto-Scrolling Configuration*/ ds90ub948_write_reg(0, 0x65, 0x01); ds90ub948_write_reg(0, 0x64, 0x01); #endif return 0; } int pl8860_backlight_on(void) { if (s3_panel) { //0 = HSYNC (50 to 150 kHz), 2=PWM_FREQ lp8860_write_reg2(0, 0x6E, 0x02); // lp8860_write_reg2(0, 0x65, 0x00); lp8860_write_reg2(0, 0x63, 0x0E); lp8860_write_reg2(0, 0x00, 0xAA); lp8860_write_reg2(0, 0x01, 0xAA); } return 0; } void fpdlink_init(void) { int reg_data; unsigned char cfgdata[20] = {0}; sp_config_get_string("panel_name", &cfgdata[0], 10); if (!strcmp(cfgdata, "s3")) { s3_panel = 1; } backlight_on(); GPIO_F_SET(SDA_PIN, eHW_GPIO_FIRST_GPIO); GPIO_M_SET(SDA_PIN,eHW_GPIO_RISC); GPIO_F_SET(SCL_PIN, eHW_GPIO_FIRST_GPIO); GPIO_M_SET(SCL_PIN,eHW_GPIO_RISC); ds90ub947_dbg("==>func = %s ,line = %d\n", __func__, __LINE__); reg_data = ds90ub947_read_reg(0, 0x03); ds90ub947_dbg("==>func = %s ,reg_data = 0x%x\n", __func__, reg_data); reg_data = reg_data | 0x08; /* General Configuration : I2C Pass-Through Mode Enabled */ ds90ub947_write_reg(0, 0x03, reg_data); // /* Set Single-pixel mode*/ // /*ds90ub947_write_reg(ds90ub947->client, 0x4F, 0x40);*/ if (s3_panel) { /* Set Double-pixel mode*/ ds90ub947_write_reg(0, 0x4F, 0x00); /* Set Slave ID0*/ ds90ub947_write_reg(0, 0x07, (ADDR_LP8860)); /* Set Slave Alias*/ ds90ub947_write_reg(0, 0x08, (ADDR_LP8860)); /* Set Slave ID1*/ ds90ub947_write_reg(0, 0x70, ((ADDR_TP) << 1)); /* Set Slave Alias1*/ ds90ub947_write_reg(0, 0x77, ((ADDR_TP) << 1)); } else { /* Set Slave ID0*/ ds90ub947_write_reg(0, 0x07, 0x34); /* Set Slave Alias*/ ds90ub947_write_reg(0, 0x08, 0x34); } /* Set INTB*/ ds90ub947_write_reg(0, 0xC6, 0x21); /* Set Port Select PORT1_I2C_EN*/ ds90ub947_write_reg(0, 0x1E, 0x04); reg_data = ds90ub947_read_reg2(0, DS90UB947_I2C_DEVICE_ID_REG); ds90ub947_dbg("==>func = %s read device id is 0x%x\n", __func__, reg_data); if (s3_panel) { /* GPIO0 for ARM_RESET. Function : enable, Output Value :948 D_GPIO0 input */ ds90ub947_write_reg(0, 0x0D, 0x03); ds90ub947_write_reg2(0, 0x0D, 0x03); } else { /* D_GPIO0 for ARM_RESET. Function : enable, Output Value :948 D_GPIO0 input */ ds90ub947_write_reg2(0, 0x0D, 0x05); } /* GPIO1 for KEY_PWM. Function : enable, Direction : input */ /* GPIO2 for BL_EN. Function : enable, Direction : input */ ds90ub947_write_reg(0, 0x0E, 0x33); /* GPIO3 for BL_PWM. Function : enable, Direction : input */ ds90ub947_write_reg(0, 0x0F, 0x03); ds90ub947_chip_init_b(); ds90ub948_chip_init(); pl8860_backlight_on(); }
Hello Betty,
I have seen similar problem discription before. This is something related to the timing of the incoming signal from the SoC.
Please have them measure the jitter and the skew on all data lanes with reference to the clock lane.
I will send you the instrunctions per email.
Thanks Hamzeh, I will let customer to measure this.
one little problem is that, customer test condition maybe is difference with you. for example scope and bandwidth.
Hi Hamzeh,
customer don't have suit scope to measure video data.
I want to confirm with you that this issue may relate to the timing of data signal, not relate to 947/948, right?
customer need to improve the SOC output signal instead of 947/948 setting? any other possible causes? thanks
Hello Betty,
you are right. This issue is on the timing of the incoming data signal, not related to 947/948.
Questions:
How long is the used cable?
What is the PCLK?
The MAP Tool results does not look correct. You can't get complete green window.
Hi Hamzeh,
for video timing, can you give a more specfic parameter about input signal that can match 947? for exampel clock, data jitter or something?
customer don't have scope to meaure input signals. do you have another methods ?
I will let customer replay your questions. thanks
Hi Hamzeh,
Please check below information:
How long is the used cable?---100 cm
What is the PCLK?--41Mhz
Hi Hamzeh,
Please check below:
How long is the used cable?
-> 100cm.
What is the PCLK?
--> 41.56Mhz.
Hello Betty,
Unfortunately, there is no other method to measure this than the High Speed scoope.
They need to measure the jitter and skew of the input signal. specially D2 because it contains the timing parameters, such as HSync, VSync and DE.