Rockchip · AI & Linux Hub

Экран и звук

Руководство Rockchip RGB/MCU: контакты, панели, SPI и тайминги

Полные протоколы RGB/MCU, поддержка платформ, карты контактов, DTS, инициализация, формулы частоты кадров и frame write/read.

· ArmSoM Editorial · Rockchip source documentation · 33 мин чтения

Это справочный материал по RGB/MCU Rockchip. Таблица V1.7.1 перечисляет RK1808, RK312X/PX3SE, RK3288, RK3308B/BS, RK3326/PX30, RK3506, RK3562, RK3568, RK3576, RV1103/1106, RV1109/RV1126 и RV1126B с различными возможностями. Это не означает поддержку на всех платах ArmSoM. Настройки SPI/панели разделены для kernel 4.19 и ранее и для 5.10 и новее. Проверьте SDK/BSP платы, доступность интерфейса, мультиплексирование контактов, напряжения и тайминги панели. Проверка на оборудовании ArmSoM не проводилась; значения и иллюстрации оригинала являются примерами платформы.

Источник: Rockchip_Developer_Guide_RGB_MCU_CN.pdf, V1.7.1, 34 страницы. Предоставлен только китайский оригинал. Английская и русская версии полностью переводят технический текст; во всех версиях используются рисунки китайского PDF без заявления о переводе надписей внутри них.

Редакционная проверка · ArmSoM documentation · Rockchip

1. Основные понятия

1.1 Интерфейс RGB

RGB также называется DPI (Display Pixel Interface). Для синхронизации используются четыре сигнала: Vsync, Hsync, Den (Enable) и DCLK (Dotclk). В зависимости от способа синхронизации различают DE mode и SYNC mode. Тайминги выхода RGB Rockchip совместимы с обоими режимами.

Тайминги режима DE

Тайминги режима DE

1.1.1 Режим DE

Действительность DB[23:0] определяется только Den. В оригинале указано, что данные действительны при низком уровне и недействительны в противном случае.

1.1.2 Режим SYNC

Тайминги режима SYNC

Тайминги режима SYNC

Данные DB[23:0] синхронизируются Vsync и Hsync и выводятся согласно приведённой развёртке.

1.2 Интерфейс MCU

MCU также называется DBI или интерфейсом 8080. Он поддерживает двунаправленную связь TX/RX с четырьмя сигналами синхронизации: RS (CSX), CSN (D/CX), WEN (WRX) и REN (RDX). Во вводном абзаце оригинала указана поддержка Rockchip только MCU TX; далее таблица платформ отдельно указывает поддержку чтения RK3506 и RV1126B. Противоречие сохранено для проверки.

1.2.1 Тайминги записи

Тайминги записи MCU

Тайминги записи MCU

CSX, D/CX и WRX последовательно переводятся в низкий уровень. Пока DB[23:0] действительны, WRX сначала переходит в низкий, затем в высокий уровень.

1.2.2 Тайминги чтения

Тайминги чтения MCU и первые недействительные данные

Тайминги чтения MCU и первые недействительные данные

CSX, D/CX и RDX последовательно переводятся в низкий уровень. Пока DB[23:0] действительны, RDX сначала переходит в низкий, затем в высокий уровень.

Перед чтением выполните запись, передающую панели адрес регистра.

Первое чтение возвращает недействительные данные; действительные данные поступают со второго чтения.

Чтение MCU обычно используется при отладке панели, для различения идентификаторов панелей и совместимости с несколькими панелями, а также для функции frame read, описанной далее.

1.2.3 Режимы bypass и normal

Режим bypass используется при передаче команд между MCU и панелью операциями write/read.

Передача init/deinit из panel-init-sequence/panel-exit-sequence и операции frame write/read относятся к режиму bypass. См. соответствующие подразделы настройки ПО ниже.

В режиме normal хост передаёт изображение через MCU в RAM панели для обычного отображения. Этот режим обычно включается после передачи panel-init-sequence и подтверждения успешной инициализации панели.

Режим bypass может включать запись и чтение; режим normal — только запись.

2. Поддержка платформ Rockchip

Платформа SoC Поддержка RGB Поддержка MCU Поддержка чтения MCU Версия VOP Тракт Video Port (VOP 2.0) Поддерживаемые режимы вывода
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

Описание VOP и VP (Video Port) см. в Rockchip_Developer_Guide_DRM_Display_Driver_CN.

3. Аппаратные соединения

3.1 RK3562/RK3576/RK3506/RV1126B

Имя компонента Имя контакта 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

Имя компонента Имя контакта 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

Имя компонента Имя контакта 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

Имя компонента Имя контакта 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

Имя компонента Имя контакта 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 введена карта данных data map для сохранения схемы соединений раннего RV1126. Разные карты выводят данные на разные аппаратные контакты.

Полные определения data map находятся в 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

Для обычного RV1126B следующие соединения MCU по умолчанию соответствуют ROCKCHIP_MCU_DATA_MAP_DATA_WITH_DUMMY_0.

Имя компонента Имя контакта 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 использует ROCKCHIP_MCU_DATA_MAP_DATA_1x24, чтобы аппаратный выход MCU соответствовал раннему RV1126. Соединения показаны ниже:

Имя компонента Имя контакта 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 √ √ × √ × √

Обычно RV1126B и RV1126B-P не требуют дополнительной настройки. При необходимости изменения можно задать в DTS.

Следующий пример настраивает RV1126B на схему соединений раннего RV1126. Для RV1126B-P эта конфигурация уже используется по умолчанию.

&rgb {
   /*

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

4. Настройка ПО

4.1 Тракты вывода

Тракты RGB/MCU для VOP 1.0/2.0

Тракты RGB/MCU для VOP 1.0/2.0

VOP (Video Output Process) — блок обработки изображения Rockchip. Архитектуры VOP 1.0 и VOP 2.0 отличаются главным образом поддержкой нескольких дисплеев; см. Rockchip_Developer_Guide_DRM_Display_Driver_CN. Левая и правая схемы показывают RGB/MCU для VOP 1.0 и VOP 2.0 соответственно. VOP читает изображение из DDR, обрабатывает его и передаёт в RGB/MCU. Интерфейс преобразует изображение в поток соответствующего протокола и отправляет панели.

4.2 Настройка панели

Драйвер панели RGB см. в drivers/gpu/drm/panel/panel-simple.c. Типичный узел панели:

/ {
   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";
};

Задайте bus-format по режиму дисплея панели, обычно указанному в описании контактов datasheet и поддерживаемых режимах IC. Макросы DTS определены в include/uapi/linux/media-bus-format.h. Соответствия аппаратным соединениям:

Режим дисплея Формат шины Циклов на пиксель
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

Измените pwms узла backlight согласно фактической разводке. Перед выводом изображения убедитесь, что подсветка включена. См. Rockchip_Developer_Guide_Linux_PWM_CN.

Настройте enable-gpios/reset-gpios и enable-delay-ms/reset-delay-ms/prepare-delay-ms/unprepare-delay-ms/disable-delay-ms согласно требованиям питания/сброса панели и реальной аппаратной схеме.

Необязательно: enable обычно управляет питанием панели. Конфигурация GPIO зависит от схемы питания.

Необязательно: панель обычно имеет контакт reset, условия срабатывания которого описаны в datasheet. Конфигурация GPIO зависит от схемы сброса.

Необязательно: задайте enable-delay-ms/reset-delay-ms/prepare-delay-ms/unprepare-delay-ms/disable-delay-ms согласно таймингам power/reset/signal из datasheet.

Datasheet панели содержит рекомендуемые display-timings. Значения можно подстраивать под приложение в пределах заданных минимальных и максимальных границ. Следующий datasheet соответствует примеру узла панели:

Исходная таблица таймингов панели примера

Исходная таблица таймингов панели примера

Режим Параметр Обозначение Мин. Тип. Макс. Единица Примечание
DE Пиксельная частота 1/tCLK 45 51.2 57 MHz  
DE Скважность DCLK Tcwh 40 50 60 %  
DE Полный период строки tH 1324 1344 1364 tCLK  
DE Активный период строки tHA   1024   tCLK  
DE Горизонтальное гашение tHB 300 320 340 tCLK  
DE Полный период кадра tV 625 635 645 tH  
DE Активный период кадра tVA   600   tH  
DE Вертикальное гашение tVB 25 35 45 tH  
SYNC Полный период строки TH 1324 1344 1364 tCLK  
SYNC Ширина горизонтального импульса Thpw   20 - tCLK thb + thpw = 160DCLK (фиксировано)
SYNC Задняя горизонтальная площадка Thb   140 - tCLK thb + thpw = 160DCLK (фиксировано)
SYNC Передняя горизонтальная площадка Thfp 140 160 180 tCLK  
SYNC Активный период строки THA   1024   tCLK  
SYNC Полный период кадра TV 625 635 645 th  
SYNC Ширина вертикального импульса Tvpw   3 - th tvpw + tvb = 23th (фиксировано)
SYNC Задняя вертикальная площадка Tvb - 20 - th tvpw + tvb = 23th (фиксировано)
SYNC Передняя вертикальная площадка Tvfp 2 12 22 th  
SYNC Активная часть кадра Tvd   600   th  

Структура DRM display_timing и описание её полей находятся в 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 */
};

Для RGB/MCU свойство clock-frequency в display-timings определяет частоту кадров VOP. В расчёте используются параметры DRM htotal и vtotal. Ниже приведён фрагмент; подробнее см. include/drm/drm_modes.h.

Расчёт частоты кадров реализован функцией drm_mode_vrefresh() в drivers/gpu/drm/drm_modes.c. Если обозначить частоту кадров fr, формула имеет вид:

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

Некоторые RGB-панели требуют команд инициализации через SPI. drivers/gpu/drm/panel/panel-simple.c поддерживает протокол 3-wire 9-bit serial interface:

Протокол инициализации трёхпроводного 9-битного SPI

Протокол инициализации трёхпроводного 9-битного SPI

Аппаратный SPI Rockchip поддерживает передачу блоками 4/8/16 бит, тогда как этот протокол использует 9 бит. Поэтому panel-simple реализует SPI программно через GPIO.

Типичная конфигурация для kernel-5.10 и новее:

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>;
         };
      };
   };
};

Включите CONFIG_SPI_GPIO и задайте sck-gpios, miso-gpios, mosi-gpios и

cs-gpios согласно аппаратной схеме; см. drivers/spi/spi-gpio.c. Узел панели в основном аналогичен приведённому выше, но учитывайте следующее:

Измените compatible на “simple-panel-spi”.

Задайте rockchip,cmd-type как “spi”.

Заполните panel-init-sequence/panel-exit-sequence соответствующими последовательностями init/deinit.

В kernel 4.19 и более ранних версиях SDI/SCL/CS для SPI RGB эмулируются GPIO непосредственно в simple-panel без стороннего драйвера SPI. SDI фактически не поддерживается: обозначение SDI в DTS относится к аппаратному SDO и является опечаткой ранней версии. Пример:

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
   ];
   ......
};

Примеры настройки SPI RGB для разных ядер:

kernel 4.19 и ранее: arch/arm64/boot/dts/rockchip/rk3308-evb-ext-v10.dtsi

kernel 5.10 и новее: arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10-rgb-k350c4516t.dts

4.3 Интерфейс RGB

Драйвер RGB: drivers/gpu/drm/rockchip/rockchip_rgb.c. Пример DTS:

&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 различается для VOP 1.0 и VOP 2.0. Примеры:

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.

Выберите pinctrl по реальным аппаратным соединениям. Определения порядка контактов находятся в rkxxxx-pinctrl.dtsi/rvxxxx-pinctrl.dtsi.

4.4 Интерфейс MCU

Драйверы интерфейса MCU и панели MCU находятся в drivers/gpu/drm/rockchip/rockchip_rgb.c. DTS в основном аналогичен RGB с дополнительными параметрами выбора режима MCU и тайминга. Пример:

&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 различается для VOP 1.0 и VOP 2.0. Примеры:

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. Драйвер выбирает MCU или RGB по свойству rockchip,data-sync-bypass узла rgb. Без свойства используется RGB; включение свойства выбирает MCU.

В kernel-5.10 и новее рекомендуется размещать MCU panel внутри узла rgb. В kernel-4.19 и ранее отдельный узел инициализируется через simple-panel. При переносе узла панели из simple-panel в rgb учитывайте:

Назовите узел mcu-panel: драйвер использует это имя для обнаружения и разбора параметров панели MCU.

Свойство compatible можно удалить; оно не требуется.

Панели MCU обычно нужна последовательность инициализации display mode, pixel format и frame rate (в зависимости от IC), а также деинициализации для выключения или перехода в малопотребляющий режим. Для panel-init-sequence и panel-exit-sequence:

Последовательность предоставляет производитель панели; обычно её нужно преобразовать из файла C в DTS.

Каждая строка последовательности содержит слева направо: тип cmd/data, задержку в ms, длину данных в байтах и данные.

Частота кадров обычно задаётся при инициализации последовательности и должна соответствовать расчёту в разделе настройки панели. Фрагмент руководства IC примера:

Исходная таблица регистра управления частотой кадров FRMCTR1

Исходная таблица регистра управления частотой кадров FRMCTR1

FRMCTR1 (B1h) D/CX RDX WRX D[23:8] D7..D0 HEX
Команда 0 1 ↑ XX 1 0 1 1 0 0 0 1 B1h
1-й параметр 1 1 ↑ XX FRS[3:0] / 0 / 0 / DIVA[1:0] B0h
2-й параметр 1 1 ↑ XX 0 / 0 / 0 / RTNA[4:0] 11h

Исходный фрагмент соответствия FRS и частоты кадров

Исходный фрагмент соответствия FRS и частоты кадров

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 задаёт тайминги управляющих сигналов CSN/WEN/REN в режиме normal. Свойства соответствуют интервалам ниже. Подробные тайминги и требования взяты из datasheet панели примера DTS. Далее описана настройка mcu-timing и clock-frequency в display-timings.

Тайминги управляющих сигналов MCU normal

Тайминги управляющих сигналов MCU normal

Тайминги записи/чтения панели

Тайминги записи/чтения панели

Исходные требования тайминга IC панели

Исходные требования тайминга IC панели

Сигнал Обозначение Параметр Мин. Макс. Единица Описание
DCX tast Время установки адреса 0 - ns -
DCX that Время удержания адреса (запись/чтение) 0 - ns -
CSX tchw Ширина высокого импульса CSX 0 - ns -
CSX tcs Установка выбора кристалла (запись) 15 - ns -
CSX trcs Установка выбора кристалла (чтение ID) 45 - ns -
CSX trcsfm Установка выбора кристалла (чтение FM) 355 - ns -
CSX tcsf Ожидание выбора кристалла (запись/чтение) 0 - ns -
WRX twc Цикл записи 30 - ns -
WRX twrh Длительность высокого уровня управления записью 15 - ns -
WRX twrl Длительность низкого уровня управления записью 15 - ns -
RDX (FM) trcfm Цикл чтения (FM) 450 - ns Чтение памяти кадра
RDX (FM) trdhfm Высокий уровень управления чтением (FM) 90 - ns Чтение памяти кадра
RDX (FM) trdlfm Низкий уровень управления чтением (FM) 355 - ns Чтение памяти кадра
RDX (ID) trc Цикл чтения (ID) 160 - ns Чтение данных ID
RDX (ID) trdh Высокий уровень управления чтением 90 - ns Чтение данных ID
RDX (ID) trdl Низкий уровень управления чтением 45 - ns Чтение данных ID
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tdst Установка данных записи 10 - ns Максимум: CL=30pF; минимум: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tdht Удержание данных записи 10 - ns Максимум: CL=30pF; минимум: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] trat Время доступа чтения - 40 ns Максимум: CL=30pF; минимум: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] tratfm Время доступа чтения - 340 ns Максимум: CL=30pF; минимум: CL=8pF
DB[23:0], DB[17:0], DB[15:0], DB[8:0], DB[7:0] trod Время отключения выхода чтения 20 80 ns Максимум: CL=30pF; минимум: CL=8pF

Пусть ptotal — значение mcu-pix-total в mcu-timing. Datasheet панели требует, чтобы интервал MCU_PIX_TOTAL был не короче tmin:

В datasheet панели twc = 40, а в datasheet IC twc = 30; используется большее значение.

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

Панель примера поддерживает MEDIA_BUS_FMT_RGB888_3X8 и MEDIA_BUS_FMT_RGB565_1X16. Обозначим cpp как Cycles Per Pixel — число циклов передачи пикселя (см. настройку панели). Теоретические пределы частоты кадров frs-max и frp-max:

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

Примечание: в общей формуле оригинала указан ptotal, но при подстановке использовано 505 (указанный vtotal). Формула и расчёт сохранены без скрытого исправления.

Поэтому в оригинале выбраны frs = 45(Hz) для последовательного rgb3x8 и frp = 60(Hz) для параллельного rgb1x16.

Далее индекс s означает последовательный режим, p — параллельный.

Значения clock-frequency в display-timings:

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

Каждая платформа ограничивает dclk MCU. См. mcu_max_dclk_rate в drivers/gpu/drm/rockchip/rockchip_rgb.c; обычно это 150000000 Hz. Проверка реализована в rockchip_rgb_encoder_mode_valid().

По dclkmax и частоте кадров fr из последовательности инициализации (обычно 60Hz) вычисляется максимальный 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

Выберите меньшее значение, ptotal = 5, и определите остальные параметры mcu-timing по диаграмме.

В конце проверьте рассчитанные фактические значения по требованиям тайминга datasheet.

Фактическая dclk MCU не равна просто clock-frequency из display-timings; она также зависит от mcu-pix-total в mcu-timing и Cycles Per Pixel:

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

Обе частоты dclk не превышают dclkmax. Фактические длительности MCU_PIX_TOTAL:

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

Обе длительности MCU_PIX_TOTAL t удовлетворяют требованию превышать 40 ns.

4.4.1 Тайминги MCU bypass

Ранние платформы MCU, например RK3308 и PX30, используют одинаковые тайминги bypass и normal. Начиная с RK3562 конструкция IC оптимизирована, а драйвер предоставляет стандартные тайминги bypass для большинства операций write/read. См. vop_mcu_bypass_cfg в drivers/gpu/drm/rockchip/rockchip_vop_reg.c и drivers/gpu/drm/rockchip/rockchip_vop2_reg.c, например:

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,
};

Если стандартные тайминги bypass не подходят, задайте их в DTS; см. 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 может включать чтение MCU. Минимальные ограничения тайминга чтения обычно больше, чем записи (см. предыдущий datasheet), поэтому mcu-bypass-timing обычно рассчитывают по ограничениям чтения, чтобы удовлетворить требованиям обеих операций.

4.4.2 MCU frame write/read

В режиме MCU normal функция frame write/read позволяет обмениваться командами между хостом и панелью между кадрами: читать регистры состояния, менять начало отображения и т. п. Обычно она используется при электростатических испытаниях либо для панелей, требующих обновления начальной позиции каждый кадр.

Для включения задайте panel-frame-sequence в DTS. См. 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
      ];
      ......
   };
   ......
};

Межкадровые write/read реализованы в 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);
};

Для специальных требований приложения можно изменить реализацию указанной выше рабочей функции.

5. Порядок отладки

1. Проверьте аппаратные соединения всех контактов RGB/MCU. Сопоставления контактов могут различаться между платформами; см.

раздел аппаратных соединений выше.

Пример соединений контактов RGB/MCU

Пример соединений контактов RGB/MCU

2. По datasheet панели настройте полярность enable/reset, последовательность питания и канал PWM подсветки. Для MCU-панели также задайте правильную последовательность инициализации.

Пример соединений reset, enable и PWM подсветки

Пример соединений reset, enable и PWM подсветки

3. При включённой подсветке снова проверьте уровни enable/reset. Если измерения не соответствуют ожидаемым, проверьте правильность выбора GPIO в iomux.

6. Типичные проблемы

6.1 Шум или смещение изображения на RGB/MCU

Попробуйте инвертировать полярность dclk свойством pixelclk-active в display-timings. Это изменяет относительную фазу dclk и данных.

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 不翻转
   };
};

Другие статьи по теме → · Учебные маршруты →