Notro has added a generic frame buffer driver called flexfb in his fbtft driver framework. This driver resulted from the observation that most small TFT driver chips share a lot in common like data transfer scheme, pushing pixels, and setting the update window. The only major difference is found in the initialization sequence required to setup the connected TFT panel on your specific board. Therefore, the flexfb driver user needs only select some generic option (e.g. bus width, type of update window command) and a transcription of the init sequence found in the driver code during runtime. Then the driver can control the display.
The big advantage of this approach is that you only need to ship this one generic driver and you can support a large set of displays without actually coding them. Also adding a new device requires only extracting the init sequence from the display’s data sheet and you can test it on the command line without any driver code development!
I gave this nice approach a quick try with Watterott’s MI0283QT-9 display (that’s already fully supported in the ili9341fb driver of fbtft, but nevertheless the generic approach might be the future :)…
First I extracted the init sequence from the driver source code file ili9341fb.c (see ili9341fb_init_display() function) and wrote the commands and delays in the init notation of flexfb:
// ILI9341 init sequence -1,0x28,-2,20 // 0x28 DISPLAY_OFF -1,0xCF,0x00,0x83,0x30 // 0xCF POWER_CTRLB -1,0xED,0x64,0x03,0x12,0x81 // 0xED POWERON_SEQ_CTRL -1,0xE8,0x85,0x01,0x79, // 0xE8 DRV_TIMING_CTRLA -1,0xCB,0x39,0x2c,0x00,0x34,0x02 // 0xCB POWER_CTRLA -1,0xF7,0x20 // 0xF7 PUMP_RATIO_CTRL -1,0xEA,0x00,0x00 // 0xEA DRV_TIMING_CTRLB -1,0xC0,0x26 // 0xC0 POWER_CTRL1 -1,0xC1,0x11 // 0xC1 POWER_CTRL2 -1,0xC5,0x35,0x3E // 0xC5 VCOM_CTRL1 -1,0xC7,0xBE // 0xC7 VCOM_CTRL2 -1,0xB1,0x00,0x1B // 0xB1 FRAME_CTRL -1,0xB6,0x0a,0x82,0x27,0x00 // 0xB6 DISPLAY_CTRL -1,0xB7,0x07 // 0xB7 ENTRY_MODE -1,0x3A,0x55 // 0x3A PIXEL_FORMAT -1,0x36,0x38 // 0x36 MEMACCESS_CTRL -1,0x11,-2,120 // 0x11 SLEEP OUT -1,0x29,-2,20 // 0x29 DISPLAY_ON
-1 denotes the begin of a command, -2 <msec> a delay of given duration, and -3 ends the init sequence. See Notro’s flexfb Wiki page for details.
Then we need to transform the sequence into one call for the shell:
modprobe flexfb width=320 height=240 buswidth=9 init=\ -1,0x28,-2,20,-1,0xCF,0x00,0x83,0x30,-1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x01,0x79,\ -1,0xCB,0x39,0x2c,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00,-1,0xC0,0x26,-1,0xC1,0x11,\ -1,0xC5,0x35,0x3E,-1,0xC7,0xBE,-1,0xB1,0x00,0x1B,-1,0xB6,0x0a,0x82,0x27,0x00,-1,0xB7,0x07,\ -1,0x3A,0x55,-1,0x36,0x38,-1,0x11,-2,120,-1,0x29,-2,20,-3
Note the additional options: the ili9341 is operated in 9 bit SPI mode on the Watterott board and the TFT panel has a resolution of 320×240 pixels.
Now we can enable the driver with the fbtft_driver helper module:
modprobe fbtft_device name=flexfb cs=1 gpios=reset:23,led:24
Here we select the Chip Select 1 as that’s the slave select I use for connecting the display. The GPIOs for Reset and backlight LED are also specific to my setup and need to be adjusted if you connected those lines to other pins on the Raspi.
Voila! That’s it 🙂 … Almost… one thing is missing: The setup of the update window on my display does not work with the current flexfb implementation:( It already provides the right commands but only sets the low byte for width/height of the display and nulls the high bytes. This does not work for our 320 (> 255) width display.
I submitted a fix for this issue to my clone of the source repository and also a pull request for Notro’s mainline repository. So if you can’t wait then clone my repo and build a kernel from there or wait until Notro builds an updated release…
Then your Watterott display will run smoothly also with the generic driver setup!