BeagleBone Black - notro/fbtft GitHub Wiki

FBTFT on BeagleBone Black running Debian.

SPI

The BeagleBone Black has 2 SPI busses:

  • spi0 has 1 Chip Select
  • spi1 has 2 Chip Selects

spi1 and HDMI both uses P9.29 so HDMI (mcasp0_fsx) has to be disabled for spi1 (spi1_d0 MISO) to be used. This means that displays with a SPI LCD controller and a SPI touch controller can't have HDMI enabled if one SPI bus is used for both lcd and touch.
Custom displays that use both SPI busses can have HDMI enabled if spi0 is used for touch (has MISO) and spi1 is used for lcd (don't need MISO) (at least in theory, not tested).

Refs:

Disable HDMI

HDMI is enabled by default in the Device Tree using capemgr.
Default setup without capes:

$ cat /sys/devices/bone_capemgr.*/slots
 0: 54:PF---
 1: 55:PF---
 2: 56:PF---
 3: 57:PF---
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI

Status field explanation:

P - Probed
F - Probe failed
O - Override
l - Loading
L - Loaded

Disable HDMI by uncommenting a line in uEnv.txt.
/boot/uboot/uEnv.txt

##Disable HDMI
cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN

After reboot the HDMI virtual capes are now disabled (not Loaded):

$ cat /sys/devices/bone_capemgr.*/slots
 0: 54:PF---
 1: 55:PF---
 2: 56:PF---
 3: 57:PF---
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN

Ref:

Expand root filesystem

Check that there's space left on the root filesystem:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          1.6G  1.5G  1.5M 100% /

Expand it to use the whole SD card:

$ sudo /opt/scripts/tools/grow_partition.sh
$ sudo reboot

FBTFT drivers

Follow Out of tree build to build and install the drivers.
The drivers are in drivers/staging/fbtft since 4.0.

Prebuilt drivers for the bone-debian-7.5-2014-05-14-2gb image:

$ cat /proc/version
Linux version 3.8.13-bone50 (root@imx6q-wandboard-2gb-0) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Tue May 13 13:24:52 UTC 2014
$ wget tronnes.org/downloads/fbtft-2014-02-07-3.8.13-bone50.tar.gz
$ sudo tar -zxPvf fbtft-2014-02-07-3.8.13-bone50.tar.gz
$ sudo depmod

# test that the drivers are available
$ modinfo fbtft

Example setup

The rest of the setup is exemplified using: 3.5" TFT Display + Touch Screen for Raspberry Pi

Device Tree Overlay

The FBTFT drivers are not enough, Linux also needs to know which device(s) are present. This is done with using a Device Tree Overlay.

The entire file: NEOSEC-TINYLCD35-00A0.dts (raw)

LCD controller device:

lcd@0{
	compatible = "neosec,tinylcd";
	reg = <0>;

	pinctrl-names = "default";
	pinctrl-0 = <&lcd_ctrl_pinmux>;

	spi-max-frequency = <48000000>;
	rotate = <270>;
	bgr;
	fps = <50>;
	buswidth = <8>;
	reset-gpios = <&gpio2 16 0>;
	dc-gpios = <&gpio2 28 0>;

	debug = <3>;
};

Note the difference in gpio index: gpio1_16 => <&gpio2 16 0>
(debug can be removed when everything is working)

PWM backlight device

backlight {
	compatible = "pwm-backlight";
	pinctrl-names = "default";
	pinctrl-0 = <&pwm_bl_pins>;
	status = "okay";

	pwms = <&ehrpwm1 0 500000 0>;
	pwm-names = "backlight";
	brightness-levels = <0 4 8 16 32 64 128 255>;
	default-brightness-level = <7>; /* index to the array above */
};

Refs:

Compile overlay

$ dtc -O dtb -o NEOSEC-TINYLCD35-00A0.dtbo -b 0 -@ NEOSEC-TINYLCD35-00A0.dts
$ sudo cp NEOSEC-TINYLCD35-00A0.dtbo /lib/firmware/

Enable overlay

$ echo NEOSEC-TINYLCD35 | sudo tee /sys/devices/bone_capemgr.*/slots

$ dmesg
[ 1904.291607] bone-capemgr bone_capemgr.9: part_number 'NEOSEC-TINYLCD35', version 'N/A'
[ 1904.291787] bone-capemgr bone_capemgr.9: slot #7: generic override
[ 1904.291834] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 7
[ 1904.291886] bone-capemgr bone_capemgr.9: slot #7: 'Override Board Name,00A0,Override Manuf,NEOSEC-TINYLCD35'
[ 1904.292152] bone-capemgr bone_capemgr.9: slot #7: Requesting part number/version based 'NEOSEC-TINYLCD35-00A0.dtbo
[ 1904.292201] bone-capemgr bone_capemgr.9: slot #7: Requesting firmware 'NEOSEC-TINYLCD35-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
[ 1904.296402] bone-capemgr bone_capemgr.9: slot #7: dtbo 'NEOSEC-TINYLCD35-00A0.dtbo' loaded; converting to live tree
[ 1904.299115] bone-capemgr bone_capemgr.9: slot #7: #5 overlays
[ 1904.362280] edma-dma-engine edma-dma-engine.0: allocated channel for 0:43
[ 1904.362436] edma-dma-engine edma-dma-engine.0: allocated channel for 0:42
[ 1904.364450] fbtft_of_value: buswidth = 8
[ 1904.364490] fbtft_of_value: debug = 3
[ 1904.364515] fbtft_of_value: rotate = 270
[ 1904.364541] fbtft_of_value: fps = 50
[ 1904.366902] of_get_named_gpio_flags exited with status 48
[ 1904.366980] fb_tinylcd spi1.0: fbtft_request_one_gpio: 'reset-gpios' = GPIO48
[ 1904.367020] of_get_named_gpio_flags exited with status 60
[ 1904.367067] fb_tinylcd spi1.0: fbtft_request_one_gpio: 'dc-gpios' = GPIO60
[ 1904.367167] fb_tinylcd spi1.0: fbtft_verify_gpios()
[ 1904.367198] fb_tinylcd spi1.0: init_display()
[ 1904.367227] fb_tinylcd spi1.0: fbtft_reset()
[ 1904.496821] fb_tinylcd spi1.0: set_var()
[ 1904.664292] fb_tinylcd spi1.0: Display update: 1791 kB/s (167.330 ms), fps=0 (0.000 ms)
[ 1904.665121] Console: switching to colour frame buffer device 120x53
[ 1904.669625] graphics fb0: fb_tinylcd frame buffer, 480x320, 300 KiB video memory, 4 KiB DMA buffer memory, fps=51, spi1.0 at 48 MHz

[ 1904.693788] ehrpwm 48302200.ehrpwm: unable to select pin group
[ 1904.696956] bone-capemgr bone_capemgr.9: slot #7: Applied #5 overlays.

(press Ctrl-Alt-F1 to get VT1 and login)

An unfortunate sideeffect is that capemgr also adds a platform device using the same DT node as the spi device:

$ ls -l /sys/devices/ocp.3/481a0000.spi/
total 0
drwxr-xr-x 3 root root    0 Aug 21 19:18 0.lcd@0

This is not a problem for regular spi drivers, but the FBTFT drivers does also support platform devices. This results in the driver probing this device as well. But the probing fails because the gpio has already been requested by the spi device. So, not a functional problem, but rather a cosmetic one with logging of errors in the kernel log that are not actual errors.

$ dmesg
[ 1904.670286] fb_tinylcd 0.lcd@0: fbtft_probe_common()
[ 1904.670307] fbtft_of_value: buswidth = 8
[ 1904.670317] fbtft_of_value: debug = 3
[ 1904.670324] fbtft_of_value: rotate = 270
[ 1904.670332] fbtft_of_value: fps = 50
[ 1904.670677] of_get_named_gpio_flags exited with status 48
[ 1904.670690] gpio_request: gpio-48 (fb_tinylcd) status -16
[ 1904.670703] fb_tinylcd 0.lcd@0: gpio_request_one('reset-gpios'=48) failed with -16
[ 1904.690650] fb_tinylcd: probe of 0.lcd@0 failed with error -16

Controlling backlight

$ cat /sys/class/backlight/backlight.*/max_brightness
7
$ cat /sys/class/backlight/backlight.*/actual_brightness
7
$ echo 5 | sudo tee /sys/class/backlight/backlight.*/brightness
$ cat /sys/class/backlight/backlight.*/actual_brightness
5

If the console is controlling the framebuffer, it will turn off backlight after some time (blanking).

Enable overlay at boot

Add to /boot/uboot/uEnv.txt

##LCD
cape_enable=capemgr.enable_partno=NEOSEC-TINYLCD35

Reboot

$ dmesg | grep bone-capemgr
[...]
[    1.035902] bone-capemgr bone_capemgr.9: slot #7: generic override
[    1.035922] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 7
[    1.035946] bone-capemgr bone_capemgr.9: slot #7: 'Override Board Name,00A0,Override Manuf,NEOSEC-TINYLCD35'
[...]
[    1.040881] bone-capemgr bone_capemgr.9: loader: check slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)
[    1.040903] bone-capemgr bone_capemgr.9: loader: after slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)
[    1.040927] bone-capemgr bone_capemgr.9: slot #7: Requesting part number/version based 'NEOSEC-TINYLCD35-00A0.dtbo
[    1.040953] bone-capemgr bone_capemgr.9: slot #7: Requesting firmware 'NEOSEC-TINYLCD35-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
[    1.418129] bone-capemgr bone_capemgr.9: failed to load firmware 'NEOSEC-TINYLCD35-00A0.dtbo'
[    1.427110] bone-capemgr bone_capemgr.9: loader: failed to load slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)

capemgr couldn't find NEOSEC-TINYLCD35-00A0.dtbo even though it exists in /lib/firmware.

The reason for this is that an initramfs filesystem is loaded early, and it doesn't contain the file:

[    0.222914] Trying to unpack rootfs image as initramfs...

Add Device Tree Overlays to initrd

Create /etc/initramfs-tools/hooks/dtbo

#!/bin/sh

set -e

. /usr/share/initramfs-tools/hook-functions

# Copy Device Tree fragments
mkdir -p "${DESTDIR}/lib/firmware"
cp -p /lib/firmware/*.dtbo "${DESTDIR}/lib/firmware/"

Make executable

$ sudo chmod +x /etc/initramfs-tools/hooks/dtbo

Backup initrd:

$ sudo cp /boot/uboot/initrd.img /boot/uboot/initrd.img.bak

Create/update initramfs:

$ sudo /opt/scripts/tools/update_initrd.sh

Reboot

$ dmesg | grep bone-capemgr
[...]
[    1.063304] bone-capemgr bone_capemgr.9: slot #7: generic override
[    1.063324] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 7
[    1.063349] bone-capemgr bone_capemgr.9: slot #7: 'Override Board Name,00A0,Override Manuf,NEOSEC-TINYLCD35'
[...]
[    1.068261] bone-capemgr bone_capemgr.9: loader: before slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)
[    1.068281] bone-capemgr bone_capemgr.9: loader: check slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)
[    1.068304] bone-capemgr bone_capemgr.9: loader: after slot-7 NEOSEC-TINYLCD35:00A0 (prio 0)
[    1.068328] bone-capemgr bone_capemgr.9: slot #7: Requesting part number/version based 'NEOSEC-TINYLCD35-00A0.dtbo
[    1.068354] bone-capemgr bone_capemgr.9: slot #7: Requesting firmware 'NEOSEC-TINYLCD35-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
[    1.068689] bone-capemgr bone_capemgr.9: slot #7: dtbo 'NEOSEC-TINYLCD35-00A0.dtbo' loaded; converting to live tree
[    1.069176] bone-capemgr bone_capemgr.9: slot #7: #5 overlays
[    1.107092] bone-capemgr bone_capemgr.9: slot #7: Applied #5 overlays.

List files in initrd:

$ lsinitramfs /boot/uboot/initrd.img

It should be possible to add the FBTFT drivers to the initramfs as well, but that hung the machine for me. Tested by adding to /etc/initramfs-tools/modules

fb_tinylcd

(dependencies are pulled in automatically)

Refs:

Touch panel

This display has an ADS7846 compatible touch controller. The Linux version 3.8 driver doesn't have Device Tree support (added in 3.11).
We use ads7846_device to add the device needed:

$ sudo modprobe ads7846_device busnum=1 gpio_pendown=117 x_plate_ohms=100 pressure_max=255 swap_xy=1
$ dmesg | grep -i ads7846
[  248.918659] ads7846 spi1.1: touchscreen, irq 245
[  248.925916] input: ADS7846 Touchscreen as /devices/ocp.3/481a0000.spi/spi_master/spi1/spi1.1/input/input3

gpio_pendown=117 is the P9.25, gpio3_21 mentioned in the dts.
(before calibration, the touch panel is way off)

Touch permanent

Create /etc/modprobe.d/ads7846_device.conf

options ads7846_device busnum=1 gpio_pendown=117 x_plate_ohms=60 pressure_max=255 swap_xy=1

Add to /etc/modules

ads7846_device

After reboot there will be a calibration screen before the regular X windows desktop.

Display cape

Most capes have an EEPROM.

Connect a 24c256 on i2c1 with A2=1,A1=0,A0=0 => 1-0054 After reboot

[    0.880942] at24 1-0054: 32768 byte 24c256 EEPROM, writable, 1 bytes/write

[    0.912689] bone-capemgr bone_capemgr.9: bone: Invalid signature 'ffffffff' at slot 0

Build mkeeprom

$ mkdir mkeeprom && cd mkeeprom
$ wget http://azkeller.com/blog/wp-content/uploads/2012/08/mkeeprom.c
$ make mkeeprom
# install
$ mkdir -p ~/bin && cp ./mkeeprom ~/bin

Make eeprom content

$ mkeeprom
Enter Name of Board in ASCII (max 32): 3.5" TFT Display Cape
Enter HW Version of Board in ASCII (max 4): 00A0
Enter Name of Manufacturer in ASCII (max 16): NeoSec LLC
Enter Part Number in ASCII (max 16): NEOSEC-TINYLCD35
Enter Serial Number in ASCII (max 16):
Enter MAX Current (mA) on VDD_3V3EXP Used by Cape (Range 0 to 250mA): 0
Enter MAX Current (mA) on VDD_5V Used by Cape (Range 0 to 1000mA): 0
Enter MAX Current (mA) on SYS_5V Used by Cape (Range 0 to 250mA): 0
Enter Current (mA) Supplied on VDD_5V by Cape (Range 0 to 65535mA): 0

Enter Number of Pins Used by Cape (Range 0 to 74): 0

Write to eeprom

$ cat data.eeprom | sudo tee /sys/bus/i2c/devices/1-0054/eeprom > /dev/null
$ sudo hexdump -C /sys/bus/i2c/devices/1-0054/eeprom
00000000  aa 55 33 ee 41 30 33 2e  35 22 20 54 46 54 20 44  |.U3.A03.5" TFT D|
00000010  69 73 70 6c 61 79 20 43  61 70 65 00 00 00 00 00  |isplay Cape.....|
00000020  00 00 00 00 00 00 30 30  41 31 4e 65 6f 53 65 63  |......00A0NeoSec|
00000030  20 4c 4c 43 00 00 00 00  00 00 4e 45 4f 53 45 43  | LLC......NEOSEC|
00000040  2d 54 49 4e 59 4c 43 44  33 35 00 00 00 00 00 00  |-TINYLCD35......|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000f0  00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000100  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

Remove NEOSEC-TINYLCD35 from /boot/uboot/uEnv.txt
Reboot

$ dmesg | grep bone-capemgr | grep "#0"
[    0.938409] bone-capemgr bone_capemgr.9: slot #0: '3.5" TFT Display Cape,00A0,NeoSec LLC,NEOSEC-TINYLCD35'
[    1.054613] bone-capemgr bone_capemgr.9: slot #0: Requesting part number/version based 'NEOSEC-TINYLCD35-00A0.dtbo
[    1.054641] bone-capemgr bone_capemgr.9: slot #0: Requesting firmware 'NEOSEC-TINYLCD35-00A0.dtbo' for board-name '3.5" TFT Display Cape', version '00A0'
[    1.054993] bone-capemgr bone_capemgr.9: slot #0: dtbo 'NEOSEC-TINYLCD35-00A0.dtbo' loaded; converting to live tree
[    1.055486] bone-capemgr bone_capemgr.9: slot #0: #5 overlays
[    1.093853] bone-capemgr bone_capemgr.9: slot #0: Applied #5 overlays.
$ cat /sys/devices/bone_capemgr.*/slots
$ cat /sys/devices/bone_capemgr.*/slots
 0: 54:P---L 3.5" TFT Display Cape,00A0,NeoSec LLC,NEOSEC-TINYLCD35

I don't know if HDMI/HDMIN can be disabled using the EEPROM only.
Not disabling it in uEnv.txt results in HDMI not loading, but HDMIN loading, resulting in the display failing to work:

[    1.061157] bone-capemgr bone_capemgr.9: slot #5: Requesting firmware 'cape-boneblack-hdmi-00A0.dtbo' for board-name 'Bone-Black-HDMI', version '00A0'
[    1.061199] bone-capemgr bone_capemgr.9: slot #5: dtbo 'cape-boneblack-hdmi-00A0.dtbo' loaded; converting to live tree
[    1.061604] bone-capemgr bone_capemgr.9: slot #5: BB-BONELT-HDMI conflict P9.25 (#0:NEOSEC-TINYLCD35)
[    1.071369] bone-capemgr bone_capemgr.9: slot #5: Failed verification
[    1.078152] bone-capemgr bone_capemgr.9: loader: failed to load slot-5 BB-BONELT-HDMI:00A0 (prio 1)

[    1.087746] bone-capemgr bone_capemgr.9: slot #6: Requesting firmware 'cape-boneblack-hdmin-00A0.dtbo' for board-name 'Bone-Black-HDMIN', version '00A0'
[    1.087778] bone-capemgr bone_capemgr.9: slot #6: dtbo 'cape-boneblack-hdmin-00A0.dtbo' loaded; converting to live tree
[    1.088834] bone-capemgr bone_capemgr.9: slot #6: #2 overlays
[    1.093442] bone-capemgr bone_capemgr.9: slot #6: Applied #2 overlays.
[    1.093474] bone-capemgr bone_capemgr.9: loader: done slot-6 BB-BONELT-HDMIN:00A0 (prio 2)

Note: I used an Atmel 138 24C32A (4k) during this testing, since that's what I had. Worked fine.

Refs:

Power

Powering the BBB from a USB port (500mA) might cause strange behaviour with some displays. In that case, try a power adapter.

Other

Watterott MI0283QT-9A display on Beaglebone Black with Angstrom

⚠️ **GitHub.com Fallback** ⚠️