Driving DPI LCD with Raspberry Pi

2016-01-11

Introduction

DPI (Display Pixel Interface), also commonly known as the parallel RGB interface. These interfaces are quite straight-forward, 16-24 bit of RGB data line (one pixel), horizontal and vertical sync signals, pixel clock, and data enable signal, that's it. The host needs to send the data continously to scan the screen. As the data directly scans the screen, so there won't be any additional tearing. DPI screens are quite common, and common ARM SoCs typically have controller for DPI screens as well. Though it's being slowly replaced by DSI.

In the past, Raspberry Pi never said the RPi could support DPI screens. On Raspberry Pi, the only possible way to connect LCD was through the DBI using GPIO, or using the HDMI. However last year, in the RPi official blog, there is one product: Gert’s VGA adapter for Raspberry Pi. It uses GPIO instead of HDMI to provide VGA, supports 1080p, supports 3D acceleration. This basically tells us, it uses DPI + R2R DAC to implement the VGA.

Given these, it should be possible to remove the R2R and directly use DPI to drive LCDs. There are already solution to do these: https://www.raspberrypi.org/forums/viewtopic.php?f=100&t=86658. Thanks to Gert van Loo for developing the VGA adapter and Dom Cobley for modifying the VideoCore IV firmware (closed source) so these are possible.

Usage

Disable the I2C and SPI (if enabled previously). Insert the SD card on to the PC, download http://adafruit-download.s3.amazonaws.com/dt-blob.bin and copy into the boot partition. Open config.txt, comment out everything related to HDMI, add the following:

#Overscan Information.
overscan_left=0
overscan_right=0
overscan_top=0
overscan_bottom=0
framebuffer_width=480
framebuffer_height=272

# Disable spi and i2c, we need these pins.
dtparam=spi=off
dtparam=i2c_arm=off

#Enable the lcd, enable custom display sizes with CVT, set as the default output.
enable_dpi_lcd=1
dpi_group=2
dpi_mode=87 # Hdmi CVT
display_default_lcd=1

dpi_output_format=520197
hdmi_timings=480 1 2 30 43 272 1 4 8 12 0 0 0 60 0 16000000 6

Save and exit. Next connect the wires, I am using 18bpp, with the pinmux defined as follows:

Once the screen is connected, bootup and test:

It's okay if it doesn't work the first time. First make sure overscan are all set to 0. Then setting the resolution. Note the pixel clock (160000000) must be at least 16MHz. The following is the definition for dpi_output_format, adjust based on the screen used:

Field Description Width
Ouput Format 0b0001: 9BIT 666 4bits
0b0010: 16BIT 565 CFG1
0b0011: 16BIT 565 CFG2
0b0100: 16BIT 565 CFG3
0b0101: 18BIT 666 CFG1
0b0110: 18BIT 666 CFG2
0b0111: 24BIT 888
RGB Arrangement 0b0001: RGB 4bits
0b0010: BGR
0b0011: GRB
0b0100: BRG
Sync Mode 0: DE mode /1: HVsync mode 1bit
Pixel Clock Polarity 0: Idle high /1: Idle low 1bit
Disable Hsync 0: Enable/ 1: Disable 1bit
Disable Vsync 0: Enable/ 1: Disable 1bit
Disable DE 0: Enable/ 1: Disable 1bit
Hsync Polarity 0: Normal/ 1: Inverted 1bit
Vsync Polarity 0: Normal/ 1: Inverted 1bit
DE Polarity 0: Normal/ 1: Inverted 1bit
Hsync Phase 0: Rising edge/ 1: Falling edge 1bit
Vsync Phase 0: Rising edge/ 1: Falling edge 1bit
DE Phase 0: Rising edge/ 1: Falling edge 1bit

Most of the values could be found in the datasheet. These forms 1 32bit number. For example, the configuration I need is 18BIT 666 CFG1, RGB, DE mode, idle high, enable HVsync and DE, inverted phase, here would be the value:

Then comes the hdmi timings, it has lot of parameters:

Name Description/ Unit
Horizontal active pixels
Horizontal sync polarity 0: Low active/ 1: High active
Horizontal front porch cycles
Horizontal sync width cycles
Horizontal back porch cycles
Vertical active lines
Vertical sync polarity 0: Low active/ 1: High active
Vertical front porch cycles
Vertical sync width cycles
Vertical back porch cycles
Vertical sync offset A -
Vertical sync offset B -
Pixel repitition -
Frame rate Hz
Interleave frames
Pixel rate Hz
Aspect ratio 1:4:3
2:14:9
3:16:9
4:5:4
5:16:10
6:15:9
7:21:9
8:64:27

Adding the correct values there and it should work.

Reference: http://blog.reasonablycorrect.com/raw-dpi-raspberry-pi/