Apalis iMX6 MIPI DSI display

Hi,

I’m trying to add a mipi-dsi display to our custom board (Ixora based, with mipi-dsi connector available).
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:

&mxcfb1 {
	disp_dev = "mipi_dsi";
	interface_pix_fmt = "RGB24";
        mode_str ="ST7701-WVGA";
	default_bpp = <24>;
	status = "okay";
};

&mipi_dsi {
	dev_id = <0>;  
	disp_id = <1>;
	lcd_panel = "ST7701-WVGA";	
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
	reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
	reset-delay-us = <120000>;
	#reset-cells = <0>;		
	status = "okay";
};

The driver code is

#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
[upload|Jsj1NEupLgkVZFrWMa8q+Hi3o9E=]

the LXDE desktop
[upload|/BjbXWR3k6rnSOq5+pgDkr/B6Ts=]

and the command

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

[upload|D58bwXlx7MGg0MhBQU51gssl0uE=]

Anybody knows how to solve this?

Regards,

Rui

hi @rbastos

Happy New Year.

Unfortunately we don’t have experience in using DSI Display and we won’t have any plan to bring up the MIPI-DSI interface here at Toradex. Please also have a look on this thread.

Thanks and best regards, Jaski

Hi @rbastos,

I am facing the same issue with my MIPI display, did you ever solve this problem?