Rockchip · AI & Linux Hub

Display & audio

Rockchip RGB/MCU Developer Guide: Pin Mapping, Panels, SPI and Timing

Complete RGB/MCU protocols, platform support, pin maps, device trees, initialization sequences, frame-rate formulas and frame write/read.

· ArmSoM Editorial · Rockchip source documentation · 34 min read

This is a Rockchip RGB/MCU platform reference. The V1.7.1 support table lists RK1808, RK312X/PX3SE, RK3288, RK3308B/BS, RK3326/PX30, RK3506, RK3562, RK3568, RK3576, RV1103/1106, RV1109/RV1126 and RV1126B, with different capabilities. It does not establish support on every ArmSoM board. SPI/panel configurations distinguish kernel 4.19 and earlier from 5.10 and later. Verify the board SDK/BSP, exposed interface, pin multiplexing, voltage and panel timing. No ArmSoM hardware validation was performed; source values and illustrations are platform examples.

Source: Rockchip_Developer_Guide_RGB_MCU_CN.pdf, V1.7.1, 34 pages. Only Chinese was supplied. English/Russian translate the full technical body; all three versions use the Chinese PDF figures, without claiming translated image labels.

Editorial notes · ArmSoM documentation · Rockchip

1. Basic concepts

1.1 RGB interface

RGB is also called DPI (Display Pixel Interface). It uses four synchronization signals: Vsync, Hsync, Den (Enable) and DCLK (Dotclk). The synchronization method distinguishes DE mode from SYNC mode. Rockchip RGB output timing can support both.

DE-mode timing

DE-mode timing

1.1.1 DE mode

The validity of DB[23:0] depends only on Den. The source states that data is valid at the low level and invalid otherwise.

1.1.2 SYNC mode

SYNC-mode timing

SYNC-mode timing

DB[23:0] data is synchronized by Vsync and Hsync and scanned according to the timing above.

1.2 MCU interface

MCU is also called DBI or the 8080 interface. It supports bidirectional communication between TX and RX, with four synchronization signals: RS (CSX), CSN (D/CX), WEN (WRX) and REN (RDX). This introductory source paragraph states that Rockchip supports only MCU TX; the later platform table separately lists read support for RK3506 and RV1126B. The inconsistency is retained for review.

1.2.1 Write timing

MCU write timing

MCU write timing

CSX, D/CX and WRX are driven low in sequence. While DB[23:0] is valid, WRX first goes low and then high.

1.2.2 Read timing

MCU read timing and initial dummy data

MCU read timing and initial dummy data

CSX, D/CX and RDX are driven low in sequence. While DB[23:0] is valid, RDX first goes low and then high.

Before reading, perform a write operation to send the register address to the panel.

The first read returns invalid data; valid data starts with the second read.

MCU read is commonly used for panel debugging, identifying panel IDs for multi-panel compatibility, and the frame-read feature described later.

1.2.3 Bypass and normal modes

Bypass mode is used when MCU and panel exchange commands through write/read operations.

Sending init/deinit commands from panel-init-sequence/panel-exit-sequence and performing frame write/read are bypass-mode operations. See the corresponding Software Configuration sections below.

In normal mode, the host sends image data through MCU into panel RAM for normal display. This mode normally starts after panel-init-sequence has been transmitted and successful panel initialization confirmed.

Bypass mode may include write and read operations; normal mode includes write operations only.

2. Rockchip platform support

SoC platform RGB support MCU support MCU read support VOP version Video Port path (VOP 2.0) Supported output modes
RK1808 Y Y N VOP 1.0   RGB666/RGB565
RK312X/PX3SE Y N N VOP 1.0   RGB888/RGB666/RGB565
RK3288 Y Y N VOP 1.0   RGB888/RGB666/RGB565/RGB3x8
RK3308B/RK3308BS Y Y N VOP 1.0   RGB888/RGB666/RGB565/RGB3x8
RK3326/PX30 Y Y N VOP 1.0   RGB888/RGB666/RGB565
RK3506 Y Y Y VOP 1.0   RGB888/RGB666/RGB565/RGB3x8/RGB3x6/RGB2x8
RK3562 Y Y N VOP 2.0 VP0 RGB888/RGB666/RGB565/RGB3x8
RK3568 Y N N VOP 2.0 VP2 RGB888/RGB666/RGB565
RK3576 Y Y N VOP 2.0 VP1/VP2 RGB888/RGB666/RGB565/RGB3x8/RGB3x6/RGB2x8
RV1103 Y Y N VOP 1.0   RGB3x8
RV1106 Y Y N VOP 1.0   RGB666/RGB565/RGB3x8
RV1109/RV1126 Y Y N VOP 1.0   RGB888/RGB666/RGB565/RGB3x8
RV1126B Y Y Y VOP 1.0   RGB888/RGB666/RGB565/RGB3x8/RGB3x6/RGB2x8

For VOP and VP (Video Port), refer to Rockchip_Developer_Guide_DRM_Display_Driver_CN.

3. Hardware connections

3.1 RK3562/RK3576/RK3506/RV1126B

Component name Pin name RGB888 (MCU) RGB666 (MCU) RGB565 (MCU) RGB3x8 (MCU) RGB3x6 (MCU) RGB2x8 (MCU)
DCLK VO_LCDC_CLK DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS)
VSYNC VO_LCDC_VSYNC VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN)
HSYNC VO_LCDC_HSYNC HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN)
DEN VO_LCDC_DEN DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN)
R7_D23 VO_LCDC_D23 √ √ √ √ (D7_m1) √ (D5_m1) √ (D7_m1)
R6_D22 VO_LCDC_D22 √ √ √ √ (D6_m1) √ (D4_m1) √ (D6_m1)
R5_D21 VO_LCDC_D21 √ √ √ √ (D5_m1) √ (D3_m1) √ (D5_m1)
R4_D20 VO_LCDC_D20 √ √ √ √ (D4_m1) √ (D2_m1) √ (D4_m1)
R3_D19 VO_LCDC_D19 √ √ √ √ (D3_m1) √ (D1_m1) √ (D3_m1)
R2_D18 VO_LCDC_D18 √ √ × × × ×
R1_D17 VO_LCDC_D17 √ × × × × ×
R0_D16 VO_LCDC_D16 √ × × × × ×
G7_D15 VO_LCDC_D15 √ √ √ √ (D2_m1) √ (D0_m1) √ (D2_m1)
G6_D14 VO_LCDC_D14 √ √ √ √ (D1_m1) × √ (D1_m1)
G5_D13 VO_LCDC_D13 √ √ √ √ (D0_m1) × √ (D0_m1)
G4_D12 VO_LCDC_D12 √ √ √ √ (D7_m0) √ (D5_m0) √ (D7_m0)
G3_D11 VO_LCDC_D11 √ √ √ √ (D6_m0) √ (D4_m0) √ (D6_m0)
G2_D10 VO_LCDC_D10 √ √ √ √ (D5_m0) √ (D3_m0) √ (D5_m0)
G1_D9 VO_LCDC_D9 √ × × × × ×
G0_D8 VO_LCDC_D8 √ × × × × ×
B7_D7 VO_LCDC_D7 √ √ √ √ (D4_m0) √ (D2_m0) √ (D4_m0)
B6_D6 VO_LCDC_D6 √ √ √ √ (D3_m0) √ (D1_m0) √ (D3_m0)
B5_D5 VO_LCDC_D5 √ √ √ √ (D2_m0) √ (D0_m0) √ (D2_m0)
B4_D4 VO_LCDC_D4 √ √ √ √ (D1_m0) × √ (D1_m0)
B3_D3 VO_LCDC_D3 √ √ √ √ (D0_m0) × √ (D0_m0)
B2_D2 VO_LCDC_D2 √ √ × × × ×
B1_D1 VO_LCDC_D1 √ × × × × ×
B0_D0 VO_LCDC_D0 √ × × × × ×

3.2 RK3568

Component name Pin name RGB888 RGB666 RGB565
DCLK LCDC_CLK DCLK DCLK DCLK
VSYNC LCDC_VSYNC VSYNC VSYNC VSYNC
HSYNC LCDC_HSYNC HSYNC HSYNC HSYNC
DEN LCDC_DEN DEN DEN DEN
R7_D23 LCDC_D23 √ √ √
R6_D22 LCDC_D22 √ √ √
R5_D21 LCDC_D21 √ √ √
R4_D20 LCDC_D20 √ √ √
R3_D19 LCDC_D19 √ √ √
R2_D18 LCDC_D18 √ √ ×
R1_D17 LCDC_D17 √ × ×
R0_D16 LCDC_D16 √ × ×
G7_D15 LCDC_D15 √ √ √
G6_D14 LCDC_D14 √ √ √
G5_D13 LCDC_D13 √ √ √
G4_D12 LCDC_D12 √ √ √
G3_D11 LCDC_D11 √ √ √
G2_D10 LCDC_D10 √ √ √
G1_D9 LCDC_D9 √ × ×
G0_D8 LCDC_D8 √ × ×
B7_D7 LCDC_D7 √ √ √
B6_D6 LCDC_D6 √ √ √
B5_D5 LCDC_D5 √ √ √
B4_D4 LCDC_D4 √ √ √
B3_D3 LCDC_D3 √ √ √
B2_D2 LCDC_D2 √ √ ×
B1_D1 LCDC_D1 √ × ×
B0_D0 LCDC_D0 √ × ×

3.3 RK312X/PX3SE/RK3288/RK3308B/RK3308BS/RK3328/RK3326/PX30/RV1109/RV1126

Component name Pin name RGB888 (MCU) RGB666 (MCU) RGB666_CPADHI (MCU) RGB565 (MCU) RGB565_CPADHI (MCU) RGB3x8 (MCU)
DCLK LCDC_CLK/LCD_CLK DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS)
VSYNC LCDC_VSYNC/LCD_VSYNC VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN)
HSYNC LCDC_HSYNC/LCD_HSYNC HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN)
DEN LCDC_DEN/LCD_DEN DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN)
R7_D23 LCDC_D23/LCD_D23 √ × √ × √ ×
R6_D22 LCDC_D22/LCD_D22 √ × √ × √ ×
R5_D21 LCDC_D21/LCD_D21 √ × √ × √ ×
R4_D20 LCDC_D20/LCD_D20 √ × √ × √ ×
R3_D19 LCDC_D19/LCD_D19 √ × √ × √ ×
R2_D18 LCDC_D18/LCD_D18 √ × √ × × ×
R1_D17 LCDC_D17/LCD_D17 √ √ × × × ×
R0_D16 LCDC_D16/LCD_D16 √ √ × × × ×
G7_D15 LCDC_D15/LCD_D15 √ √ √ √ √ ×
G6_D14 LCDC_D14/LCD_D14 √ √ √ √ √ ×
G5_D13 LCDC_D13/LCD_D13 √ √ √ √ √ ×
G4_D12 LCDC_D12/LCD_D12 √ √ √ √ √ ×
G3_D11 LCDC_D11/LCD_D11 √ √ √ √ √ ×
G2_D10 LCDC_D10/LCD_D10 √ √ √ √ √ ×
G1_D9 LCDC_D9/LCD_D9 √ √ × √ × ×
G0_D8 LCDC_D8/LCD_D8 √ √ × √ × ×
B7_D7 LCDC_D7/LCD_D7 √ √ √ √ √ √
B6_D6 LCDC_D6/LCD_D6 √ √ √ √ √ √
B5_D5 LCDC_D5/LCD_D5 √ √ √ √ √ √
B4_D4 LCDC_D4/LCD_D4 √ √ √ √ √ √
B3_D3 LCDC_D3/LCD_D3 √ √ √ √ √ √
B2_D2 LCDC_D2/LCD_D2 √ √ √ √ × √
B1_D1 LCDC_D1/LCD_D1 √ √ × √ × √
B0_D0 LCDC_D0/LCD_D0 √ √ × √ × √

3.4 RK1808/RV1106

Component name Pin name RGB666 (MCU) RGB565 (MCU) RGB565 (MCU) RGB3x8 (MCU)
DCLK LCDC_CLK/LCD_CLK DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS)
VSYNC LCDC_VSYNC/LCD_VSYNC VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN)
HSYNC LCDC_HSYNC/LCD_HSYNC HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN)
DEN LCDC_DEN/LCD_DEN DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN)
R5_D17 LCDC_D17/LCD_D17 √ × × ×
R4_D16 LCDC_D16/LCD_D16 √ × × ×
R3_D15 LCDC_D15/LCD_D15 √ √ √ ×
R2_D14 LCDC_D14/LCD_D14 √ √ √ ×
R1_D13 LCDC_D13/LCD_D13 √ √ √ ×
R0_D12 LCDC_D12/LCD_D12 √ √ √ ×
G5_D11 LCDC_D11/LCD_D11 √ √ √ ×
G4_D10 LCDC_D10/LCD_D10 √ √ √ ×
G3_D9 LCDC_D9/LCD_D9 √ √ √ ×
G2_D8 LCDC_D8/LCD_D8 √ √ √ ×
G1_D7 LCDC_D7/LCD_D7 √ √ √ √
G0_D6 LCDC_D6/LCD_D6 √ √ √ √
B5_D5 LCDC_D5/LCD_D5 √ √ √ √
B4_D4 LCDC_D4/LCD_D4 √ √ √ √
B3_D3 LCDC_D3/LCD_D3 √ √ √ √
B2_D2 LCDC_D2/LCD_D2 √ √ √ √
B1_D1 LCDC_D1/LCD_D1 √ √ √ √
B0_D0 LCDC_D0/LCD_D0 √ √ √ √

3.5 RV1103

Component name Pin name RGB3x8 (MCU)
DCLK LCDC_CLK DCLK(RS)
VSYNC LCDC_VSYNC VSYNC(CSN)
HSYNC LCDC_HSYNC HSYNC(WRN)
DEN LCDC_DEN DEN(RDN)
D7 LCDC_D7 √
D6 LCDC_D6 √
D5 LCDC_D5 √
D4 LCDC_D4 √
D3 LCDC_D3 √
D2 LCDC_D2 √
D1 LCDC_D1 √
D0 LCDC_D0 √

3.6 RV1126B-P

RV1126B-P introduces a data map to maintain the hardware connection scheme of the earlier RV1126. Different data maps route data to different hardware pins.

The complete data-map definitions are in include/dt-bindings/display/rockchip_vop.h:

/* mcu_data[23:0] */
#define ROCKCHIP_MCU_DATA_MAP_DATA_1x24 0
/*

 * { mcu_data[7:3], 3'b0, mcu_data[2:0], mcu_data[7:5], 2'b0, mcu_data[4:0], 3'b0 }
 * That is:
 *   LCDC_D23 -> MCU_D7_M1
 *   LCDC_D22 -> MCU_D6_M1
 *   LCDC_D21 -> MCU_D5_M1
 *   LCDC_D20 -> MCU_D4_M1
 *   LCDC_D19 -> MCU_D3_M1
 *   LCDC_D18 -> N/A
 *   LCDC_D17 -> N/A
 *   LCDC_D16 -> N/A
 *   LCDC_D15 -> MCU_D2_M1
 *   LCDC_D14 -> MCU_D1_M1

 *   LCDC_D13 -> MCU_D0_M1
 *   LCDC_D12 -> MCU_D7_M0
 *   LCDC_D11 -> MCU_D6_M0
 *   LCDC_D10 -> MCU_D5_M0
 *   LCDC_D9 -> N/A

 *   LCDC_D8 -> N/A
 *   LCDC_D7 -> MCU_D4_M0
 *   LCDC_D6 -> MCU_D3_M0
 *   LCDC_D5 -> MCU_D2_M0
 *   LCDC_D4 -> MCU_D1_M0
 *   LCDC_D3 -> MCU_D0_M0
 *   LCDC_D2 -> N/A
 *   LCDC_D1 -> N/A
 *   LCDC_D0 -> N/A
 */
#define ROCKCHIP_MCU_DATA_MAP_DATA_WITH_DUMMY_0 1

For standard RV1126B, the default MCU connections below correspond to ROCKCHIP_MCU_DATA_MAP_DATA_WITH_DUMMY_0.

Component name Pin name RGB888 (MCU) RGB666 (MCU) RGB565 (MCU) RGB3x8 (MCU) RGB3x6 (MCU) RGB2x8 (MCU)
DCLK VO_LCDC_CLK DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS)
VSYNC VO_LCDC_VSYNC VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN)
HSYNC VO_LCDC_HSYNC HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN)
DEN VO_LCDC_DEN DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN)
R7_D23 VO_LCDC_D23 √ √ √ √ (D7_m1) √ (D5_m1) √ (D7_m1)
R6_D22 VO_LCDC_D22 √ √ √ √ (D6_m1) √ (D4_m1) √ (D6_m1)
R5_D21 VO_LCDC_D21 √ √ √ √ (D5_m1) √ (D3_m1) √ (D5_m1)
R4_D20 VO_LCDC_D20 √ √ √ √ (D4_m1) √ (D2_m1) √ (D4_m1)
R3_D19 VO_LCDC_D19 √ √ √ √ (D3_m1) √ (D1_m1) √ (D3_m1)
R2_D18 VO_LCDC_D18 √ √ × × × ×
R1_D17 VO_LCDC_D17 √ × × × × ×
R0_D16 VO_LCDC_D16 √ × × × × ×
G7_D15 VO_LCDC_D15 √ √ √ √ (D2_m1) √ (D0_m1) √ (D2_m1)
G6_D14 VO_LCDC_D14 √ √ √ √ (D1_m1) × √ (D1_m1)
G5_D13 VO_LCDC_D13 √ √ √ √ (D0_m1) × √ (D0_m1)
G4_D12 VO_LCDC_D12 √ √ √ √ (D7_m0) √ (D5_m0) √ (D7_m0)
G3_D11 VO_LCDC_D11 √ √ √ √ (D6_m0) √ (D4_m0) √ (D6_m0)
G2_D10 VO_LCDC_D10 √ √ √ √ (D5_m0) √ (D3_m0) √ (D5_m0)
G1_D9 VO_LCDC_D9 √ × × × × ×
G0_D8 VO_LCDC_D8 √ × × × × ×
B7_D7 VO_LCDC_D7 √ √ √ √ (D4_m0) √ (D2_m0) √ (D4_m0)
B6_D6 VO_LCDC_D6 √ √ √ √ (D3_m0) √ (D1_m0) √ (D3_m0)
B5_D5 VO_LCDC_D5 √ √ √ √ (D2_m0) √ (D0_m0) √ (D2_m0)
B4_D4 VO_LCDC_D4 √ √ √ √ (D1_m0) × √ (D1_m0)
B3_D3 VO_LCDC_D3 √ √ √ √ (D0_m0) × √ (D0_m0)
B2_D2 VO_LCDC_D2 √ √ × × × ×
B1_D1 VO_LCDC_D1 √ × × × × ×
B0_D0 VO_LCDC_D0 √ × × × × ×

RV1126B-P uses ROCKCHIP_MCU_DATA_MAP_DATA_1x24 so that MCU hardware output matches the earlier RV1126. Its connections are shown below:

Component name Pin name RGB888 (MCU) RGB666 (MCU) RGB666_CPADHI (MCU) RGB565 (MCU) RGB565_CPADHI (MCU) RGB3x8 (MCU)
DCLK LCDC_CLK/LCD_CLK DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS) DCLK(RS)
VSYNC LCDC_VSYNC/LCD_VSYNC VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN) VSYNC(CSN)
HSYNC LCDC_HSYNC/LCD_HSYNC HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN) HSYNC(WRN)
DEN LCDC_DEN/LCD_DEN DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN) DEN(RDN)
R7_D23 LCDC_D23/LCD_D23 √ × √ × √ ×
R6_D22 LCDC_D22/LCD_D22 √ × √ × √ ×
R5_D21 LCDC_D21/LCD_D21 √ × √ × √ ×
R4_D20 LCDC_D20/LCD_D20 √ × √ × √ ×
R3_D19 LCDC_D19/LCD_D19 √ × √ × √ ×
R2_D18 LCDC_D18/LCD_D18 √ × √ × × ×
R1_D17 LCDC_D17/LCD_D17 √ √ × × × ×
R0_D16 LCDC_D16/LCD_D16 √ √ × × × ×
G7_D15 LCDC_D15/LCD_D15 √ √ √ √ √ ×
G6_D14 LCDC_D14/LCD_D14 √ √ √ √ √ ×
G5_D13 LCDC_D13/LCD_D13 √ √ √ √ √ ×
G4_D12 LCDC_D12/LCD_D12 √ √ √ √ √ ×
G3_D11 LCDC_D11/LCD_D11 √ √ √ √ √ ×
G2_D10 LCDC_D10/LCD_D10 √ √ √ √ √ ×
G1_D9 LCDC_D9/LCD_D9 √ √ × √ × ×
G0_D8 LCDC_D8/LCD_D8 √ √ × √ × ×
B7_D7 LCDC_D7/LCD_D7 √ √ √ √ √ √
B6_D6 LCDC_D6/LCD_D6 √ √ √ √ √ √
B5_D5 LCDC_D5/LCD_D5 √ √ √ √ √ √
B4_D4 LCDC_D4/LCD_D4 √ √ √ √ √ √
B3_D3 LCDC_D3/LCD_D3 √ √ √ √ √ √
B2_D2 LCDC_D2/LCD_D2 √ √ √ √ × √
B1_D1 LCDC_D1/LCD_D1 √ √ × √ × √
B0_D0 LCDC_D0/LCD_D0 √ √ × √ × √

Normally neither RV1126B nor RV1126B-P requires additional configuration. If a change is necessary, it can be specified in DTS.

The example below configures RV1126B to use the earlier RV1126 hardware connections. This is already the default for RV1126B-P.

&rgb {
   /*

   * RV1126 compatible pin output mode 0.
   * MCU: ROCKCHIP_MCU_DATA_MAP_DATA_1x24
   */
   rockchip,data-map-mode = <0>;
};

4. Software configuration

4.1 Display paths

RGB/MCU paths for VOP 1.0/2.0

RGB/MCU paths for VOP 1.0/2.0

VOP (Video Output Process) is Rockchip’s display-processing unit. VOP 1.0 and VOP 2.0 differ mainly in multi-display support; see Rockchip_Developer_Guide_DRM_Display_Driver_CN. The left and right diagrams show RGB/MCU paths for VOP 1.0 and VOP 2.0 respectively. VOP reads and processes image data from DDR, then sends it to RGB/MCU. The interface converts the image into a protocol-compliant stream and transmits it to the panel.

4.2 Panel configuration

For the RGB panel driver, see drivers/gpu/drm/panel/panel-simple.c. A typical panel node is:

/ {
   panel: panel {

      compatible = "simple-panel";
      bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
      backlight = <&backlight>;
      enable-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
      enable-delay-ms = <20>;
      reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
      reset-delay-ms = <10>;
      status = "okay";

      display-timings {

         native-mode = <&fx070_dhm11boe_timing>;

         fx070_dhm11boe_timing: timing0 {
           clock-frequency = <50000000>;
           hactive = <1024>;
           vactive = <600>;
           hback-porch = <140>;
           hfront-porch = <160>;
           vback-porch = <20>;
           vfront-porch = <20>;
           hsync-len = <20>;
           vsync-len = <2>;

           hsync-active = <0>;
           vsync-active = <0>;
           de-active = <0>;
           pixelclk-active = <0>;
         };
      };

      port {
         panel_in_rgb: endpoint {
           remote-endpoint = <&rgb_out_panel>;
         };
      };
   };

};

&backlight {
   pwms = <&pwm9 0 25000 0>;
   status = "okay";
};

Set bus-format according to the panel’s display mode, usually determined from its datasheet pin definitions and driver-IC display-mode support. DTS macros are defined in include/uapi/linux/media-bus-format.h. Their hardware mappings are:

Display mode Bus format Cycles per pixel
RGB888 (24bit) MEDIA_BUS_FMT_RGB888_1X24 1
RGB666 (18bit) MEDIA_BUS_FMT_RGB666_1X18 1
RGB666_CPADHI (18bit) MEDIA_BUS_FMT_RGB666_1X24_CPADHI 1
RGB565 (16bit) MEDIA_BUS_FMT_RGB565_1X16 1
RGB565_CPADHI (16bit) MEDIA_BUS_FMT_RGB565_1X24_CPADHI 1
RGB3x8 (8bit) MEDIA_BUS_FMT_RGB888_3X8 MEDIA_BUS_FMT_RGB888_3X8 3
RGB4x8(8bit) MEDIA_BUS_FMT_RGB888_DUMMY_4X8 MEDIA_BUS_FMT_BGR888_DUMMY_4X8 4

Modify the backlight node’s pwms configuration to match the actual wiring. Ensure that the backlight is on before displaying an image. See Rockchip_Developer_Guide_Linux_PWM_CN.

Configure enable-gpios/reset-gpios and enable-delay-ms/reset-delay-ms/prepare-delay-ms/unprepare-delay-ms/disable-delay-ms according to panel power/reset timing requirements and the actual hardware circuit.

Optional: enable normally controls panel power. Its GPIO configuration depends on the power circuit.

Optional: the panel usually exposes a reset pin and describes reset conditions in its datasheet. GPIO configuration depends on the reset circuit.

Optional: configure enable-delay-ms/reset-delay-ms/prepare-delay-ms/unprepare-delay-ms/disable-delay-ms according to datasheet power/reset/signal timing.

The panel datasheet recommends display-timings values. They may be fine-tuned within the specified minimum/maximum limits for the application. The following datasheet corresponds to the example panel node:

Original example panel timing table

Original example panel timing table

Mode Parameter Symbol Min Typ Max Unit Note
DE Dot clock 1/tCLK 45 51.2 57 MHz  
DE DCLK pulse duty Tcwh 40 50 60 %  
DE Horizontal total tH 1324 1344 1364 tCLK  
DE Horizontal effective tHA   1024   tCLK  
DE Horizontal blank tHB 300 320 340 tCLK  
DE Vertical total tV 625 635 645 tH  
DE Vertical effective tVA   600   tH  
DE Vertical blank tVB 25 35 45 tH  
SYNC Horizontal total TH 1324 1344 1364 tCLK  
SYNC Horizontal pulse width Thpw   20 - tCLK thb + thpw = 160DCLK (fixed)
SYNC Horizontal back porch Thb   140 - tCLK thb + thpw = 160DCLK (fixed)
SYNC Horizontal front porch Thfp 140 160 180 tCLK  
SYNC Horizontal effective THA   1024   tCLK  
SYNC Vertical total TV 625 635 645 th  
SYNC Vertical pulse width Tvpw   3 - th tvpw + tvb = 23th (fixed)
SYNC Vertical back porch Tvb - 20 - th tvpw + tvb = 23th (fixed)
SYNC Vertical front porch Tvfp 2 12 22 th  
SYNC Vertical valid Tvd   600   th  

DRM’s display_timing structure and member descriptions are in include/video/display_timing.h:

/*
 * Single "mode" entry. This describes one set of signal timings a display can
 * have in one setting. This struct can later be converted to struct videomode

 * (see include/video/videomode.h). As each timing_entry can be defined as a
 * range, one struct display_timing may become multiple struct videomodes.
 *
 * Example: hsync active high, vsync active low
 *
 *            Active Video
 * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________
 *  |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync..
 *  |    |  porch |        |  porch |
 *
 * HSync _|¯¯¯¯¯¯¯¯¯¯|___________________________________________|¯¯¯¯¯¯¯¯¯
 *

 * VSync ¯|__________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________
 */
struct display_timing {
   struct timing_entry pixelclock;

   struct timing_entry hactive; /* hor. active video */
   struct timing_entry hfront_porch; /* hor. front porch */
   struct timing_entry hback_porch; /* hor. back porch */
   struct timing_entry hsync_len; /* hor. sync len */

   struct timing_entry vactive; /* ver. active video */
   struct timing_entry vfront_porch; /* ver. front porch */
   struct timing_entry vback_porch; /* ver. back porch */

   struct timing_entry vsync_len; /* ver. sync len */

   enum display_flags flags; /* display flags */
};

For RGB/MCU, clock-frequency in display-timings determines the VOP output frame rate. The calculation uses DRM timing properties htotal and vtotal. An excerpt follows; see include/drm/drm_modes.h for details.

The frame-rate calculation is implemented by drm_mode_vrefresh() in drivers/gpu/drm/drm_modes.c. With frame rate denoted by fr, the formula is:

fr = clock / (htotal * vtotal)
/**
 * struct drm_display_mode - DRM kernel-internal display mode structure

 * @hdisplay: horizontal display size
 * @hsync_start: horizontal sync start
 * @hsync_end: horizontal sync end
 * @htotal: horizontal total size
 * @hskew: horizontal skew?!
 * @vdisplay: vertical display size
 * @vsync_start: vertical sync start
 * @vsync_end: vertical sync end
 * @vtotal: vertical total size
 * @vscan: vertical scan?!
......
 *

 * The horizontal and vertical timings are defined per the following diagram.
 *
 * ::
 *
 *
 *          Active           Front      Sync       Back
 *         Region           Porch                  Porch
 *   <-----------------------><----------------><-------------><-------------->
 *    //////////////////////|
 *    ////////////////////// |
 *   ////////////////////// |.................. ................
 *                                  _______________

 *   <----- [hv]display ----->
 *   <------------- [hv]sync_start ------------>
 *   <--------------------- [hv]sync_end --------------------->
 *   <-------------------------------- [hv]total ----------------------------->*
 *
......
 */

/**
 * drm_mode_vrefresh - get the vrefresh of a mode
 * @mode: mode
 *
 * Returns:

 * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
 * value first if it is not yet set.
 */
int drm_mode_vrefresh(const struct drm_display_mode *mode)
{
   unsigned int num, den;

   if (mode->htotal == 0 || mode->vtotal == 0)
      return 0;

   num = mode->clock;
   den = mode->htotal * mode->vtotal;


   if (mode->flags & DRM_MODE_FLAG_INTERLACE)
      num *= 2;
   if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
      den *= 2;
   if (mode->vscan > 1)
      den *= mode->vscan;

   return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
}
EXPORT_SYMBOL(drm_mode_vrefresh);

4.2.1 SPI initialization

Some RGB panels require initialization commands over SPI. drivers/gpu/drm/panel/panel-simple.c supports the 3-wire 9-bit serial interface protocol:

Three-wire 9-bit SPI initialization protocol

Three-wire 9-bit SPI initialization protocol

Rockchip SPI hardware supports transfer units of 4/8/16 bits, whereas this protocol uses 9 bits. Therefore panel-simple implements SPI through GPIO bit-banging.

Typical configuration for kernel-5.10 and later:

spi_gpio: spi-gpio {
   compatible = "spi-gpio";

   #address-cells = <0x1>;
   #size-cells = <0x0>;
   pinctrl-names = "default";
   pinctrl-0 = <&spi_gpio_pins>;
   spi-delay-us = <10>;
   status = "okay";

   sck-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
   miso-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
   mosi-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
   cs-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;
   num-chipselects = <1>;


   /*
   * 320x480 RGB/MCU screen K350C4516T
   */
   panel: panel {
      compatible = "simple-panel-spi";
      reg = <0>;
      bus-format = <MEDIA_BUS_FMT_RGB666_1X18>;
      backlight = <&backlight>;
      enable-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
      enable-delay-ms = <20>;
      reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
      reset-delay-ms = <10>;

      prepare-delay-ms = <20>;
      unprepare-delay-ms = <20>;
      disable-delay-ms = <20>;
      init-delay-ms = <10>;
      width-mm = <217>;
      height-mm = <136>;
      rockchip,cmd-type = "spi";

      status = "okay";

      // type:0 is cmd, 1 is data
      panel-init-sequence = [
         /* type delay num val1 val2 val3 */
         00 00 01 e0
         01 00 01 00
         ......
         00 78 01 11
         00 00 01 29
      ];


      panel-exit-sequence = [
         //type delay num val1 val2 val3
         00 0a 01 28
         00 78 01 10
      ];

      display-timings {
         native-mode = <&kd050fwfba002_timing>;

         kd050fwfba002_timing: timing0 {
           /*
            * 10453500 for RGB666(18bit)
            */

           clock-frequency = <10453500>;
           hactive = <320>;
           vactive = <480>;
           hback-porch = <10>;
           hfront-porch = <5>;
           vback-porch = <10>;
           vfront-porch = <5>;
           hsync-len = <10>;
           vsync-len = <10>;
           hsync-active = <0>;
           vsync-active = <0>;
           de-active = <0>;

           pixelclk-active = <1>;
         };
      };

      port {
         panel_in_rgb: endpoint {
           remote-endpoint = <&rgb_out_panel>;
         };
      };
   };
};

Enable CONFIG_SPI_GPIO and configure sck-gpios, miso-gpios, mosi-gpios and

cs-gpios according to the hardware; see drivers/spi/spi-gpio.c. The panel node is essentially the same as above, with these points:

Change compatible to “simple-panel-spi”.

Set rockchip,cmd-type to “spi”.

Fill panel-init-sequence/panel-exit-sequence with the appropriate init/deinit sequences.

For kernel 4.19 and earlier, SPI RGB SDI/SCL/CS are emulated directly by GPIO in simple-panel without a third-party SPI driver. Note that SDI is not actually supported: the DTS property named SDI refers to hardware SDO, a typo in the early version. Example:

panel: panel {
   compatible = "simple-panel";

   ......
   spi-sdi-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
   spi-scl-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
   spi-cs-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
   ......
   rockchip,cmd-type = "spi";

   /* type:0 is cmd, 1 is data */
   panel-init-sequence = [
      /* type delay num val1 val2 val3 */
       00  00 01 e0
       ......
       00  78 01 11

       00  00 01 29
   ];

   panel-exit-sequence = [
      /* type delay num val1 val2 val3 */
      00 0a 01 28
      00 78 01 10
   ];
   ......
};

Reference SPI RGB configurations by kernel version:

kernel 4.19 and earlier: arch/arm64/boot/dts/rockchip/rk3308-evb-ext-v10.dtsi

kernel 5.10 and later: arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10-rgb-k350c4516t.dts

4.3 RGB interface

The RGB driver is drivers/gpu/drm/rockchip/rockchip_rgb.c. Reference DTS configuration:

&rgb {
   status = "okay";

   pinctrl-0 = <&rgb666_pins>;
   ports {
      port@1 {
         reg = <1>;


         rgb_out_panel: endpoint {
           remote-endpoint = <&panel_in_rgb>;
         };
      };
   };
};

//VOP 1.0
&rgb_in_vop {
   status = "okay";
};


//VOP 2.0
&rgb_in_vp0 {
   status = "okay";
};

RGB node configuration differs between VOP 1.0 and VOP 2.0. Reference configurations:

VOP 1.0: arch/arm/boot/dts/rv1106-evb-ext-rgb-v10.dtsi.

VOP 2.0: arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10-rgb-FX070-DHM11BOE-A.dts.

Choose pinctrl according to actual hardware connections. Pin-order definitions are in rkxxxx-pinctrl.dtsi/rvxxxx-pinctrl.dtsi.

4.4 MCU interface

The MCU interface and MCU panel drivers are in drivers/gpu/drm/rockchip/rockchip_rgb.c. DTS is essentially the same as for RGB, with additional MCU-mode selection and timing. Reference configuration:

&rgb {
   status = "okay";

   rockchip,data-sync-bypass;
   pinctrl-names = "default";
   /*
   * rgb3x8_pins_m0/rgb3x8_pins_m1 for RGB3x8(8bit)
   * rgb565_pins for RGB565(16bit)
   */
   pinctrl-0 = <&rgb565_pins>;

   /*
   * 320x480 RGB/MCU screen K350C4516T
   */
   mcu_panel: mcu-panel {
      /*

      * MEDIA_BUS_FMT_RGB888_3X8 for RGB3x8(8bit)
       * MEDIA_BUS_FMT_RGB565_1X16 for RGB565(16bit)
       */
      bus-format = <MEDIA_BUS_FMT_RGB565_1X16>;

      backlight = <&backlight>;
      enable-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_LOW>;
      enable-delay-ms = <20>;
      reset-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_LOW>;
      reset-value = <0>;
      reset-delay-ms = <10>;
      prepare-delay-ms = <20>;
      unprepare-delay-ms = <20>;
      disable-delay-ms = <20>;
      init-delay-ms = <10>;
      width-mm = <217>;
      height-mm = <136>;


      // type:0 is cmd, 1 is data
      panel-init-sequence = [
         //type delay num val1 val2 val3
          ......
          01  00 01 55 /*
                       * interface pixel format:
                       * 66 for RGB3x8(8bit)
                       * 55 for RGB565(16bit)
                       */
          ......
          01  00 01 a0 /*
                       * frame rate control:

                       * 70 (45hz) for RGB3x8(8bit)
                       * a0 (60hz) for RGB565(16bit)
                       */
          ......
          01  00 01 02 /*
                       * display function control:
                       * 32 for RGB
                       * 02 for MCU
                       */
          00  78 01 11
          00  32 01 29
          00  00 01 2c

      ];

      panel-exit-sequence = [
         //type delay num val1 val2 val3
          00  0a 01 28
          00  78 01 10
      ];

      display-timings {
         native-mode = <&kd050fwfba002_timing>;

         kd050fwfba002_timing: timing0 {
            /*
             * 7840125 for frame rate 45Hz
             * 10453500 for frame rate 60Hz
             */

            clock-frequency = <10453500>;
            hactive = <320>;
            vactive = <480>;
            hback-porch = <10>;
            hfront-porch = <5>;
            vback-porch = <10>;
            vfront-porch = <5>;
            hsync-len = <10>;
            vsync-len = <10>;
            hsync-active = <0>;
            vsync-active = <0>;
            de-active = <0>;

            pixelclk-active = <1>;
         };
      };

      port {
            panel_in_rgb: endpoint {
               remote-endpoint = <&rgb_out_panel>;
            };
         };
      };

      ports {
         rgb_out: port@1 {

            reg = <1>;
            #address-cells = <1>;
            #size-cells = <0>;

            rgb_out_panel: endpoint@0 {
               reg = <0>;
               remote-endpoint = <&panel_in_rgb>;
            };
         };
      };
   };
};


//VOP 1.0
&rgb_in_vop {
   status = "okay";
};

&vop {
   status = "okay";

   /*
    * Default config is as follows:
    *
    * mcu-pix-total = <9>;
   * mcu-cs-pst = <1>;
   * mcu-cs-pend = <8>;
   * mcu-rw-pst = <2>;

   * mcu-rw-pend = <5>;
   * mcu-hold-mode = <0>; // default set to 0
   *
   * To increase the frame rate, reduce all parameters because
   * the max dclk rate of mcu is 150M in rv1103/rv1106.
   */
   mcu-timing {
      mcu-pix-total = <5>;
      mcu-cs-pst = <1>;
      mcu-cs-pend = <4>;
      mcu-rw-pst = <2>;
      mcu-rw-pend = <3>;


      mcu-hold-mode = <0>; // default set to 0
   };
};

//VOP 2.0
&rgb_in_vp0 {
   status = "okay";
};

&vp0 {
   status = "okay";


   /*
   * Default config is as follows:
   *
   * mcu-pix-total = <9>;
   * mcu-cs-pst = <1>;
   * mcu-cs-pend = <8>;
   * mcu-rw-pst = <2>;
   * mcu-rw-pend = <5>;
   * mcu-hold-mode = <0>; // default set to 0
   *
   * To increase the frame rate, reduce all parameters because
   * the max dclk rate of mcu is 150M in rk3562.

   */
   mcu-timing {
      mcu-pix-total = <5>;
      mcu-cs-pst = <1>;
      mcu-cs-pend = <4>;
      mcu-rw-pst = <2>;
      mcu-rw-pend = <3>;

      mcu-hold-mode = <0>; // default set to 0
   };
};

MCU node configuration differs between VOP 1.0 and VOP 2.0. Reference configurations:

VOP 1.0: arch/arm/boot/dts/rv1106-evb-ext-mcu-v10.dtsi.

VOP 2.0: arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10-mcu-k350c4516t.dts. The driver selects MCU or RGB using rockchip,data-sync-bypass under the rgb node. Without the property, RGB is the default; enabling it selects MCU.

For kernel-5.10 and later, place the MCU panel under the rgb node. For kernel-4.19 and earlier, initialize it through simple-panel as an independent node. When moving a panel node from simple-panel under rgb, note:

Name the node mcu-panel; the driver uses this name to identify and parse MCU panel parameters.

The compatible property may be removed; it is not required.

An MCU panel usually needs an initialization sequence for display mode, pixel format and frame rate (depending on its driver IC), and a deinitialization sequence to turn it off or enter low-power mode. For panel-init-sequence and panel-exit-sequence:

The panel manufacturer supplies the sequence, which usually must be converted from a C file into DTS.

Each sequence row contains, from left to right: command type cmd/data, delay in ms, data length in bytes, and data.

Frame rate is normally configured during sequence initialization and must match the rate calculated in Panel Configuration. The example driver-IC manual states:

Original FRMCTR1 frame-rate-control register table

Original FRMCTR1 frame-rate-control register table

FRMCTR1 (B1h) D/CX RDX WRX D[23:8] D7..D0 HEX
Command 0 1 ↑ XX 1 0 1 1 0 0 0 1 B1h
1st parameter 1 1 ↑ XX FRS[3:0] / 0 / 0 / DIVA[1:0] B0h
2nd parameter 1 1 ↑ XX 0 / 0 / 0 / RTNA[4:0] 11h

Original excerpt of FRS/frame-rate mapping

Original excerpt of FRS/frame-rate mapping

FRS[3:0] CNT Hz / TE OFF (R34h) Hz / TE ON (R35h), VBP+VFP <24
0000 37 28.78 27.64
0001 35 30.38 29.17
0010 33 32.17 30.89
0011 31 34.18 32.82
0100 29 36.46 35.01
0101 27 39.06 37.51
0110 25 42.07 40.40
0111 23 45.57 43.76
1000 21 49.71 47.74
1001 19 54.69 52.52
1010 17 60.76 58.35
1011 15 68.36 65.65
1100 13 78.13 75.03
1101 11 91.15 87.53

mcu-timing configures normal-mode control signals CSN/WEN/REN. Its properties correspond to the intervals below. Detailed timing and interval requirements are from the datasheet of the panel used in the DTS example. The following explains how to configure mcu-timing and clock-frequency in display-timings.

MCU normal-mode control-signal timing

MCU normal-mode control-signal timing

Panel write/read timing

Panel write/read timing

Original panel driver-IC timing requirements

Original panel driver-IC timing requirements

Signal Symbol Parameter Min Max Unit Description
DCX tast Address setup time 0 - ns -
DCX that Address hold time (write/read) 0 - ns -
CSX tchw CSX high pulse width 0 - ns -
CSX tcs Chip select setup (write) 15 - ns -
CSX trcs Chip select setup (read ID) 45 - ns -
CSX trcsfm Chip select setup (read FM) 355 - ns -
CSX tcsf Chip select wait (write/read) 0 - ns -
WRX twc Write cycle 30 - ns -
WRX twrh Write control high duration 15 - ns -
WRX twrl Write control low duration 15 - ns -
RDX (FM) trcfm Read cycle (FM) 450 - ns Read frame memory
RDX (FM) trdhfm Read control high duration (FM) 90 - ns Read frame memory
RDX (FM) trdlfm Read control low duration (FM) 355 - ns Read frame memory
RDX (ID) trc Read cycle (ID) 160 - ns Read ID data
RDX (ID) trdh Read control high duration 90 - ns Read ID data
RDX (ID) trdl Read control low duration 45 - ns Read ID data
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tdst Write data setup 10 - ns Maximum: CL=30pF; minimum: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tdht Write data hold 10 - ns Maximum: CL=30pF; minimum: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] trat Read access - 40 ns Maximum: CL=30pF; minimum: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tratfm Read access - 340 ns Maximum: CL=30pF; minimum: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] trod Read output disable 20 80 ns Maximum: CL=30pF; minimum: CL=8pF

Let ptotal be mcu-pix-total in mcu-timing. The panel datasheet requires the MCU_PIX_TOTAL interval to be no shorter than tmin:

The panel datasheet gives twc = 40, while the driver-IC datasheet gives twc = 30; use the larger value.

tmin = T_CHW + T_AST + T_WC + T_CHW = 40 ns

The example panel supports MEDIA_BUS_FMT_RGB888_3X8 and MEDIA_BUS_FMT_RGB565_1X16. Let cpp denote Cycles Per Pixel, the number of cycles used to transmit one pixel (see Panel Configuration). Their theoretical maximum frame rates, frs-max and frp-max, are:

fr < 1000000000 / (htotal * ptotal * cpp * tmin)
htotal = hactive + hback-porch + hfront-porch + hsync-len = 345
vtotal = vactive + vback-porch + vfront-porch + vsync-len = 505
fr_s-max < 1000000000 / (345 * 505 * 3 * 40) ≈ 47.83 Hz
fr_p-max < 1000000000 / (345 * 505 * 1 * 40) ≈ 143.49 Hz

Editorial note: the general source formula uses ptotal, but the numerical substitution uses 505 (the stated vtotal). Both are retained without silently correcting the formula.

The source therefore selects frs = 45(Hz) for serial rgb3x8 and frp = 60(Hz) for parallel rgb1x16.

Below, suffix s means serial and suffix p means parallel.

The clock-frequency values in display-timings are:

clock_s = fr_s * htotal * vtotal = 45 * 345 * 505 = 7840125
clock_p = fr_p * htotal * vtotal = 60 * 345 * 505 = 10453500

Each platform limits MCU dclk. See mcu_max_dclk_rate in drivers/gpu/drm/rockchip/rockchip_rgb.c; it is normally 150000000 Hz. The check is implemented in rockchip_rgb_encoder_mode_valid().

Using dclkmax and the frame rate fr configured in the initialization sequence (normally 60Hz), calculate the maximum ptotal:

ptotal_max < dclk_max / (cpp * clock) - 1
ptotal_s-max < 150000000 / (3 * 7840125) - 1 ≈ 5.38
ptotal_p-max < 150000000 / (1 * 10453500) - 1 ≈ 13.35

Choose the smaller value, ptotal = 5, and determine the remaining mcu-timing values from the timing diagram.

Finally validate the calculated actual values against the datasheet timing requirements.

Actual MCU dclk is not simply clock-frequency from display-timings; it also depends on mcu-pix-total in mcu-timing and Cycles Per Pixel:

dclk = clock * cpp * (ptotal + 1)
dclk_s = 7840125 * 3 * 6 = 141122250
dclk_p = 10453500 * 1 * 6 = 62721000

Both dclk values remain below dclkmax. The actual MCU_PIX_TOTAL durations are:

t_s = (ptotal + 1) * 1000000000 / dclk_s ≈ 42.52 ns
t_p = (ptotal + 1) * 1000000000 / dclk_p ≈ 95.66 ns

Both MCU_PIX_TOTAL durations t satisfy the requirement to exceed 40 ns.

4.4.1 MCU bypass timing

Early MCU-capable platforms such as RK3308 and PX30 use the same timing for bypass and normal modes. Starting with RK3562, the IC design was optimized and the driver provides default bypass timing for most write/read needs. See vop_mcu_bypass_cfg definitions in drivers/gpu/drm/rockchip/rockchip_vop_reg.c and drivers/gpu/drm/rockchip/rockchip_vop2_reg.c, for example:

static struct rockchip_mcu_timing rk3506_mcu_bypass_timing = {
   .mcu_pix_total = 26,
   .mcu_cs_pst = 3,

   .mcu_cs_pend = 24,
   .mcu_rw_pst = 6,
   .mcu_rw_pend = 15,
};

static const struct vop_mcu_bypass_cfg rk3506_mcu_bypass_cfg = {
   .timing = &rk3506_mcu_bypass_timing,
   .dclk_rate = 120000000,
};

If the default bypass timing does not meet the application requirements, specify it in DTS; see arch/arm/boot/dts/rk3506g-evb1-v10-mcu-k350c4516t.dts:

&vop {
   mcu-timing {

      mcu-pix-total = <5>;
      mcu-cs-pst = <1>;
      mcu-cs-pend = <4>;
      mcu-rw-pst = <2>;
      mcu-rw-pend = <3>;

      mcu-hold-mode = <0>;
   };

   mcu-bypass-timing {
      mcu-pix-total = <9>;
      mcu-cs-pst = <1>;
      mcu-cs-pend = <8>;

      mcu-rw-pst = <2>;
      mcu-rw-pend = <7>;

      mcu-hold-mode = <0>;
   };
};

Bypass mode can include MCU reads. Minimum read-timing limits are normally larger than write-timing limits (see the previous example datasheet), so mcu-bypass-timing is usually calculated from read limits to satisfy both write and read requirements.

4.4.2 MCU frame write/read

In MCU normal mode, frame write/read allows commands to be exchanged between host and panel between frames, for example reading status registers or changing the display start position. It is commonly used in electrostatic stress tests or for panels requiring a per-frame display-start update.

Enable the feature by configuring panel-frame-sequence in DTS. See arch/arm/boot/dts/rk3506g-evb1-v10-mcu-k350c4516t.dts:

&rgb {
   ......
   mcu_panel: mcu-panel {

      ......
      panel-frame-sequence = [
         //type delay num val1 val2 val3
          00  00 01 0a
          02  00 01 0a
          02  00 01 0a
          00  00 01 2c
      ];
      ......
   };
   ......
};

Inter-frame write/read is implemented in drivers/gpu/drm/rockchip/rockchip_rgb.c:

static void mcu_interframe_work_func(struct work_struct *work)
{
   struct rockchip_mcu_panel *mcu_panel =

      container_of(work, struct rockchip_mcu_panel, interframe_work);
   struct drm_panel *panel = &mcu_panel->base;
   struct drm_display_mode *mode = mcu_panel->desc->mode;
   struct drm_crtc *crtc = mcu_panel->encoder->crtc;
   u32 timeout = DIV_ROUND_CLOSEST_ULL(1000, drm_mode_vrefresh(mode));
   int ret;

   ret = rockchip_drm_wait_vact_end(crtc, timeout);
   if (ret) {
      DRM_DEV_ERROR(panel->dev, "wairt vact end timed out\n");
      return;
   }


   ret = rockchip_mcu_panel_xfer_mcu_cmd_seq(mcu_panel, mcu_panel->desc->frame_seq);
   if (ret) {
      DRM_DEV_ERROR(panel->dev, "failed to send frame cmds seq\n");
      return;
   }

   schedule_work(&mcu_panel->interframe_work);
};

For specific application requirements, modify the implementation of the work item above.

5. Debugging procedure

1. Verify the hardware connections of every RGB/MCU pin. Pin mappings can differ between platforms; see

Hardware Connections above.

Example RGB/MCU pin connections

Example RGB/MCU pin connections

2. Use the panel datasheet to configure enable/reset polarity, power sequencing and the backlight PWM channel. For MCU panels, also configure the correct initialization sequence.

Example reset, enable and backlight PWM connections

Example reset, enable and backlight PWM connections

3. With the backlight on, verify the enable/reset levels again. If measurements are still unexpected, verify that iomux selects GPIO correctly.

6. Common issues

6.1 RGB/MCU displays an image with noise or misalignment

Try inverting dclk polarity using pixelclk-active under display-timings. This changes the relative phase of dclk and data.

display-timings {
   native-mode = <&fx070_dhm11boe_timing>;


   fx070_dhm11boe_timing: timing0 {
      clock-frequency = <50000000>;
      hactive = <1024>;
      vactive = <600>;
      hback-porch = <140>;
      hfront-porch = <160>;
      vback-porch = <20>;
      vfront-porch = <20>;
      hsync-len = <20>;
      vsync-len = <2>;
      hsync-active = <0>;
      vsync-active = <0>;

      de-active = <0>;
      pixelclk-active = <0>; // 1 翻转,0 不翻转
   };
};

Explore this topic → · Learning paths →