Page 1 of 1

MIPI DBI/ST7789

Posted: 2026-05-27 1:12
by nobuddy2012

I know I'm asking for a lot of trouble here, but I'll ask anyway.

I see that, out-of-box, Luckfox Lyra has support for a few DSI displays -- a few more than Raspberry Pi has (wink). However, I'm trying to use something physically smaller than 2.8". I have a few ST7789s lying around, and I know for a fact they will work with the Linux "panel" driver over SPI.

What I am looking for in the way of information:

  1. Which DTS do I modify, if any, to set the chip up so it looks for the display on SPI0.0? SEE BELOW

  2. How do I properly remove the overlay that keeps removing my kernel driver config to include the panel driver, instead of modifying said overlay? SEE BELOW

  3. Where do I configure the display parameters, knowing that Luckfox doesn't have a "config.txt" in the same way that Raspberry Pi does?IGNORE THIS

Thanks

**UPDATE**

While poking around, I managed to get the driver to register, but I'm still having trouble getting the signals to actually output from the module. This is what I have done so far:

  • Modified rk3506-display.config (I'm not sure how to prevent this from overriding my kernel config):

    Code: Select all

    CONFIG_DRM_PANEL_MIPI_DBI=m
    
  • Added to rk3506-luckfox-lyra.dtsi:

    Code: Select all

    &spi0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&rm_io7_spi0_clk &rm_io6_spi0_mosi &rm_io5_spi0_miso &rm_io4_spi0_csn0>;
    
    	dbi_panel: panel@1 {
    		compatible = "panel", "panel-mipi-dbi-spi";
    		reg = <0>;
    		spi-max-frequency = <40000000>;
    		dc_gpios=<&gpio0 RK_PA3 0>;
    		reset_gpios=<&gpio0 RK_PA2 0>;
    		backlight=<&gpio1 RK_PD3 0>;
    		width-mm = <33>;
    		height-mm = <33>;
    		write-only;
    		panel-timing {
    			hactive = <240>;
    			vactive = <240>;
    			hback-porch = <0>;
    			vback-porch = <0>;
    
    			clock-frequency = <0>;
    			hfront-porch = <0>;
    			hsync-len = <0>;
    			vfront-porch = <0>;
    			vsync-len = <0>;
    		};
    	};
    
    };
    
  • added the appropriate firmware for my ST7789 display, per https://github.com/notro/panel-mipi-dbi/wiki

Any pointers on how to get the SPI and GPIO up and running would be appreciated. The driver isn't throwing any errors in `dmesg` so I'm imagining I must have the pin configuration wrong somehow.


Re: MIPI DBI/ST7789

Posted: 2026-05-28 2:32
by Crocodile
  1. Modify the DTS file corresponding to your board form factor, enable spi0, and configure the relevant pins and driver. If you need to use the SPI display as a framebuffer, you may refer to this device tree configuration (using the FBTFT driver). As for the tinydrm driver you mentioned, I have not used it before, and I am unsure whether it will conflict with Rockchip's driver (which requires the display to be bound to a VOP).

    Code: Select all

    /**********spi0**********/
    &spi0 {
    	status = "okay";
    	pinctrl-0 = <&rm_io1_spi0_clk &rm_io4_spi0_mosi &rm_io3_spi0_csn0>;
    	#address-cells = <1>;
    	#size-cells = <0>;
    
    	fbtft@0{
    		status = "okay";
    		compatible = "sitronix,st7789v";
    		reg = <0>;
    		spi-max-frequency = <50000000>;
    		fps = <60>;
    		buswidth = <8>;
    		debug = <0x7>;
    		dc-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;      //DC
    		reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;    //RES
    	};
    };
  2. After running ./build.sh config, select Kernel and set the defconfig fragments to empty. This will prevent the kernel configuration from being overwritten.
  3. config.txt is a mechanism specific to the Raspberry Pi. On the Luckfox Lyra, the initialization sequence and resolution must be properly configured directly in the driver source code.

Re: MIPI DBI/ST7789

Posted: 2026-05-29 20:14
by nobuddy2012

Thank you for that. I did realize the config.txt is specific to RPi after a short while. I'm aiming for the TinyDRM driver since many sources say the FBTFT driver is deprecated. If all else fails I'll go with FBTFT but I'm hoping with some of my own research we all can find a solution.

I'm able to get the system to recognize the panel-mipi-dbi-spi driver without conflicts. The problem now is that the display doesn't render anything when I run `modetest -M panel-mipi-dbi -s 31:240x240@XR24`. I do see it flicker a bit, as if it's initializing, but I don't see the test pattern. Per the author, I also created the required "firmware" file (https://github.com/notro/panel-mipi-dbi/wiki); the driver will not initialize without it.

I disconnected the display and put SCK/MOSI on a scope. I ran the modetest command again, and I see about three or four "bursts" followed by the actual display render data. None of them contain the hex commands in the firmware file. I'm still troubleshooting whether this is a driver problem, a hardware problem, or a "me" problem.

See attached images for details on what the scope picked up. Expected init sequence is as follows:

Code: Select all

# Adafruit ST7789 MiniPiTFT LCD and TFT Bonnet
# width=240,height=240

command 0x01  # _SWRESET and Delay 150ms
delay 150

command 0x11  # _SLPOUT and Delay 10ms
delay 10

command 0x3A 0x55  # _COLMOD and Delay 10ms
delay 10

command 0x36 0x08  # _MADCTL Botton->Top Refresh
command 0x21  # _INVON Hack and Delay 10ms
delay 10

command 0x13  # _NORON and Delay 10ms
delay 10

# Command 36h sets the read order from frame memory to the display panel
# Remember to swap width/height on 0/180 rotations
#command 0x36 0x00 # rotation 0
command 0x36 0xA0 # rotation 90
#command 0x36 0xC0 # rotation 180
#command 0x36 0x60 # rotation 270

command 0x29  # _DISPON and Delay 500ms
delay 250
delay 250

The relevant DTS fragment that I know works, at least with respect to the driver loading and seeing the SPI bus is as follows:

Code: Select all

/**********SPI**********/
&spi1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&spi1_clk_pins &spi1_csn1_pins>;
	#address-cells = <1>;
	#size-cells = <0>;

	panel@1 {
		status = "okay";
		compatible = "panel", "panel-mipi-dbi-spi";
		reg = <1>;
		spi-max-frequency = <20000000>;
		dc_gpios=<&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
		reset_gpios=<&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
		backlight-gpios=<&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>;
		width-mm=<33>;
		height-mm=<33>;
                debug = <3>;
		write-only;
		spi-cpha;
		panel-timing {
			hactive = <240>;
			vactive = <240>;
			hback-porch = <0>;
			vback-porch = <0>;

			clock-frequency = <0>;
			hfront-porch = <0>;
			hsync-len = <0>;
			vfront-porch = <0>;
			vsync-len = <0>;
		};
	};
	spidev@1 {
		compatible = "rockchip,spidev";
		reg = <1>;
		status = "disabled";
		spi-max-frequency = <10000000>;
	};
};

I'm still not quite sure how to remap SPI0 to alternate RMII pins, since `<&rm_io1_spi0_clk &rm_io4_spi0_mosi &rm_io3_spi0_csn0>` did not work, but I can live with SPI1.1 instead of SPI0.0 for now.

Thanks again for any assistance!

**UPDATE** I compared against my RasPi Zero that does work, and even that isn't sending the correct init sequence. It also requires the clock polarity to be inverted, which, according to the display datasheet, is incorrect. The init sequence taken from Notro's GitHub doesn't work, but another one I found on Reddit does work. So at this point I'm lost.


Re: MIPI DBI/ST7789

Posted: 2026-05-30 23:27
by nobuddy2012

One more thing to add -- I have confirmed that my scope is not (entirely) reading dud values. I rebuilt the kernel with the trace option and found that the modetest, by way of the SPI controller, is in fact sending the wrong data.

Code: Select all

        modetest-1679    [002] .....   147.744264: spi_transfer_start: spi1.1 75c4c684 len=9 tx=[00-00-00-00-00-00-00-00-2a] rx=[]
        modetest-1679    [002] .....   147.744407: spi_transfer_start: spi1.1 75c4c684 len=9 tx=[80-40-20-1e-f0-00-00-00-00] rx=[]
        modetest-1679    [002] .....   147.744586: spi_transfer_start: spi1.1 75c4c684 len=9 tx=[00-00-00-00-00-00-00-00-2b] rx=[]
        modetest-1679    [002] .....   147.744695: spi_transfer_start: spi1.1 75c4c684 len=9 tx=[80-40-20-1e-f0-00-00-00-00] rx=[]
        modetest-1679    [002] .....   147.744797: spi_transfer_start: spi1.1 0853b70c len=9 tx=[00-00-00-00-00-00-00-00-2c] rx=[]

I know this isn't terribly helpful to resolving my issue but I'm putting this here for any future viewers. I've reached out to the TinyDRM author in hopes he might have some thoughts.

If all else fails, I have confirmed FBTFT works. So thank you very much @Crocodile!


Re: MIPI DBI/ST7789

Posted: 2026-06-05 0:02
by nobuddy2012

Good news! I finally got it working! I can get `modeset` to display a test pattern. In the absence of other guides, I thought I would post here what I did to accomplish this.

  1. Modify the device tree! I added the following to the end of my `rk3506-luckfox-lyra-sd.dts`:

    Code: Select all

    /**********DISPLAY**********/
    &pinctrl {
    	// Reset Pin -- Pull Up
    	rm_io2 {
    		rm_io2_pins {
    			rockchip,pins = <0 RK_PA2 7 &pcfg_pull_up>;
    		};
    	};
    	// DC Pin -- Pull None
    	rm_io3 {
    		rm_io3_pins {
    			rockchip,pins = <0 RK_PA3 7 &pcfg_pull_none>;
    		};
    	};
    
    };
    
    &spi1 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&spi1_clk_pins &spi1_csn1_pins &rm_io2_pins &rm_io3_pins>;
    	#address-cells = <1>;
    	#size-cells = <0>;
    
    	panel@1 {
    		status = "okay";
    		compatible = "panel", "panel-mipi-dbi-spi";
    		reg = <1>;
    		spi-max-frequency = <80000000>;
    		dc-gpios=<&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
    		reset-gpios=<&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
    		backlight=<&backlight_mipi_dbi>;
    		width-mm=<33>;
    		height-mm=<33>;
    		write-only;
    		spi-cpha;
    		spi-cpol;
    		panel-timing {
    			hactive = <240>;
    			vactive = <240>;
    			hback-porch = <0>;
    			vback-porch = <0>;
    
    			clock-frequency = <0>;
    			hfront-porch = <0>;
    			hsync-len = <0>;
    			vfront-porch = <0>;
    			vsync-len = <0>;
    		};
    	};
    
    	spidev@1 {
    		compatible = "rockchip,spidev";
    		reg = <1>;
    		status = "disabled";
    		spi-max-frequency = <10000000>;
    	};
    };
    

    I have defined backlight_mipi_dbi above in the first block as such. This is optional. Just remember to remove or change the backlight parameter from your `panel@1` block if you do:

    Code: Select all

    backlight_mipi_dbi: backlight@1 {
    		status = "okay";
    		pinctrl-names = "default";
    		#address-cells = <1>;
    		#size-cells = <0>;
    		reg=<0>;
    		compatible = "gpio-backlight";
    		gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>;
    };
    
  2. Wire up the LCD module! I tested this with Adafruit 1.54" 240x240 Wide Angle TFT LCD Display . Per the above Device Tree, the pins should be as follows:
    RM_IO2 - RST (Reset)
    RM_IO3 - DC (Data/Command Select)
    RM_IO7 - TFTCS (Chip Select)
    RM_IO8 - SCK (SPI Clock)
    RM_IO9 - MOSI (SPI Master Out)
    RM_IO31 - BL (Backlight)
    If you have altered the pin muxes, you know what you're doing, so you're on your own here.

  3. Generate the display firmware! To do this, you will need a Python tool created by the mipi-panel-dbi driver author. This tool can be found at https://github.com/notro/panel-mipi-dbi/. DO NOT USE HIS EXAMPLE IN THE WIKI! There is a bug in the driver that prevents the firmware init codes from being sent when the kernel modeset occurs. Use this instead:

    Code: Select all

    command 0x11                            # 0x1000011
    delay 255                               # 0x20000ff
    
    command 0x36 0x78                       # MADCTL MX | MV | ML | RGB
    
    command 0x3a 0x05                       # 0x100003a 0x05
    command 0x21                            # 0x1000021
    command 0x2a 0x00 0x01 0x00 0x3f        # 0x100002a 0x00 0x01 0x00 0x3f
    command 0x2b 0x00 0x00 0x00 0xef        # 0x100002b 0x00 0x00 0x00 0xef
    command 0xb2 0x0c 0x0c 0x00 0x33 0x33   # 0x10000b2 0x0c 0x0c 0x00 0x33 0x33
    command 0xb7 0x35                       # 0x10000b7 0x35
    command 0xbb 0x1a                       # 0x10000bb 0x1a # Set VCOM to 0.75V
    command 0xc0 0x0c                       # 0x10000c0 0x0c
    command 0xc2 0x01                       # 0x10000c2 0x01
    command 0xc3 0x0b                       # 0x10000c3 0x0b # VRHS 4.1V + ...
    command 0xc4 0x20                       # 0x10000c4 0x20
    command 0xc6 0x0f                       # 0x10000c6 0x0f
    command 0xd0 0xa4 0xa1                  # 0x10000d0 0xa4 0xa1
    command 0xE0 0x00 0x19 0x1E 0x0A 0x09 0x15 0x3D 0x44 0x51 0x12 0x03 0x00 0x3F 0x3F # Set Positive Voltage Gamma Control
    command 0xE1 0x00 0x18 0x1E 0x0A 0x09 0x25 0x3F 0x43 0x52 0x33 0x03 0x00 0x3F 0x3F # Set Negative Voltage Gamma Control
    command 0x29                            # 0x1000029
    

    There is more to this, and it can be found at https://github.com/tquiggle/Diecast-Rem ... 1.3-HAT.sh. I am posting this here in case that link ever goes stale. Save the output file as panel.bin. It might also be a good idea to add this to your buildroot config so it automatically goes into /lib/firmware/panel.bin.

  4. Flash and fire it up! If you have not added the firmware.bin file to your buildroot config, you will need to add this to /lib/firmware as soon as you boot. Once everything is set, run `modetest -M panel-mipi-dbi -s 31:240x240@XR24` in a terminal and be amazed!


Re: MIPI DBI/ST7789

Posted: 2026-06-08 2:46
by Crocodile

Congratulations on successfully using TinyDrm, and thank you for sharing.