notro / fbtft

Linux Framebuffer drivers for small TFT LCD display modules. Development has moved to https://git.kernel.org/cgit/linux/kernel/git/gregkh/staging.git/tree/drivers/staging/fbtft?h=staging-testing
1.85k stars 494 forks source link

Can't initialize a 4.3" TFT SSD1963 display #327

Closed jaburjak closed 8 years ago

jaburjak commented 8 years ago

Hi, I bought this display: http://www.dx.com/p/wbyjb03-4-3-color-tft-lcd-display-module-for-arduino-mcu-learning-development-226028. I connected it to the Pi and run those commands, which I found in a notro's comment:

modprobe --first-time flexfb width=480 height=272 buswidth=16 init=-1,0xE2,0x2d,0x02,0x04,-1,0xE0,0x01,-2,1,-1,0xE0,0x03,-2,5,-1,0x01,-2,5,-1,0xE6,0x00,0xff,0xbe,-1,0xB0,0x20,0x00,0x01,0xDF,0x01,0x0F,0x00,-2,5,-1,0xB4,0x02,0x13,0x00,0x2B,0x0A,0x00,0x08,0x00,-1,0xB6,0x01,0x20,0x00,0x0C,0x0A,0x00,0x04,-1,0x36,0x00,-1,0xF0,0x03,-2,5,-1,0x29,-1,0xBE,0x06,0xf0,0x01,0xf0,0x00,0x00,-1,0xd0,0x0d,-1,0xB8,0x00,0x01,-1,0xBA,0x00,-3
modprobe --first-time fbtft_device name=flexpfb debug=3 gpios=reset:3,dc:2,wr:4,cs:13,db00:14,db01:15,db02:18,db03:17,db04:27,db05:22,db06:23,db07:24,db08:10,db09:25,db10:6,db11:19,db12:21,db13:20,db14:16,db15:26 rotate=0

I use the raspbian-ua-netinst version, which is a minimal Raspbian installation, so I had to compile the modules by myself, but they seem working. dmesg is not giving any strange messages, actually, it properly shows that there's a new graphics device:

graphics fb1: flexfb frame buffer, 480x272, 255 KiB video memory, 4 KiB DMA buffer memory, fps=20

However, the display stays just white. I run the wire testing script from the troubleshooting wiki page and it passed without problems, so I assume that there's a problem with initialization sequence. But I'm afraid that I don't have enough knowledge to fix this by myself and I wasn't able to find any helpful resources.

What now?

notro commented 8 years ago

I did some searching but I couldn't find any code for the display. You can contact the seller and ask for example code which will include the init sequence. You can also make a script to try and read from the controller to make sure it's really connected. Reset the controller and see if you can read back the default register values.

Be aware that the display will probably be very slow, so no movies. fbtft uses gpiolib to toggle the pins and it's slow for this use.

jaburjak commented 8 years ago

I have found some C codes, but all of them feature Write_Command and Write_Data commands, which I don't how to transfer to FBTFT init sequence and wiki doesn't really help…

notro commented 8 years ago

This init sequence:

-1,0xE2,0x2d,0x02,0x04,-1,0xE0,0x01,-2,1,-3

Could be written as:

Write_Command(0xE2);
Write_Data(0x2d);
Write_Data(0x02);
Write_Data(0x04);

Write_Command(0xE0);
Write_Data(0x01);

mdelay(1);

-1 is start of command/data sequence -2 is start of delay -3 is end of sequence

jaburjak commented 8 years ago

I'm sorry, is that some error or maybe I don't get it…

notro commented 8 years ago

Haha, yes the markdown was messed up. I've edited the post.

jaburjak commented 8 years ago

Allright, none of my attempts seem to work. Can you please point me to some resources where I can find how to make that script that reads the default register values from the controller?

notro commented 8 years ago

I didn't find any example.

But this is what you do: set all pins as output pull high: cs,wr,rd,reset

toggle reset low to reset the controller

pull cs low to enable

pull dc low pull wr low set db pins to the register you want to read: 0x0A pull wr high

set db pins as input pull dc high pull rd low read db values pull rd high

For details see the 8080 timing diagram in the ssd1963 datasheet

If you like python you could use RPi.GPIO: http://makezine.com/projects/tutorial-raspberry-pi-gpio-pins-and-python/

jaburjak commented 8 years ago

I'm afraid that I can't make the script by myself, so I keep trying to find the right initialization sequence. Could you at least tell me, if I should look for an init sequence for the SSD1963 or for the HannStar HSD043I9W1 display in particular?

notro commented 8 years ago

You need to find one for the panel.

jaburjak commented 8 years ago

Isn't there some generic initialization sequence? I really can't find anything and I'm not that advanced to make the script mentioned earlier. DealExtreme is not responding, neither does HannStar. I was able to find out that it's a HannStar HSD043I9W1 panel driven by SSD1963 and HX8257 chips, if that would help.

notro commented 8 years ago

The product page says ssd1963. The init sequence is panel+controller specific. So switching to another controller means a different init sequence. The controller has to be configured for a specific panel. Many panels have the same characteristics, but different controllers have different registers settings to express those characteristics.

jaburjak commented 8 years ago

So that means that I have to find the right commands for the SSD1963 and other panel, but I have to modify the data (e.g. width and height) to fit my panel?

notro commented 8 years ago

You need an init sequence for this controller and panel combination. The seller of the display should be able to provide that.

jaburjak commented 8 years ago

This is all I got. In the panel specification I found this:

Power on sequence: VDD » DISP » Data » VLED
Data include R0~R7, G0~G7, B0~B7, HSD, VSD, DCLK, DE
notro commented 8 years ago

The 'SSD1963 Eval Rev2A User’s Guide' in the linked rar file has this address: http://www.techtoys.com.hk/Displays/SSD1963EvalRev2A/SSD1963%20Eval%20Board%20Rev2A.htm Download 'A port for Microchip Graphics Library v2.00': http://www.techtoys.com.hk/Displays/SSD1963EvalRev2A/src/GUIv200.rar

From GUIv200.rar\Microchip\Graphics\Drivers\SSD1963.c:

void ResetDevice(void)
{
    RST_LAT_BIT = 1;        
    RST_TRIS_BIT = 0;       // enable RESET line

    RS_TRIS_BIT = 0;        // enable RS line 

    CS_LAT_BIT = 1;         // SSD1963 is not selected by default
    CS_TRIS_BIT = 0;        // enable SSD1963 CS line    

    RD_LAT_BIT = 1;
    RD_TRIS_BIT = 0;

    WR_LAT_BIT = 1;
    WR_TRIS_BIT = 0;

    // PMP setup 
    PMMODE = 0; PMAEN = 0; PMCON = 0;
    PMMODEbits.MODE   = 2;  // Intel 80 master interface
    // Before PLL is set and locked, the reference clock = crystal freq.
    // Set the largest data setup time for 10MHz clock
    PMMODEbits.WAITB  = 3;
    PMMODEbits.WAITM  = 15;
    PMMODEbits.WAITE  = 3;

#ifdef USE_16BIT_PMP
    PMMODEbits.MODE16 = 1;  // 16 bit mode
#else
    PMMODEbits.MODE16 = 0;  // 8 bit mode
#endif

    PMCONbits.PTRDEN = 0;   // disable RD line
    PMCONbits.PTWREN = 0;   // disable WR line
    PMCONbits.PMPEN  = 1;   // enable PMP

    RST_LAT_BIT = 0;
    DelayMs(1);
    RST_LAT_BIT = 1;       // release from reset state to sleep state

    //Set MN(multipliers) of PLL, VCO = crystal freq * (N+1)
    //PLL freq = VCO/M with 250MHz < VCO < 800MHz
    //The max PLL freq is around 120MHz. To obtain 120MHz as the PLL freq

    WriteCommand(0xE2);             // Set PLL with OSC = 10MHz (hardware)
                                    // Multiplier N = 35, VCO (>250MHz)= OSC*(N+1), VCO = 360MHz
    CS_LAT_BIT = 0;
    WriteData(0x23);
    WriteData(0x02);                // Divider M = 2, PLL = 360/(M+1) = 120MHz
    WriteData(0x54);                // Validate M and N values
    CS_LAT_BIT = 1; 

    WriteCommand(0xE0);             // Start PLL command
    CS_LAT_BIT = 0;
    WriteData(0x01);                // enable PLL
    CS_LAT_BIT = 1; 

    DelayMs(1);                     // wait stablize
    WriteCommand(0xE0);             // Start PLL command again
    CS_LAT_BIT = 0;
    WriteData(0x03);                // now, use PLL output as system clock  
    CS_LAT_BIT = 1; 
    //once PLL locked (at 120MHz), the data hold time set shortest
    PMMODEbits.WAITB  = 0;
    PMMODEbits.WAITM  = 0;
    PMMODEbits.WAITE  = 0;  

    WriteCommand(0x01);             // Soft reset
    DelayMs(10);
    /*
    ***********************************
    * 4.3" TFT panel model # TY430TFT480272
    ***********************************
    */
#if (DISPLAY_PANEL==TY430TFT480272) 
    //Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
    //Typical DCLK for TY430TFT480272 is 9MHz
    //9MHz = 120MHz*(LCDC_FPR+1)/2^20
    //LCDC_FPR = 78642 (0x13332)
    WriteCommand(0xE6);
    CS_LAT_BIT = 0;
    WriteData(0x01);
    WriteData(0x33);
    WriteData(0x32);
    CS_LAT_BIT = 1;
    /*
    ****************************************************************
    * 7" TFT model # TY700TFT800480
    ****************************************************************
    */
#elif (DISPLAY_PANEL==TY700TFT800480)
    //Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
    //Typical DCLK for TY700TFT800480 is 33.3MHz(datasheet), experiment shows 30MHz gives a stable result
    //30MHz = 120MHz*(LCDC_FPR+1)/2^20
    //LCDC_FPR = 262143 (0x3FFFF)
    //Time per line = (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)/30 us = 1056/30 = 35.2us
    WriteCommand(0xE6);
    CS_LAT_BIT = 0;
    WriteData(0x03);
    WriteData(0xff);
    WriteData(0xff);    
    CS_LAT_BIT = 1;
    /*
    ***********************************
    * 3.5" TFT model # LVC75Z779V1S
    ***********************************
    */
#elif (DISPLAY_PANEL==LVC75Z779V1S)
    //Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
    //Typical DCLK for LVC75Z779V1S is 6.5MHz in 24 bit format
    //6.5MHz = 120MHz*(LCDC_FPR+1)/2^20
    //LCDC_FPR = 56796 (0x00DDDC)
    WriteCommand(0xE6);
    CS_LAT_BIT = 0;
    WriteData(0x00);
    WriteData(0xDD);
    WriteData(0xDC);
    CS_LAT_BIT = 1;
#endif

    //Set panel mode, varies from individual manufacturer
    WriteCommand(0xB0);
#if ((DISPLAY_PANEL==TY430TFT480272)||(DISPLAY_PANEL==LVC75Z779V1S))
    CS_LAT_BIT = 0;
    WriteData(0x20);                // set 24-bit for TY430TF480272 4.3" panel or LVC75Z779V1S 3.5" TFT Panel
    WriteData(0x00);                // set Hsync+Vsync mode
    WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
    WriteData(DISP_HOR_RESOLUTION-1);
    WriteData((DISP_VER_RESOLUTION-1)>>8);
    WriteData(DISP_VER_RESOLUTION-1);
    WriteData(0x00);                //RGB sequence
    CS_LAT_BIT = 1;
#elif (DISPLAY_PANEL==TY700TFT800480)
    CS_LAT_BIT = 0;
    WriteData(0x10);                // set 18-bit for 7" panel TY700TFT800480
    WriteData(0x80);                // set TTL mode
    WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
    WriteData(DISP_HOR_RESOLUTION-1);
    WriteData((DISP_VER_RESOLUTION-1)>>8);
    WriteData(DISP_VER_RESOLUTION-1);
    WriteData(0x00);                //RGB sequence  
    CS_LAT_BIT = 1;
#endif

    //Set horizontal period
    WriteCommand(0xB4);
    #define HT (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)
    CS_LAT_BIT = 0;
    WriteData((HT-1)>>8);   
    WriteData(HT-1);
    #define HPS (DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH)
    WriteData((HPS-1)>>8);
    WriteData(HPS-1);
    WriteData(DISP_HOR_PULSE_WIDTH-1);
    WriteData(0x00);
    WriteData(0x00);
    WriteData(0x00);
    CS_LAT_BIT = 1;
    //Set vertical period
    WriteCommand(0xB6);
    #define VT (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH+DISP_VER_FRONT_PORCH+DISP_VER_RESOLUTION)
    CS_LAT_BIT = 0;
    WriteData((VT-1)>>8);
    WriteData(VT-1);
    #define VSP (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH)
    WriteData((VSP-1)>>8);
    WriteData(VSP-1);
    WriteData(DISP_VER_PULSE_WIDTH-1);
    WriteData(0x00);
    WriteData(0x00);
    CS_LAT_BIT = 1;

    //Set pixel format, i.e. the bpp
    WriteCommand(0x3A);
    CS_LAT_BIT = 0;
    WriteData(0x55);                // set 16bpp
    CS_LAT_BIT = 1;

    //Set pixel data interface
    WriteCommand(0xF0);
    CS_LAT_BIT = 0;
#ifdef USE_16BIT_PMP
    WriteData(0x03);                //16-bit(565 format) data for 16bpp PIC32MX only
#else
    WriteData(0x00);                //8-bit data for 16bpp, PIC24 series
    CS_LAT_BIT = 1;
#endif

#if ((DISPLAY_PANEL==TY430TFT480272)||(DISPLAY_PANEL==LVC75Z779V1S))
    WriteCommand(0xB8);             // Set all GPIOs to output, controlled by host
    CS_LAT_BIT = 0;
    WriteData(0x0f);                // Set GPIO0 as output
    WriteData(0x01);                // GPIO[3:0] used as normal GPIOs
    CS_LAT_BIT = 1;
    // LL Reset to LCD!!!
    GPIO_WR(LCD_SPENA, 1);
    GPIO_WR(LCD_SPCLK, 1);
    GPIO_WR(LCD_SPDAT,1);
    GPIO_WR(LCD_RESET,1);
    GPIO_WR(LCD_RESET,0);
    DelayMs(1);
    GPIO_WR(LCD_RESET,1);
#endif

#if (DISPLAY_PANEL==LVC75Z779V1S)
    SPI_SetReg(0x01, 0x7300);                   // 0x73 gives the best result by trial-an-error
    SPI_SetReg(0x02, 0x0200);
    SPI_SetReg(0x03, 0x6364);
    SPI_SetReg(0x04, 0x0407);                   // Set himax for 24-bit parallel TFT mode
    SPI_SetReg(0x05, 0xBCC4);
    SPI_SetReg(0x0A, 0x4008);
    SPI_SetReg(0x0B, 0xD400);
    SPI_SetReg(0x0D, 0x3229);
    SPI_SetReg(0x0E, 0x3200);
    SPI_SetReg(0x0F, 0x0000);
    SPI_SetReg(0x16, 0x9F80);
    SPI_SetReg(0x17, 0x2212);
    SPI_SetReg(0x1E, 0x0052);
    SPI_SetReg(0x30, 0x0000);
    SPI_SetReg(0x31, 0x0407);
    SPI_SetReg(0x32, 0x0202);
    SPI_SetReg(0x33, 0x0000);
    SPI_SetReg(0x34, 0x0505);
    SPI_SetReg(0x35, 0x0003);
    SPI_SetReg(0x36, 0x0707);
    SPI_SetReg(0x37, 0x0000);
    SPI_SetReg(0x3A, 0x0904);
    SPI_SetReg(0x3B, 0x0904);
#endif

    WriteCommand(0x29);             // Turn on display; show the image on display   
}

You need to find which DISPLAY_PANEL you got and extract the register settings.

jaburjak commented 8 years ago

Apparentely, I'm still missing something. This is what dmesg tells me:

[   13.212355] fbtft_device:  SPI devices registered:
[   13.224907] fbtft_device:  'fb' Platform devices registered:
[   13.251632] fbtft_device:      bcm2708_fb id=-1 pdata? no
[   13.919026] graphics fb1: flexfb frame buffer, 480x272, 255 KiB video memory, 4 KiB DMA buffer memory, fps=20
[   13.955665] fbtft_device:  GPIOS used by 'flexpfb':
[   13.979371] fbtft_device:    'reset' = GPIO2
[   13.995697] fbtft_device:    'dc' = GPIO3
[   14.015690] fbtft_device:    'wr' = GPIO4
[   14.031185] fbtft_device:    'cs' = GPIO10
[   14.051710] fbtft_device:    'rd' = GPIO25
[   14.063651] fbtft_device:    'db00' = GPIO14
[   14.083578] fbtft_device:    'db01' = GPIO15
[   14.092960] fbtft_device:    'db02' = GPIO18
[   14.115578] fbtft_device:    'db03' = GPIO17
[   14.147671] fbtft_device:    'db04' = GPIO27
[   14.168026] fbtft_device:    'db05' = GPIO22
[   14.187760] fbtft_device:    'db06' = GPIO23
[   14.199073] fbtft_device:    'db07' = GPIO24
[   14.212276] fbtft_device:  'fb' Platform devices registered:
[   14.239633] fbtft_device:      bcm2708_fb id=-1 pdata? no
[   14.271344] fbtft_device:      flexpfb id=0 pdata? yes

This is how I start the modules (content of /etc/modules):

flexfb width=480 height=272 buswidth=8 regwidth=16 init=-1,0xE2,0x23,0x02,0x54,-1,0x01,-2,1,-1,0xE0,0x03,-1,0x01,-2,10,-1,0xE6,0x01,0x33,0x32,-1,0xB0,0x20,0x00,0x1,0x1DF,0x1,0x10F,0x00,-1,0xB4,0x2,0x20D,0x0,0x28,0x0,0x00,0x00,-1,0xB6,0x1,0x120,0x0,0x8,0x0,0x00,0x00,-1,0x3A,0x55,-1,0xF0,0x00,-1,0xB8,0x0F,0x01,-2,1,-1,0x29,-3
fbtft_device name=flexpfb verbose=3 gpios=reset:2,dc:3,wr:4,cs:10,rd:25,db00:14,db01:15,db02:18,db03:17,db04:27,db05:22,db06:23,db07:24 rotate=0

And these are the display panel parameters:

DISP_HOR_RESOLUTION   = 480
DISP_HOR_PULSE_WIDTH  = 1
DISP_HOR_BACK_PORCH   = 40
DISP_HOR_FRONT_PORCH  = 5
HT                    = 526
HPS                   = 41
DISP_VER_PULSE_WIDTH  = 1
DISP_VER_BACK_PORCH   = 8
DISP_VER_FRONT_PORCH  = 8
DISP_VER_RESOLUTION   = 272
VT                    = 289
VSP                   = 9

But the screen is still all white.

jaburjak commented 8 years ago

I have one more question – can not delivering enough power to the display cause it stays white? Because everything seems set up right, the only thing that comes to my mind is that maybe the display doesn't have enough current and that's the reason why it just lights up and doesn't react to the commands.

notro commented 8 years ago

You would get warnings on B+ if that where the case: https://www.raspberrypi.org/forums/viewtopic.php?t=82373 Do you power the backlight from 5V or 3V3?

jaburjak commented 8 years ago

I power it from 5V, using the GPIO on the Pi. And indeed, the red LED goes off a few moments after the Pi boots.

notro commented 8 years ago

Try controlling backlight manually and turn it on after boot and see what happens.

notro commented 8 years ago

Closing old issues, reopen if needed.