Linux Framebuffer fbtft with SPI DMA for Intel Edison

When you want to connect a display to the Intel Edison module, you should utilise the existing Linux infrastructure and use a kernel framebuffer driver instead of writing your own screen functions based on Arduino libraries.

The schematics and more technical information about my display and board are in my previous post: Framebuffer fbtft Installation on Intel Edison for OLED Display SSD1322.

At the time of writing the article, the Linux kernel SPI support was broken in the original Intel kernel. So, I used Primiano’s kernel that fixed the SPI support. It works perfectly for me, it may not contain the latest Intel’s modifications. Use it on your own risk.

First, I downloaded the Intel sources from http://iotdk.intel.com/src/3.0/edison/. I extracted them into ~/edison in my home directory and followed the instructions for compiling it.

cd ~/edison/poky/
source oe-init-build-env ../build_edison/
bitbake edison-image u-boot
../poky/meta-intel-edison/utils/flash/postBuild.sh .
./toFlash/flashall.sh

Then I replaced the kernel in ~/edison/poky/linux-kernel by my own, but I kept the directories .git and .meta intact.
I increased the revision number in the variable PR = “r3″ in the file ~/edison/poky/meta-intel-edison/meta-intel-edison-bsp/recipes-kernel/linux/linux-externalsrc.bb
I added my new configuration parameters for fbtft into the file ~/edison/poky/linux-kernel/arch/x86/configs/i386_edison_defconfig

I downloaded the fbtft sources. I created the folder ~/edison/poky/linux-kernel/drivers/video/fbtft and extracted the fbtft sources into the folder.

I added the line in ~/edison/poky/linux-kernel/drivers/video/Kconfig before the line “endmenu”.

source "drivers/video/fbtft/Kconfig"

I added the line in ~/edison/poky/linux-kernel/drivers/video/Makefile

obj-$(CONFIG_FB_TFT)    += fbtft/

Then I edited the file ~/edison/poky/linux-kernel/drivers/video/fbtft/fbtft_device.c

I added the header

#include <linux/spi/intel_mid_ssp_spi.h>

Then I added the description of my display into the list of displays.
Where “reset” uses the number 49 of the GP49 pin, “dc” is GP15.
The pin “led” is GP14 and I use it in my custom initialization code in the file fb_ssd1322.c

It seems that the chip SSD1322 supports speeds only up to 12.5MHz, but the Edison must be able to support speeds up to 25MHz.

{
   .name = "er_oled028",
   .spi = &(struct spi_board_info) {
       .modalias = "fb_ssd1322",
       .max_speed_hz = 12500000,
       .mode = SPI_MODE_3,
       .bus_num = 5,
       .chip_select = 0,
       .controller_data = &(struct intel_mid_ssp_spi_chip) {
           .burst_size = DFLT_FIFO_BURST_SIZE,
           .timeout = DFLT_TIMEOUT_VAL,
           .dma_enabled = true,
        },
        .platform_data = &(struct fbtft_platform_data) {
           .display = {
               .buswidth = 8,
               .backlight = 0,
               .width = 256,
               .height = 64,
           },
           .gpios = (const struct fbtft_gpio []) {
               { "reset", 49 },
               { "dc", 15},
               { "led", 14},
               {},
           },
       }
   }
},

I modified the file ~/edison/poky/linux-kernel/drivers/video/fbtft/fbtft-core.c

--- fbtft-core.c	2015-03-05 02:54:01.000000000 -0800
+++ fbtft-core.c.new	2016-05-30 19:19:21.000000000 -0700
@@ -863,7 +863,7 @@
 	if (txbuflen > 0) {
 		if (dma) {
 			dev->coherent_dma_mask = ~0;
-			txbuf = dmam_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA);
+			txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_DMA | GFP_ATOMIC);
 		} else {
 			txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
 		}

I added the lines to the file ~/edison/poky/meta-intel-edison/meta-intel-edison-bsp/conf/machine/edison.conf to autoload the fbtft module.
Where busnum=5 is the SPI bus number on the Edison.,
name=er_oled028 defines my oled display from fbtft_device.c,
debug=7 shows more debugging information. It’s optional.

KERNEL_MODULE_AUTOLOAD += "fbtft_device"
module_conf_fbtft_device = "options fbtft_device name=er_oled028 busnum=5 debug=7"
KERNEL_MODULE_PROBECONF += "fbtft_device"

Then I recompiled the kernel and flashed my Edison.

I compiled mplayer on the Edison and played a sample video. I couldn’t find a video with the same dimensions as my display, but it should work in the full-screen mode too.

/usr/local/bin/mplayer -vo fbdev ultra.mp4
Downloads

Linux kernel for Edison with SPI DMA fixes and fbtft framebuffer