SSD1322(SPI) fbtft framebuffer driver - alidaf/raspberryPi GitHub Wiki
##SSD1322(SPI) - Using the fbtft framebuffer driver (Raspbian)
I don't have any experience of the Linux kernel or writing hardware drivers but I have managed to write a very rudimentary framebuffer driver for this display that uses pthreads to continually write a buffer array to the display, and while it can handle 4-bit graphics, it doesn't have any frame scheduling or access to the device as a file, e.g. via /dev/fb0. It will not be able to provide console output during booting or make use of any packages that can write text and graphics to a framebuffer without writing more software beyond some simple demonstrations. Consequently I have tried to find an existing framebuffer driver that has these features.
There is a framebuffer project that aims to provide drivers for small display modules. The project includes devices for well over 20 different displays, plus a further 10 or more in a fork. The original project has now been included in the Linux kernel staging tree and further development has pretty much ceased. However, since Raspbian is moving towards a DMA system for drivers, it is likely that the staging tree will eventually become deprecated. The fork hasn't been synced with the parent for some time and there are now some disparities. Following the existing information on the fbtft framework has been difficult, but I have pieced together a guide that has enabled me to compile and test a driver for the SSD1322 display. This guide should also be applicable to some of the other displays provided in the original and forked repositories.
###Prerequisites
-
It is assumed that the SPI connections use the ALT0 (default) GPIO pins. The display's DC# and RESET# connections can be assigned to pretty much any other GPIO, but they will need to be identified and passed as parameters in the modprobe function, or specified in the device tree overlay file. The connections used for my project are shown in a schematic further below.
-
The code for the SSD1322 in the fork is a little out of date so pick up an up-to-date revision here. For other drivers the changes are due to the FBTFT_REGISTER_DRIVER function and adding some aliases for device tree overlay support. The required change for the function is as follows:
-
Edit the driver source file e.g. fb_ssd1322.c and find the following line (near the end of the file)...
FBTFT_REGISTER_DRIVER(DRVNAME, &display);
- and change it to...
FBTFT_REGISTER_DRIVER(DRVNAME, "Device id", &display);
e.g.
FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1322", &display);
Whatever device id is used, i.e. the "solomon,ssd1322" part, needs to match the device id in the device tree file (.dts) if an overlay is going to be used. Creating a device tree overlay is dealt with later.
- Add some module aliases just below that, in addition to the ones already there, e.g.
MODULE_ALIAS("spi:ssd1322");
MODULE_ALIAS("platform:ssd1322");
- Install bc:
sudo apt-get install bc
- Update the system to ensure parity with the kernel we are about to compile:
sudo apt-get update
sudo apt-get dist-upgrade
###Preparation
- Create a compilation folder for the kernel and drivers:
cd ~/
mkdir kernel
cd kernel
- Clone the kernel source code (just 1 layer deep):
git clone --depth=1 https://github.com/raspberrypi/linux
- Clone the notro framebuffer code:
cd linux/drivers/video
git clone https://github.com/notro/fbtft
- Copy the
fb_ssd1322.c
source code that was just modified to this folder:
cp <location of code>fb_ssd1322.c fbtft/
###Modify the compilation files
- Add the following line to Kconfig:
source "drivers/video/fbtft/Kconfig"
- Add the following line to Makefile:
obj-y += fbtft/
- Add the following lines to fbtft/Kconfig:
config FB_TFT_SSD1322
tristate "FB driver for the SSD1322 OLED Controller"
depends on FB_TFT
help
Framebuffer support for SSD1322
- Add the following line to fbtft/Makefile:
obj-$(CONFIG_FB_TFT_SSD1322) += fb_ssd1322.o
###Enable driver and compile
cd ~/kernel/linux
* For RPi2 and later:
KERNEL = kernel7
make bcm2709_defconfig
* For RPi1 and compute module:
KERNEL = kernel
make bcmrpi_defconfig
make menuconfig
- Enable the specific driver to be compiled as either inbuilt or a module:
Device Drivers --->
Graphics support --->
Frame buffer Devices --->
Support for small TFT LCD display modules --->
Highlight FB driver for the SSD1322 OLED Controller
and press M
to create a loadable kernel module. Feel free to turn off any that will not be used.
- Save and exit.
make -j4 zImage modules dtbs
Note: The -j4 switch is only for the rPi 2 (or newer) and enables multi-threaded compilation. Even with this, compilation will take some time.
sudo make modules_install
###Replace kernel and load module
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img
sudo shutdown -r now
This will reboot the computer with the new kernel.
- Load the driver and device modules:
sudo modprobe fb_ssd1322
sudo modprobe fbtft_device custom name=fb_ssd1322 width=256 height=64 speed=16000000 gpios=dc:23,reset:24
Note: The GPIO numbers for #DC (GPIO23) and #RESET (GPIO24) are dependent on how the display is wired to the pi and can be connected to almost any GPIO. It is assumed that the SPI connections are the default Raspberry Pi ALT0 SPI GPIO pins, i.e. MOSI (GPIO10), SCLK (GPIO11) & CE0 (GPIO8). MISO isn't used because the display registers cannot be read in SPI mode, hence why the WR# connection is wired directly to the GND (0V) line. The configuration used here is shown below. ###Configuration used
---------------------------------------------------------------------GND
| |
RPi | |
1 2 | |
[o o] | |
[o o] | SSD1322 |
[o o] | 1 2 |
[o o] |----GND[o o]+5V----(-----------,
[o o] | [o o]SCLK---(-------, |
[o o] ,---(---SDIN[o o] | | |
[o o] | |-------[o o]-------| | |
[o o]GPIO23-----, | |-------[o o]-------| | |
[o o]GPIO24-----(---, | |-------[o o]-------' | |
,-------MOSI[o o] | | | '--- WR#[o o]DC#--------, | |
| [o o] | '---(-----RESET#[o o]CS#----, | | |
| ,---SCLK[o o]CE0----, | | 2 1 | | | |
| | [o o] | | | | | | |
| | 25 26 '---(-------|-----------------------' | | |
| | | | | | |
| | '-------(---------------------------' | |
| | | | |
| '-------------------------------(-------------------------------' |
| | |
'-----------------------------------' ,-------------------'
|
---------------------------------------------------------------------+5V
###Testing This is a handy test that doesn't need X display drivers (from notro's wiki):
cd ~/
sudo apt-get install libnetpbm10-dev
git clone https://git.kernel.org/pub/scm/linux/kernel/git/geert/fbtest
cd fbtest
make
./fbtest --fbdev /dev/fb1
With some luck you should see a series of display tests. ###Loading modules at boot
- Create a file /etc/modules-load.d/ssd1322.conf and add the following lines:
spi-bcm2835
fbtft_device
- Create an options file /etc/modprobe.d/ssd1322.conf and add the modprobe options:
options fbtft_device custom name=fb_ssd1322 width=256 height=64 speed=16000000 gpios=dc:23,reset:24
- Reboot and check the modules have loaded:
lsmod
Note: This method has been superseded by the device tree method below. This will still work as-is for Raspbian < 4.4.37 but recent versions appear to be more thoroughly transitioned to the device tree method. This method may still work by adding device_tree=
to /boot/config.txt
.
###Creating an overlay to load the module on boot After upgrading to the latest version of Raspbian (4.4.37), the requirement for device trees appears to be much more in force and loading modules at boot using the above method no longer works without making some changes. Device trees appear pretty intimidating but by copying one from an existing driver and modifying it has actually been relatively easy although a deeper understanding would have helped. This thread helped in converting an existing device tree overlay to one that worked for the SSD1322.
- Install the dtc compiler:
sudo apt-get install device-tree-compiler
- Create the device tree file, e.g. my one for the SSD1322, or copy one for another driver and modify it. The main changes were to the name of the device and changing some of the default GPIOs. I also had to add some aliases but if you choose one of the dts files from notro's repository, the aliases should already be there although the device id's will need to be changed.
- Compile and copy the device tree file:
sudo dtc -@ -I dts -O dtb -o /boot/overlays/ssd1322-spi.dtbo ssd1322-spi-overlay.dts
- Load the overlay on boot by adding it to /boot/config.txt:
dtoverlay=ssd1322-spi
- Reboot and check overlay has been loaded:
sudo vcdbg log msg
There are some further troubleshooting tips in this thread. ###Console support (from notro's wiki) The display may be used as an interactive console with little effort. This will also display some boot information limited to everything after the fbtft module is loaded.
- Enable console support by adding the following to the end of the line in
/boot/cmdline.txt
:
fbcon=map:10
- Select a more suitable font, since the default font is fairly large:
sudo dpkg-reconfigure console-setup
There will be a series of questions that need responses:
Encoding to use on the console: <UTF-8>
Character set to support: <Guess optimal character set>
Font for the console: Terminus (default is VGA) <-- There is a short list of available fonts to choose from.
Font size: 6x12 (framebuffer only)
###Boot splash animation I haven't managed to get this working yet. The latest version of Plymouth appears to be broken and I've submitted an upstream bug report to Debian for now. ###Acknowledgements Thanks to notro for the original driver code and helping me through the empirical process of trying to combine what remains of the projects into something usable for me, and hopefully others.
Thanks also to presslab-us for adding some additional drivers, including the one for the SSD1322.
###To Do
Figure out how to allow console messages from boot so that a boot graphic can be displayed. This will need the module to be automatically loaded or compiled into the kernel.
Figure out how to write text with custom fonts and send graphics to the buffer.
Integrate this into the jivelite package.