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

9 thoughts on “Linux Framebuffer fbtft with SPI DMA for Intel Edison

  1. I’m fixing this particular issue right now. I’m about to push some stuff to my **eds** branch on GitHub to support iDMA 32-bit and enable it for SPI. Would you be interested in that? (My stuff is targeting upstream kernel, so, sooner or later we will have this code in upstream).

    1. Today I sent contents of my branch to upstream mailing lists. Regarding to GPIO (actually it’s a property of so called FLIS, i.e. pin control, IP) you need to setup pin control configuration tables in your code. The pin control driver is in upstream starting from v4.8.

  2. Thanks for the patch farit! I managed to compile the kernel and get the DMA feature running. One question though, using this kernel version seemed to break the support of using mraa set GPIO? I no longer able to initialize any GPIO context.

      1. Eventually in v5.7 we will have fbtft driver which can be used from ACPI without any recompilation required! I managed to test three (ili9341, ssd1306, hx8347d) displays myself and one more is coming (ssd1331).

    1. There were patches against MRAA for new kernel. But I recommend to use standard kernel interfaces directly. See more details on edison-fw project on GitHub.

Leave a Reply to Farit Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>