Other Parts Discussed in Thread: ALP
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(); }