44.Linux君正X1000-添加st7789v顯示


由於板子LCD舊屏是ili9335型號的,舊屏有時候會斷貨,如果斷貨則使用一個st7789v型號的LCD

它們兩個屏的區別在於初始化屏的參數不同,引腳都一樣,也就是說需要使板子同時支持ili9335型號和st7789v型號

思路:

  • 1.uboot在顯示LOG(初始化屏參數)之前,通過命令來讀LCD型號,來檢測LCD型號,然后來修改初始化屏的參數.
  • 2.如果屏是新屏,則設置bootargs,向內核傳遞參數lcd_type=new
  • 3.當kernel收到參數lcd_type=new時,則在初始化LCD之前,修改屏的參數.

改uboot

首先來看單板配置信息,根據配置找到哪個文件是初始化LCD屏的

根據make ap60pro_uImage_sfc_nand命令,找ap60pro_uImage_sfc_nand單板信息

vi   ./u-boot/boards.cfg    

找到:

# Target      ARCH   CPU   Board name  Vendor     SoC    Options
##############################################################
ap60pro_uImage_sfc_nand      mips        xburst      ap60pro       ingenic    x1000   ap60pro:SPL_SFC_NAND,LIBSLEEP,GET_BT_MAC

從上面看到board name為ap60pro,所以最終通過下面幾個來初始化: 

./arch/mips/cpu/xburst\x1000\start.S    //啟動代碼 ./include/configs/ap60pro.h             //各種define配置 ./board/ingenic/ap60pro                 //單板配置源文件 

查看ap60pro.h,查看LCD相關的define配置

查找CONFIG_ILI9335_240X320,找到在./board/ingenic/ap60pro/Makefile里調用:

COBJS-$(CONFIG_ILI9335_240X320) += lcd-ili9335_240x320.o    //保存LCD初始化參數的信息

查找CONFIG_ILI9335_240X320,找到在./drivers/video/Makefile里調用:

COBJS-$(CONFIG_JZ_LCD_V13) +=  jz_lcd/jz_lcd_v13.o        //根據lcd-ili9335_240*320.c來初始化LCD

 

修改lcd-ili9335_240x320.c

添加st7789v初始化的數組表(在代碼中以New_ili9335_data_table數組表示):

struct smart_lcd_data_table ili9335_data_table[] = {    //舊屏的初始化參數表
{SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0xec}, {SMART_CONFIG_DATA,0x1e}, {SMART_CONFIG_DATA,0x8f}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x01}, {SMART_CONFIG_DATA,0x01}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x02}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x03}, {SMART_CONFIG_DATA,0x10}, {SMART_CONFIG_DATA,0x30}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x08}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x09}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x0a}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x08}, //enable te
 {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x0d}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x0f}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x60}, {SMART_CONFIG_DATA,0x27}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x61}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x6a}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x10}, {SMART_CONFIG_DATA,0x16}, {SMART_CONFIG_DATA,0x90}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x11}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x27}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x12}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x0d}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x21}, {SMART_CONFIG_DATA,0x16}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x29}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x18}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x2b}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x0a}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x20}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x21}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, //============Gamma============
    {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x30}, {SMART_CONFIG_DATA,0x04}, {SMART_CONFIG_DATA,0x03}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x31}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x07}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x32}, {SMART_CONFIG_DATA,0x04}, {SMART_CONFIG_DATA,0x04}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x35}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x36}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x0f}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x37}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x03}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x38}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x39}, {SMART_CONFIG_DATA,0x03}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x3c}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x3d}, {SMART_CONFIG_DATA,0x0f}, {SMART_CONFIG_DATA,0x00}, //============================= // set RAM address
  {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x50}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x51}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0xef}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x52}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x53}, {SMART_CONFIG_DATA,0x01}, {SMART_CONFIG_DATA,0x3f}, {SMART_CONFIG_UDELAY,10000}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x80}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x81}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x82}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x83}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x84}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x85}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x90}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x10}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x91}, {SMART_CONFIG_DATA,0x06}, {SMART_CONFIG_DATA,0x00}, //display on
    {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x07}, {SMART_CONFIG_DATA,0x01}, {SMART_CONFIG_DATA,0x33}, {SMART_CONFIG_CMD,0x00}, {SMART_CONFIG_CMD,0x22}, }; unsigned long truly_cmd_buf[]= { 0x22002200, }; struct jzfb_config_info jzfb1_init_data = { .num_modes = 1, .modes = &jzfb1_videomode, .lcd_type = LCD_TYPE_SLCD, .bpp = 24,                            //R8G8B8
    .pinmd  = 0, .smart_config.rsply_cmd_high = 0, .smart_config.csply_active_high = 0, /* write graphic ram command, in word, for example 8-bit bus, write_gram_cmd=C3C2C1C0. */ .smart_config.newcfg_fmt_conv =  0, .smart_config.clkply_active_rising = 1, .smart_config.data_times = 2, .smart_config.write_gram_cmd = truly_cmd_buf, .smart_config.length_cmd = ARRAY_SIZE(truly_cmd_buf), .smart_config.bus_width = 8,                                    //總線8位的
    .smart_config.length_data_table = ARRAY_SIZE(ili9335_data_table), .smart_config.data_table = ili9335_data_table, .dither_enable = 1, }; //新屏的初始化參數表
static struct smart_lcd_data_table New_ili9335_data_table[] = { {SMART_CONFIG_CMD,0x11}, {SMART_CONFIG_UDELAY,120000},    //Sleep out
      {SMART_CONFIG_CMD,0x36},                //控制
    {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_CMD,0x21},    //0x13顯示不反轉 ,21h 反顯
 {SMART_CONFIG_CMD,0x3A}, {SMART_CONFIG_DATA,0x05}, {SMART_CONFIG_CMD,0x2A}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0xEF}, {SMART_CONFIG_CMD,0x2B}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x01}, {SMART_CONFIG_DATA,0x3F}, {SMART_CONFIG_CMD,0xB2},        //前后肩
    {SMART_CONFIG_DATA,0x0C}, {SMART_CONFIG_DATA,0x0C}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x33}, {SMART_CONFIG_DATA,0x33}, {SMART_CONFIG_CMD,0xB7},     //VGH VGL
    {SMART_CONFIG_DATA,0x35}, {SMART_CONFIG_CMD,0xBB},     //VCOM 
    {SMART_CONFIG_DATA,0x1E}, {SMART_CONFIG_CMD,0xC0},      //LCM
    {SMART_CONFIG_DATA,0x2C}, {SMART_CONFIG_CMD,0xC2}, {SMART_CONFIG_DATA,0x01}, {SMART_CONFIG_CMD,0xC3},     //VRH( vcom+vcom offset+vdv) 
    {SMART_CONFIG_DATA,0x27}, {SMART_CONFIG_CMD,0xC4},     //vdv
    {SMART_CONFIG_DATA,0x20}, {SMART_CONFIG_CMD,0xC6},        //幀率
    {SMART_CONFIG_DATA,0x0F}, {SMART_CONFIG_CMD,0xD0},        //功率控制模式 
    {SMART_CONFIG_DATA,0xA4}, {SMART_CONFIG_DATA,0xA1}, {SMART_CONFIG_CMD,0xE0},        //正GAMMA 
    {SMART_CONFIG_DATA,0xD0}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x05}, {SMART_CONFIG_DATA,0x03}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x07}, {SMART_CONFIG_DATA,0x3F}, {SMART_CONFIG_DATA,0x55}, {SMART_CONFIG_DATA,0x50}, {SMART_CONFIG_DATA,0x09}, {SMART_CONFIG_DATA,0x14}, {SMART_CONFIG_DATA,0x15}, {SMART_CONFIG_DATA,0x22}, {SMART_CONFIG_DATA,0x25}, {SMART_CONFIG_CMD,0xE1},    //負GAMMA
    {SMART_CONFIG_DATA,0xD0}, {SMART_CONFIG_DATA,0x00}, {SMART_CONFIG_DATA,0x05}, {SMART_CONFIG_DATA,0x03}, {SMART_CONFIG_DATA,0x02}, {SMART_CONFIG_DATA,0x07}, {SMART_CONFIG_DATA,0x3F}, {SMART_CONFIG_DATA,0x55}, {SMART_CONFIG_DATA,0x54}, {SMART_CONFIG_DATA,0x0C}, {SMART_CONFIG_DATA,0x18}, {SMART_CONFIG_DATA,0x14}, {SMART_CONFIG_DATA,0x22}, {SMART_CONFIG_DATA,0x25}, {SMART_CONFIG_CMD,0x11},    // sleep out
    {SMART_CONFIG_UDELAY,120000}, {SMART_CONFIG_CMD,0x29},//Display On
    {SMART_CONFIG_UDELAY,20000}, }; unsigned long New_truly_cmd_buf[]= { 0x2C2C2C2C, }; void switch_lcd_New(void)              //切換為ST7789V
{ jzfb1_init_data.smart_config.data_table = New_ili9335_data_table; jzfb1_init_data.smart_config.length_data_table = ARRAY_SIZE(New_ili9335_data_table); jzfb1_init_data.smart_config.write_gram_cmd = New_truly_cmd_buf; }
//... ...

 

查看jz_lcd_v13.c調用順序

從uboot啟動時,調用board_init_r()函數開始:

 -> board_init_r() -> stdio_init() -> drv_lcd_init()                //初始化硬件LCD
                  -> drv_video_init()             //繪制log

其中drv_lcd_init()中調用順序為:

 -> drv_lcd_init() -> lcd_init() -> lcd_ctrl_init()                 // 位於drivers\video\jz_lcd\Jz_lcd_v13.c

所以,接下來,我們便來修改jz_lcd_v13.c,讓uboot在初始化LCD之前,讀LCD的ID,是否需要切換新屏參數

 

修改jz_lcd_v13.c

由於X1000的SLCD控制寄存器只能向LCD寫命令/數據,沒有讀數據的寄存器,所以我們便需要使用GPIO來模擬時序,讀出ID來

參考ST7789V數據手冊,找到ID命令為04h:

參考ST7789V數據手冊,找到讀寫8080時序圖:

接下來開始改代碼: 

//添加下面函數,通過GPIO模擬LCD寄存器,來實現讀ID
void  gpio_setfunc(unsigned int gpioPort,enum gpio_function fun) { enum gpio_port port; switch((gpioPort /32)) { case 0:    port = GPIO_PORT_A; break; case 1:    port = GPIO_PORT_B; break; case 2:    port = GPIO_PORT_C; break; case 3:    port = GPIO_PORT_D; break; default: port = GPIO_NR_PORTS;   break; } gpio_set_func(port, fun, 1<< (gpioPort % 32)); if(fun == GPIO_OUTPUT0||fun == GPIO_OUTPUT1)   { if(fun == GPIO_OUTPUT0) gpio_direction_output(gpioPort, 0); else gpio_direction_output(gpioPort, 1); } } static void write_SLCD_CD(int isCOMD,unsigned int value) //寫命令/數據
{ #define  SLCD_DC    20
    #define  SLCD_WR   17
    #define  SLCD_RD    16
    #define  SLCD_CS     18
    
    int i; gpio_direction_output(GPIO_PB(SLCD_CS), 1); for( i=0;i<8;i++) { gpio_setfunc(GPIO_PA(i),GPIO_OUTPUT0); gpio_direction_output(GPIO_PA(i), (value>>i)&0x01); } mdelay(10); if(isCOMD!=0)    //如果是寫命令,則拉低DC腳
 { gpio_direction_output(GPIO_PB(SLCD_DC), 0); } else { gpio_direction_output(GPIO_PB(SLCD_DC),1); } gpio_direction_output(GPIO_PB(SLCD_WR), 0); gpio_direction_output(GPIO_PB(SLCD_RD), 1); gpio_direction_output(GPIO_PB(SLCD_CS), 0); mdelay(4); gpio_direction_output(GPIO_PB(SLCD_WR), 1); mdelay(7); } static unsigned int read_SLCD_DATA(void)   //讀數據
{ #define  SLCD_DC    20
    #define  SLCD_WR   17
    #define  SLCD_RD    16
    #define  SLCD_CS     18
    
    int i; int ret=0; gpio_direction_output(GPIO_PB(SLCD_CS), 1);     //取消片選
    
    for( i=0;i<8;i++)        //將data腳設為輸入腳
 { gpio_setfunc(GPIO_PA(i),GPIO_INPUT); } gpio_direction_output(GPIO_PB(SLCD_DC), 1); gpio_direction_output(GPIO_PB(SLCD_WR), 1); gpio_direction_output(GPIO_PB(SLCD_RD), 0); gpio_direction_output(GPIO_PB(SLCD_CS), 0);     //選中片選
 mdelay(4); gpio_direction_output(GPIO_PB(SLCD_RD), 1); for( i=0;i<8;i++) ret|=(gpio_get_value(GPIO_PA(i))<<i); mdelay(7); return ret; } static void lcd_func_init(int isRestore) { int i,n; #define  SLCD_DC    20
    #define  SLCD_WR   17
    #define  SLCD_RD    16
    #define  SLCD_TE     19            //input
     #define  SLCD_CS     18
       
 
      
     if(isRestore) //恢復管腳為LCD控制寄存器 { for(i=0;i<8;i++) gpio_setfunc(GPIO_PA(i),GPIO_FUNC_1); gpio_setfunc(GPIO_PB(SLCD_DC),GPIO_FUNC_1); gpio_setfunc(GPIO_PB(SLCD_WR),GPIO_FUNC_1); gpio_setfunc(GPIO_PB(SLCD_RD),GPIO_FUNC_1); gpio_setfunc(GPIO_PB(SLCD_TE),GPIO_FUNC_1); gpio_setfunc(GPIO_PB(SLCD_CS),GPIO_FUNC_1); } else                          //設置為普通IO管腳 { for(i=0;i<8;i++) gpio_setfunc(GPIO_PA(i),GPIO_OUTPUT0); gpio_setfunc(GPIO_PB(SLCD_DC),GPIO_OUTPUT0); gpio_setfunc(GPIO_PB(SLCD_WR),GPIO_OUTPUT0); gpio_setfunc(GPIO_PB(SLCD_RD),GPIO_OUTPUT0); gpio_setfunc(GPIO_PB(SLCD_TE),GPIO_INPUT); gpio_setfunc(GPIO_PB(SLCD_CS),GPIO_OUTPUT0); } mdelay(200); } static u8 Read_ID_isNewLcd(void) { #define  SLCD_DC    20
    #define  SLCD_WR   17
    #define  SLCD_RD    16
    #define  SLCD_TE     19            //input
     #define  SLCD_CS     18 u8 ret = 0; u8 IDH,IDL; lcd_func_init(0);   //設置LCD相關的引腳,設置為普通IO腳
    
write_SLCD_CD(1,0x04);  //寫入0x04命令 IDH = read_SLCD_DATA(); IDL = read_SLCD_DATA(); printf("Read ID: 0x%X 0x%X\r\n",IDH,IDL); IDH = read_SLCD_DATA(); IDL = read_SLCD_DATA(); printf("Read ID: 0x%X 0x%X\r\n",IDH,IDL); if(IDL!=0x52) //如果值!=0X52,則表示是舊屏ili9335 { ret =1; } lcd_func_init(1); //將lcd相關引腳配置為LCD控制腳 mdelay(10); return ret; } extern void switch_lcd_New(void) ; static int lcd_type_isNew=0; void set_lcd_type_from_cmdline(void) //設置bootargs,向內核傳遞lcd_type參數 { if(lcd_type_isNew) { run_command("set bootargs "CONFIG_BOOTARGS" lcd_type=new ", 0); } }
//在lcd_ctrl_init()函數里添加讀ID函數
void lcd_ctrl_init(void *lcd_base) { if(Read_ID_isNewLcd()==0) //讀ID,檢測是否是新屏 { printf("Read_ID_isNewLcd=0\r\n"); switch_lcd_New(); //調用Lcd-ili9335_240x320.c的切換新屏參數的函數 lcd_type_isNew=1; } //... ... 后面的代碼不需要修改,因為后面便會根據LCD初始化參數表.來初始化LCD }

上面的set_lcd_type_from_cmdline()函數需要在后面調用main_loop()的時候之前被調用,所以還需要修改board_init_r()函數(arch\mips\lib\Board.c ).

 

然后裝上舊屏ili9335,啟動uboot,查看讀的屏幕ID,屏幕顯示正常:

 

然后換為新屏,啟動uboot,查看讀的ID信息,log顯示正常:

啟動內核時,也可以看到傳遞給內核bootargs有我們新添的參數:

然后在內核中,便通過新參數再次設置屏參數表即可.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM