ILI9341 SPI TFT LCD Display Issue on Le Potato

Hello,

I’ve successfully set up my ILI9341 SPI TFT LCD with the spicc and spicc-ili9341 overlays on Le Potato. However, it’s displaying the main CLI on /dev/fb0. When I overwrite pixel data, a persistent cursor remains in the screen center. I’d prefer this not to be treated as the primary display.

Note: occassionally the initialization fails, making the display not associate with fb0 or fb1. It just becomes unresponsive in this case.

Here is the dmesg message when it does work (but only on fb0 which conflicts with the main display):

potato@raspberrypi:~ $ dmesg | grep -i ilitek
[ 8.193630] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply from device tree
[ 8.193657] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply property in node /soc/bus@c1100000/spi@8d80/display@0 failed
[ 8.193695] panel-ilitek-ili9341 spi0.0: get optional vcc failed
[ 8.614362] panel-ilitek-ili9341 spi0.0: [drm] Initialized display serial interface
[ 8.783437] panel-ilitek-ili9341 spi0.0: [drm] fb0: ili9341drmfb frame buffer device

And when it doesn’t work, leading to a black and unresponsive display (even when I try to write to fb1 nothing happens):

potato@raspberrypi:~ $ dmesg | grep -i ilitek
[ 8.330873] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply from device tree
[ 8.330899] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply property in node /soc/bus@c1100000/spi@8d80/display@0 failed
[ 8.330937] panel-ilitek-ili9341 spi0.0: get optional vcc failed
[ 8.334849] panel-ilitek-ili9341 spi0.0: [drm] fb1: ili9341drmfb frame buffer device

Any advice on how to resolve this?

Thanks in advance!

I want to add that changing the overlay to the following seemed to help make the fb_ili9341 driver take over and initialize the display correctly to point to /dev/fb1/, being responsive. I am not sure what the actual solution is, but I assume this may be useful:

/*
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */

/*
 * Overlay aimed to enable the Ilitek ILI9341 based panels such as the :
 * - Adafruit 2.2" SPI display
 * - Adafruit 2.8" Touch Shield V2 (SPI)
 * - Adafruit 2.4" TFT LCD with Touchscreen Breakout w/MicroSD Socket
 * - Adafruit 2.8" TFT LCD with Touchscreen Breakout Board w/MicroSD Socket
 * - Adafruit 2.2" 18-bit color TFT LCD display with microSD card breakout
 * - Adafruit TFT FeatherWing - 2.4" 320x240 Touchscreen For All Feathers
 * Pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CS), 29 (DC), 31 (Reset)
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>

{
        compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";
        fragment@0 {
                target-path = "/aliases";

                __overlay__ {
                        spi0 = "/soc/cbus@c1100000/spi@8d80";
                };
        };
        fragment@1 {
                target = <&spicc>;

                __overlay__ {
                        /*
                         * The display signals are connected to :
                         * - SDO(MISO) to Pin21 (SPI_MISO)
                         * - LED/Backlight to Pin2 (5v)
                         * - SCK to Pin23 (SPI_CLK)
                         * - SDI(MOSI) to Pin19 (SPI_MOSI)
                         * - D/C to Pin29 (GPIOX_17)
                         * - RESET to Pin31 (GPIOX_18)
                         * - (LCD) CS to Pin24 (GPIOX_10)
                         * - GND to Pin25 (GND)
                         * - VCC/VIN to Pin17 (3.3V)
                         */
                        display@0 {
                                compatible = "ilitek,ili9341";
                                reg = <0>;
                                height = <320>;
                                width = <240>;
                                rotate = <180>;
                                buswidth = <8>;
                                spi-max-frequency = <41666667>;
                                led-gpios = <&gpio GPIOX_0 GPIO_ACTIVE_HIGH>;
                                dc-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
                                reset-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_LOW>;
                                status = "okay";
                        };
                };
        };
};

Since most ILI9341 displays do not come with a static pinout that can fit on top of the 40 pin header, you need to assign or align the proper GPIOs.

I had aligned the GPIOs properly as the display works now, I just think it was an overlay/driver issue as it only began working after I modified the preexisting overlay from the libre wiring tools.

Okay so for Raspbian 12 at least, it looks like all support for this framebuffer is removed. I setup everything as I did for my old ISO image of Raspbian 11, but now its not working. I even used the old spicc.dts and a version of spicc-ili9341.dts which made it work before with no luck. How can I get this display working again with Raspbian 12. PLEASE.

spicc-ili9341.dts

/*
 * ILI9341 Display Overlay
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 *
 * Version: 1.1
 * Last Modified: [Your Last Modification Date]
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 *
 * Description:
 * This overlay enables support for the Ilitek ILI9341 based panels, including
 * various Adafruit displays with different sizes and features. It specifies
 * the pin connections for these displays and configures the necessary
 * interfaces.
 */

// Device Tree Source and Plugin Declaration
/dts-v1/;
/plugin/;

// Include necessary GPIO bindings for the device tree.
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>

/ {
    // Compatibility of Overlay with Various Devices
    compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

    // SPI Interface Configuration
    spi_interface_fragment: fragment@0 {
        target-path = "/aliases";
        __overlay__ {
            spi0 = "/soc/cbus@c1100000/spi@8d80";
        };
    };

    // Display Configuration and Connection Details
    display_config_fragment: fragment@1 {
        target = <&spicc>;
        __overlay__ {
            display@0 {
                compatible = "ilitek,ili9341";
                reg = <0>;
                height = <320>;
                width = <240>;
                rotate = <180>;
                buswidth = <8>;
                spi-max-frequency = <30000000>;

                // GPIO Pin Configurations
                led-gpios = <&gpio GPIOX_0 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
                reset-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_LOW>;

                // Activation Status
                status = "okay";
            };
        };
    };
};

spicc.dts

/*
 * Copyright (c) 2017 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */

/*
 * Overlay aimed to enable SPICC on Header 7J1 :
 * Pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (SS0)
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>

/ {
	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

	fragment@0 {
		target-path = "/aliases";

		__overlay__ {
			spi0 = "/soc/cbus@c1100000/spi@8d80";
		};
	};

	fragment@1 {
		target = <&spicc>;

		__overlay__ {
			status = "okay";
			pinctrl-0 = <&spi_pins>;
			pinctrl-1 = <&spi_pins>, <&spi_idle_high_pins>;
			pinctrl-2 = <&spi_pins>, <&spi_idle_low_pins>;
			pinctrl-names = "default", "idle-high", "idle-low";

			cs-gpios = <&gpio GPIOX_10 GPIO_ACTIVE_LOW>;
		};
	};
};

ILI9341 is supported by DRM which emulates /dev/fbX. Do not change the driver compatible in the overlays.

You need both spi-cc-cs1 and spi-cc-1cs-ili9341 overlays in that order. You should not need to modify the overlays except for rotation. You can use the ili9486 displays such as mpi3501 for how to handle rotation. The other stuff you’re adding is not valid. Make sure your hardware is connected correctly.

Raspbian 11 is using X11 for the DE where as Raspbian 12 is using wlroot/wayland.

1 Like

To preface: I’ve double checked that the wiring is correct and swapped the display with another (same exact model) in case it was a hardware issue.

After doing what you had said with the spi-cc-cs1 and spi-cc-1cs-ili9341 overlays in that order with the rotation, but still white screen. Below are the system messages I thought would relate to the issue.

potato@raspbian-bullseye-aml-s905x-cc:~ $ sudo /opt/libretech-wiring-tool/ldto merge spi-cc-cs1 spi-cc-1cs-ili9341
Overlay spi-cc-cs1: merged for next boot
Overlay spi-cc-1cs-ili9341: merged for next boot
potato@raspbian-bullseye-aml-s905x-cc:~ $ dmesg | grep drm
[    2.997686] meson-drm d0100000.vpu: Queued 2 outputs on vpu
[    3.158778] meson-drm d0100000.vpu: bound c883a000.hdmi-tx (ops meson_dw_hdmi_ops)
[    3.166572] [drm] Initialized meson 1.0.0 20161109 for d0100000.vpu on minor 0
[    3.209523] meson-drm d0100000.vpu: [drm] fb0: mesondrmfb frame buffer device
[    7.407822] systemd[1]: Starting Load Kernel Module drm...
[    9.629110] [drm] Initialized lima 1.1.0 20191231 for d00c0000.gpu on minor 1
[    9.753938] [drm] Initialized ili9341 1.0.0 20210716 for spi0.0 on minor 2
[    9.758371] panel-ilitek-ili9341 spi0.0: [drm] fb2: ili9341drmfb frame buffer device
potato@raspbian-bullseye-aml-s905x-cc:~ $ dmesg | grep ili9341
[    9.669830] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply from device tree
[    9.669854] panel-ilitek-ili9341 spi0.0: Looking up vcc-supply property in node /soc/bus@c1100000/spi@8d80/display@0 failed
[    9.669886] panel-ilitek-ili9341 spi0.0: get optional vcc failed
[    9.753938] [drm] Initialized ili9341 1.0.0 20210716 for spi0.0 on minor 2
[    9.758371] panel-ilitek-ili9341 spi0.0: [drm] fb2: ili9341drmfb frame buffer device

UPDATE: I got it to work as it did before, but only with the following device tree overlay files. I am not sure what exactly is the reason for it working, but it isn’t the wiring or the hardware, since I didn’t change any of that. It could be the old ISO Image that I used paired with the updated device tree overlay files. Note that I referred to this old commit to get the device tree overlay files I used with the corresponding ISO Image a months ago (around August).

ISO Image: 2022-09-22-raspbian-bullseye-arm64-lite+aml-s905x-cc.img

Device Tree Overlay Files:

spicc.dts (no changes from old commit):

/*
 * Copyright (c) 2017 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */

/*
 * Overlay aimed to enable SPICC on Header 7J1 :
 * Pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (SS0)
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>

/ {
	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

	fragment@0 {
		target-path = "/aliases";

		__overlay__ {
			spi0 = "/soc/cbus@c1100000/spi@8d80";
		};
	};

	fragment@1 {
		target = <&spicc>;

		__overlay__ {
			status = "okay";
			pinctrl-0 = <&spi_pins>;
			pinctrl-1 = <&spi_pins>, <&spi_idle_high_pins>;
			pinctrl-2 = <&spi_pins>, <&spi_idle_low_pins>;
			pinctrl-names = "default", "idle-high", "idle-low";

			cs-gpios = <&gpio GPIOX_10 GPIO_ACTIVE_LOW>;
		};
	};
};

spicc-ili9341.dts (modified from old commit):

/*
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */

/*
 * Overlay aimed to enable the Ilitek ILI9341 based panels such as the :
 * - Adafruit 2.2" SPI display
 * - Adafruit 2.8" Touch Shield V2 (SPI)
 * - Adafruit 2.4" TFT LCD with Touchscreen Breakout w/MicroSD Socket
 * - Adafruit 2.8" TFT LCD with Touchscreen Breakout Board w/MicroSD Socket
 * - Adafruit 2.2" 18-bit color TFT LCD display with microSD card breakout
 * - Adafruit TFT FeatherWing - 2.4" 320x240 Touchscreen For All Feathers
 * Pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CS), 29 (DC), 31 (Reset)
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>

/ {
	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";
	fragment@0 {
		target-path = "/aliases";

		__overlay__ {
			spi0 = "/soc/cbus@c1100000/spi@8d80";
		};
	};
	fragment@1 {
		target = <&spicc>;
		__overlay__ {
			/*
			 * The display signals are connected to:
			 * - SDO(MISO) to Pin21 (SPI_MISO)
			 * - LED/Backlight to Pin2 (5v)
			 * - SCK to Pin23 (SPI_CLK)
			 * - SDI(MOSI) to Pin19 (SPI_MOSI)
			 * - D/C to Pin29 (GPIOX_17)
			 * - RESET to Pin31 (GPIOX_18)
			 * - (LCD) CS to Pin24 (GPIOX_10)
			 * - GND to Pin25 (GND)
			 * - VCC/VIN to Pin17 (3.3V)
			 */
			display@0 {
				compatible = "adafruit,yx240qv29", "ilitek,ili9341";
				reg = <0>;
				height = <320>;
				width = <240>;
				rotate = <180>;
				buswidth = <8>;
				spi-max-frequency = <30000000>;

				dc-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
				reset-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_HIGH>;
				
				status = "okay";
			};
		};
	};
};

Steps to reproduce:

  1. git clone https://github.com/libre-computer-project/libretech-wiring-tool.git
  2. Copy the old/modified .dts files into the libretech-wiring-tool/libre-computer/aml-s905x-cc/dt/ directory.
  3. In the same directory, delete the corresponding .dtbo files to the old/modified .dts files, if they exist.
  4. Run sudo ./install.sh to generate the .dtbo files for the .dts files you added.
  5. Making sure to have the device tree cleared with sudo ldto reset and sudo reboot before doing sudo ldto merge spicc spicc-ili9341 and sudo reboot to merge the new device tree overlays that you added to the system.

Resulting Behavior

  1. The display points to /dev/fb1 which you can write pixel data to in the format you can find by doing fbset -fb /dev/fb1
  2. The display was unresponsive to data being sent to the framebuffer until I used con2fbmap 1 1 to set the console (pointing at /dev/fb0) to point to /dev/fb1 where the display is pointing to. This triggered the display to initialize in some way such that it become responsive from new data being sent to the framebuffer.

Goal: I want the display to always be responsive to data on boot.

Yet again another update:
it works with the neweset Raspbian 12 image, but the issue was purely initialization which I got to consistently trigger by doing con2fbmap, mapping console to the framebuffer, /dev/fb2, then back to /dev/fb0, then I clear the screen. However, occasionally it goes white screen and stops responding until I reboot the system. Here are the dmesg error messages just before the white screen happens:

[   92.640158] panel-ilitek-ili9341 spi0.0: SPI transfer failed: -110
[   92.640219] spi_master spi0: failed to transfer one message from queue
[   92.640238] panel-ilitek-ili9341 spi0.0: [drm] *ERROR* Failed to update display -110
[  100.059646] panel-ilitek-ili9341 spi0.0: SPI transfer failed: -110
[  100.059759] spi_master spi0: failed to transfer one message from queue

Please help me debug or understand what is causing this.

Is there a python library for drawing on a display connected via SPI for the Le Potato? Currently I am writing directly to the framebuffer to which the display is connected, but I presume this may be a core issue to my problems.

This is not a microcontroller. There is no library that generates SPI commands for ILI9341. It is abstracted behind the kernel driver. Depending the compatible you are using, it is either a legacy fb device or a DRM device with fb emulation.

As for the timeouts, it is related to frequency the bus is being driven at.

It seemed like increasing my spi-max-frequency from 16Mhz to 30Mhz fixed my issue (Yes, I do realize that I changed it from the default set in the libretech wiring tool :melting_face:) . Can’t believe it was as trivial as that. Thanks for the information about the driver. So basically, writing to the frame buffer is all I need to do with the driver handling the communication to the display?

Yes, you can do direct framebuffer drawing that will get synced by the kernel driver. That’s essentially what ILI9341 is. A giant display buffer that the LCD scans repeatedly. The driver just updates the buffer over SPI.

1 Like