AnsweredAssumed Answered

i.MX6 MIPI-DSI Display ( ST7701 controller)

Question asked by Bastos Rui on Dec 28, 2018

Hi,

 

I'm trying to add a mipi-dsi display to our custom board (Ixora based, with mipi-dsi connector available), using Apalis iMX6 Dual. The display (http://www.cct.com.my/pdf/TFT-color-spec2017/4.0%20-T400A01X00_REV2/4.0%20-T400A01X00_REV2.pdf) uses a Sitronix ST7701 controller ( http://www.startek-lcd.com/res/starteklcd/pdres/201705/20170512144242904.pdf ).

No modifications are made in u-boot. The modification in the imx6qdl-apalis-ixora-v1.1_custom.dtsi file, to allow mipi-dsi are:

 

  1. &mxcfb1 {
  2. disp_dev = "mipi_dsi";
  3. interface_pix_fmt = "RGB24";
  4. mode_str ="ST7701-WVGA";
  5. default_bpp = <24>;
  6. status = "okay";
  7. };
  8. &mipi_dsi {
  9. dev_id = <0>;
  10. disp_id = <1>;
  11. lcd_panel = "ST7701-WVGA";
  12. pinctrl-names = "default";
  13. pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
  14. reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
  15. reset-delay-us = <120000>;
  16. #reset-cells = <0>;
  17. status = "okay";
  18. };

the driver code

 

 #define REFRESH      60
 #define XRES         480
 #define YRES         854
 
 #define LEFT_MARGIN  12       /* HBP horizontal back porch    */
 #define RIGHT_MARGIN 38       /* HFP horizontal front porch   */
 #define HSYNC_LEN    12       /* HSW horizontal pulse width   */
 
 #define UPPER_MARGIN 4        /* VBP vertical back porch      */
 #define LOWER_MARGIN 18       /* VFP vertical front porch     */
 #define VSYNC_LEN    8        /* VSW vertical low pulse width */
 
 #define PIXCLOCK KHZ2PICOS( (XRES + LEFT_MARGIN + RIGHT_MARGIN + HSYNC_LEN)* (YRES + UPPER_MARGIN + LOWER_MARGIN + VSYNC_LEN) * REFRESH / 1000 )
 
 static int st7701_bl_brightness;
 
 static struct fb_videomode st7701_lcd_modedb[] = {
     {
         "ST7701-WVGA",              /* name                 */
         REFRESH,                    /* refresh / frame rate */
         XRES, YRES,                 /* resolution           */
         PIXCLOCK,                   /* pixel clock          */
         LEFT_MARGIN, RIGHT_MARGIN,  /* l/r margin           */
         UPPER_MARGIN, LOWER_MARGIN, /* u/l margin           */
         HSYNC_LEN, VSYNC_LEN,       /* hsync/vsync length   */
         FB_SYNC_OE_LOW_ACT,         /* sync                 */
         FB_VMODE_NONINTERLACED,     /* vmode FB_VMODE_NONINTERLACED FB_VMODE_INTERLACED FB_VMODE_DOUBLE */
         0,                          /* flag FB_MODE_IS_DETAILED*/
     },
 };
 
 
 static inline int st7701_dsi_write(struct mipi_dsi_info *mipi_dsi, const void *seq, size_t len)
 {
   int err;
   
   err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi,MIPI_DSI_GENERIC_LONG_WRITE, (u32*)seq, len);
   CHECK_RETCODE(err);
 }
 
 #define ST7701_DSI(mipi_dsi, seq...)                \
 {                                                   \
     const u8 d[] = { seq };                         \
     st7701_dsi_write(mipi_dsi, d, ARRAY_SIZE(d));   \
 }
 
 static struct mipi_lcd_config lcd_config = {
     .virtual_ch     = 0,
     .data_lane_num  = 2,
     .max_phy_clk    = 800,
     .dpi_fmt        = MIPI_RGB888,
 };
 
 void mipid_st7701_get_lcd_videomode(struct fb_videomode **mode, int *size,
                                     struct mipi_lcd_config **data)
 {
 
     *mode = &st7701_lcd_modedb[0];
     *size = ARRAY_SIZE(st7701_lcd_modedb);
     *data = &lcd_config;
 }
 
 
 int mipid_st7701_lcd_setup(struct mipi_dsi_info *mipi_dsi)
 {
   u8 buf[DSI_CMD_BUF_MAXSIZE];
    
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI st7701 LCD PIXCLOCK %d \n",KHZ2PICOS(PIXCLOCK));
   
   ST7701_DSI(mipi_dsi, MIPI_DCS_SOFT_RESET, 0x00);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI SOFT RESET ...OK.\n");     
   
   /* We need to wait 5ms before sending new commands */
   msleep(5);  
 
   ST7701_DSI(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE, 0x00);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Sleep Out ...OK.\n");      
   
   msleep( 80 );   // sleep delay
 
   // Command2, BK0
   // Display Control setting
   ST7701_DSI(mipi_dsi, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL );  
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Command2_BK0 Function Selection ...OK.\n");    
 
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK0_NVGAMCTRL, 0x00, 0x0E, 0x95, 0x0F, 0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E, 0x2C, 0x34, 0x1F);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Negative Voltage Gamma Control ...OK.\n");
   
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK0_LNESET, DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1);  
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Display Line setting ...OK. [%d] [0x%02X]\n", st7701_lcd_modedb[0].xres, ((st7701_lcd_modedb[0].xres - 8)/8) );  
   
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK0_PORCTRL,DSI_CMD2_BK0_PORCTRL_B0(st7701_lcd_modedb),DSI_CMD2_BK0_PORCTRL_B1(st7701_lcd_modedb));
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Porch control ...OK. [0x%02X] [0x%02X]\n",DSI_CMD2_BK0_PORCTRL_B1(st7701_lcd_modedb), DSI_CMD2_BK0_PORCTRL_B0(st7701_lcd_modedb));
   
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK0_INVSEL, DSI_CMD2_BK0_INVSEL_B0, DSI_CMD2_BK0_INVSEL_B1);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Inversion selection & Frame Rate Control ...OK.\n");   
   
   /* Command2, BK1 */
   ST7701_DSI(mipi_dsi, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Command2_BK1 Function Selection ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_VRHS, DSI_CMD2_BK1_VRHA_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Vop amplitude setting ...OK.\n");  
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_VCOM, DSI_CMD2_BK1_VCOM_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI VCOM amplitude setting ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_VGHSS, DSI_CMD2_BK1_VGHSS_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI VGH Voltage setting ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI TEST Command Setting ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_VGLS, DSI_CMD2_BK1_VGLS_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI VGL Voltage setting ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_PWCTLR1, DSI_CMD2_BK1_PWCTLR1_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Power Control 1 ...OK.\n");  
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_PWCTLR2, DSI_CMD2_BK1_PWCTLR2_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Power Control 2 ...OK.\n");  
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_SPD1, DSI_CMD2_BK1_SPD1_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Source pre_drive timing set1 ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_SPD2, DSI_CMD2_BK1_SPD2_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Source pre_drive timing set2 ...OK.\n");
   ST7701_DSI(mipi_dsi, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_SET);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI MIPI Setting 1 ...OK.\n");   
   
   msleep(100);  
   
   /**
    * ST7701_SPEC_V1.2 is unable to provide enough information above this
    * specific command sequence, so grab the same from vendor BSP driver.
    */
    // GIP Settings
   ST7701_DSI(mipi_dsi, 0xE0, 0x00, 0x00, 0x02);
   ST7701_DSI(mipi_dsi, 0xE1, 0x0B, 0x00, 0x0D, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x44, 0x44);
   ST7701_DSI(mipi_dsi, 0xE2, 0x33, 0x33, 0x44, 0x44, 0x64, 0x00, 0x66, 0x00, 0x65, 0x00, 0x67, 0x00, 0x00);
   ST7701_DSI(mipi_dsi, 0xE3, 0x00, 0x00, 0x33, 0x33);
   ST7701_DSI(mipi_dsi, 0xE4, 0x44, 0x44);
   ST7701_DSI(mipi_dsi, 0xE5, 0x0C, 0x78, 0x3C, 0xA0, 0x0E, 0x78, 0x3C, 0xA0, 0x10, 0x78, 0x3C, 0xA0, 0x12, 0x78, 0x3C, 0xA0);
   ST7701_DSI(mipi_dsi, 0xE6, 0x00, 0x00, 0x33, 0x33);
   ST7701_DSI(mipi_dsi, 0xE7, 0x44, 0x44);
   ST7701_DSI(mipi_dsi, 0xE8, 0x0D, 0x78, 0x3C, 0xA0, 0x0F, 0x78, 0x3C, 0xA0, 0x11, 0x78, 0x3C, 0xA0, 0x13, 0x78, 0x3C, 0xA0);
   ST7701_DSI(mipi_dsi, 0xEB, 0x02, 0x02, 0x39, 0x39, 0xEE, 0x44, 0x00);
   ST7701_DSI(mipi_dsi, 0xEC, 0x00, 0x00);
   ST7701_DSI(mipi_dsi, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF);
   // End GIP Setting
   // End Power Control Registers Initial
   // End Bank1 Setting  
   
   /* disable Command2 */
   ST7701_DSI(mipi_dsi, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);  
   
   msleep(10);   
 
   ST7701_DSI(mipi_dsi, MIPI_DCS_SET_DISPLAY_ON, 0x00);
   dev_info(&mipi_dsi->pdev->dev, "MIPI DSI Display On ...OK.\n");   
   
   /* We need to wait 200ms after a sleep out command */
   msleep(200);    
 
   return 0;
 }

 

When Linux starts the driver is registered, but I cannot get a valid image,

 

 root@apalis-imx6:~# fbset -i
 mode "480x854-60"
     # D: 28.747 MHz, H: 53.039 kHz, V: 59.999 Hz
     geometry 480 854 480 864 32
     timings 34786 12 38 4 18 12 8
     rgba 8/16,8/8,8/0,8/24
 endmode
 
 Frame buffer device information:
     Name        : DISP3 BG - DI1
     Address     : 0x20800000
     Size        : 16715520
     Type        : PACKED PIXELS
     Visual      : TRUECOLOR
     XPanStep    : 1
     YPanStep    : 1
     YWrapStep   : 1
     LineLength  : 1920
     Accelerator : No

 

At linux boot the display image is

Linux boot

 

the LXDE desktop

LXDE

 

and the command

gst-launch-1.0 -v videotestsrc ! imxg2dvideosink force-aspect-ratio=false

gst-launch-1.0 -v videotestsrc

 

Anybody knows how to solve this?

Regards,

Rui

Outcomes