K230 linux LCD 移植指南#
本文档仅适用于 K230 Linux SDK
概述#
VO(Video Output,视频输出)模块主动从内存中读取视频和图形数据,并通过显示设备输出。K230 芯片支持以下显示/回写设备及视频层配置。
LAYER 层支持#
功能 |
LAYER1 |
LAYER3 |
LAYER4 |
|---|---|---|---|
输入格式 |
YUV420 NV12 |
YUV420 NV12 |
YUV420 NV12 |
最大分辨率 |
1920 x 1080 |
1920 x 1080 |
1920 x 1080 |
叠加显示 |
支持可配置叠加顺序 |
支持可配置叠加顺序 |
支持可配置叠加顺序 |
Rotation |
√ |
- |
- |
Scaler |
√ |
- |
- |
Mirror |
√ |
- |
- |
Gray 模式 |
√ |
- |
- |
独立开关 |
√ |
√ |
√ |
OSD 层支持#
功能 |
OSD0 |
OSD1 |
OSD2 |
OSD3 |
|---|---|---|---|---|
输入格式 |
RGB888, RGB565, ARGB8888, Monochrome-8-bit, RGB4444, RGB1555 |
RGB888, RGB565, ARGB8888, Monochrome-8-bit, RGB4444, RGB1555 |
RGB888, RGB565, ARGB8888, Monochrome-8-bit, RGB4444, RGB1555 |
RGB888, RGB565, ARGB8888, Monochrome-8-bit, RGB4444, RGB1555 |
最大分辨率 |
1920 x 1080 |
1920 x 1080 |
1920 x 1080 |
1920 x 1080 |
叠加显示 |
支持可配置叠加顺序 |
支持可配置叠加顺序 |
支持可配置叠加顺序 |
支持可配置叠加顺序 |
ARGB 265 级 Alpha |
√ |
√ |
√ |
√ |
独立开关 |
√ |
√ |
√ |
√ |
Linux 下 LCD 适配#
本章节介绍如何在 K230 Linux SDK 中新增一块 MIPI LCD 屏幕。K230 通过 DSI 接口以 LP(Low Power)命令方式配置屏幕,主要需要修改屏幕初始化序列和时序参数相关的设备树。
屏幕初始化序列#
屏幕初始化序列对应设备树节点 panel-init-sequence,每行命令格式如下:
字节位置 |
0 |
1 |
2 |
3+ |
|---|---|---|---|---|
含义 |
Command Type |
Delay |
Payload Length |
Data |
参数说明:
参数 |
说明 |
|---|---|
Command Type |
命令类型(0x05: 单字节数据,0x15: 双字节数据,0x39: 多字节数据) |
Delay |
命令执行后等待的毫秒数 |
Payload Length |
数据负载长度(字节数) |
Data |
要写入的命令数据 |
命令示例解析
// 39 00 04 ff 98 81 03
// Command Type: 0x39 (多字节),Delay: 0ms,Payload Length: 4 字节
// 数据: ff 98 81 03
//
// 15 00 02 01 00
// Command Type: 0x15 (双字节),Delay: 0ms,Payload Length: 2 字节
// 数据: 01 00
//
// 05 00 01 35
// Command Type: 0x05 (单字节),Delay: 0ms,Payload Length: 1 字节
// 数据: 35
//
// 05 78 01 11
// Command Type: 0x05 (单字节),Delay: 120ms (0x78),Payload Length: 1 字节
// 数据: 11
panel-init-sequence = [
39 00 04 ff 98 81 03
15 00 02 01 00
15 00 02 02 00
15 00 02 03 53
15 00 02 04 13
15 00 02 05 00
15 00 02 06 04
// ... 中间省略 ...
15 00 02 ce 59
15 00 02 cf 2c
15 00 02 d0 30
15 00 02 d1 55
15 00 02 d2 6b
15 00 02 d3 3f
39 00 04 ff 98 81 00
05 00 01 35
05 78 01 11
05 00 01 29
];
// 完整示例请参考: arch/riscv/boot/dts/canaan/display-ili9881-800x1280.dtsi
注意:屏幕初始化序列通常由屏幕厂商提供,需按 K230 设备树格式转换。
屏幕时序参数#
LCD 时序参数用于配置 DSI 控制器以匹配屏幕的时序要求。
// 示例: arch/riscv/boot/dts/canaan/display-st7701-480x800.dtsi
lcd: panel@0 {
compatible = "canaan,universal";
reg = <0>;
display-timings {
timing-0 {
clock-frequency = <39600000>;
hactive = <480>;
vactive = <800>;
hfront-porch = <80>;
hback-porch = <20>;
hsync-len = <20>;
vfront-porch = <220>;
vback-porch = <70>;
vsync-len = <10>;
};
};
};
字段说明:
字段 |
说明 |
|---|---|
clock-frequency |
DSI 像素时钟频率(Hz)。推荐使用 k230 屏幕时序工具 计算 |
hactive |
有效水平显示宽度(像素) |
vactive |
有效垂直显示高度(像素) |
hfront-porch |
水平前肩(bfp):一行有效数据结束到同步脉冲开始之间的等待时间 |
hback-porch |
水平后肩(hbp):同步脉冲结束到下一行有效数据开始之间的等待时间 |
hsync-len |
水平同步脉冲宽度(hsa) |
vfront-porch |
垂直前肩(vfp):一帧数据结束到垂直同步脉冲开始之间的等待时间 |
vback-porch |
垂直后肩(vbp):垂直同步脉冲结束到下一帧有效数据开始之间的等待时间 |
vsync-len |
垂直同步脉冲宽度(vsa) |
单位说明:
hsa、hbp、bfp、hactive 单位为像素(pix)
vsa、vbp、vfp、vactive 单位为行(line)
屏幕其他配置项#
// 示例: arch/riscv/boot/dts/canaan/display-st7701-480x800.dtsi
lcd: panel@0 {
compatible = "canaan,universal";
reg = <0>;
panel-width-mm = <480>; // 屏幕物理宽度(mm)
panel-height-mm = <800>; // 屏幕物理高度(mm)
panel-dsi-lane = <2>; // DSI 数据 lane 数量
};
配置项说明:
字段 |
说明 |
必填 |
|---|---|---|
panel-width-mm |
屏幕物理宽度(单位:mm) |
是 |
panel-height-mm |
屏幕物理高度(单位:mm) |
是 |
panel-dsi-lane |
DSI 数据 lane 数量(2/4) |
是 |
注意:以上参数需根据实际屏幕规格书进行配置。
U-Boot 下 LCD 适配#
说明:K230 U-Boot 下支持 LCD 主要用于显示开机 Logo,一般场景下不建议在 U-Boot 中启用 LCD。目前仅 K230 01 Studio 产品开启了 Logo 显示功能。
适配概述#
U-Boot 仅支持 01 Studio 屏幕,如需支持其他屏幕,可参考 K230 01 Studio U-Boot 支持 ILI9881 8 寸屏 的提交。
在 SDK 中搜索 CONFIG_K230_BARE_DISP_LOGO_ILI9881 可查看需要修改的位置,主要包括:
屏幕初始化序列
屏幕时序参数
VO 配置
初始化序列#
需要把 Linux 下的初始化序列转换为类似如下格式:
// buildroot-overlay/boot/uboot/u-boot-2022.10-overlay/board/canaan/common/logo/st7701.c
void ili9881_800x1280_init(void)
{
// ILI9881 800x1280 initialization sequence from DTS
// Page 0x03
uint8_t param1[] = {0xff, 0x98, 0x81, 0x03};
uint8_t param2[] = {0x01, 0x00};
uint8_t param3[] = {0x02, 0x00};
uint8_t param4[] = {0x03, 0x53};
// ... 其他初始化参数
kd_dwc_lpdt_send_pkg(param202, sizeof(param202));
msleep(100);
kd_dwc_lpdt_send_pkg(param201, sizeof(param201));
msleep(120);
kd_dwc_lpdt_send_pkg(param202, sizeof(param202));
}
时序和vo配置#
// buildroot-overlay/boot/uboot/u-boot-2022.10-overlay/board/canaan/common/logo/k230_logo.c
int k230_display_logo(void)
{
info = (k_connector_info){
0,
BACKGROUND_PINK_COLOR,
10,
14,
1,
K_DSI_2LAN,
K_BURST_MODE,
K_VO_LP_MODE,
{ 9, 196, 0x17, 0xa3 },
{ 39600, 475200, 600, 480, 20, 20, 80, 1100, 800, 10, 70, 220 },
};
}
说明:请使用 k230 屏幕时序工具 计算参数后转换填写。
分辨率设置#
在 U-Boot 中设置屏幕分辨率,参考以下代码片段:
// buildroot-overlay/boot/uboot/u-boot-2022.10-overlay/board/canaan/common/logo/display_logo.c
void vo_layer1_test(k_connector_info *info)
{
uint32_t reg = 0;
#ifdef CONFIG_K230_BARE_DISP_LOGO_DF
uint32_t act_w = 480;
uint32_t act_h = 640;
#elif defined(CONFIG_K230_BARE_DISP_LOGO_ILI9881)
uint32_t act_w = 800;
uint32_t act_h = 1280;
#else
uint32_t act_w = 480;
uint32_t act_h = 800;
#endif
// ...
}
复位和背光#
//buildroot-overlay/boot/uboot/u-boot-2022.10-overlay/board/canaan/common/logo/st7701.c
#define GPIO_RST_PIN 24 //修改为正确值
#define GPIO_LCD_BACKLIGHT_EN 25 //修改为正确值
注意:如果uboot使能logo的化,linux下需要注掉类似如下代码:
//output/k230_canmv_01studio_defconfig/build/linux-7d4e1f444f461dbe3833bd99a4640e7b6c2cd529/arch/riscv/boot/dts/canaan/>k230-canmv-01studio-lcd.dts &lcd { // dsi_reset-gpios = <&gpio0_ports 24 GPIO_ACTIVE_HIGH>; // backlight_gpio-gpios = <&gpio0_ports 25 GPIO_ACTIVE_HIGH>; };
U-Boot 下 Logo 替换#
01 Studio 在 LCD 上会显示嘉楠 Logo,如需替换为其他图片,请参考本章节。
相关配置宏#
# buildroot-overlay/boot/uboot/u-boot-2022.10-overlay/configs/k230_canmv_01studio_defconfig
CONFIG_K230_BARE_DISP_LOGO=y # 使能 Logo 显示
CONFIG_K230_BARE_DISP_LOGO_PATH="board/canaan/k230-soc/logo/logo_01.yuv" # Logo 文件路径
CONFIG_SYS_MEM_TOP_HIDE=0x200000 # 为 Logo 预留内存(2MB),如 Logo 超大需调增
Logo 文件格式#
Logo 文件格式为 YUV NV12,替换 board/canaan/k230-soc/logo/logo_01.yuv 文件即可。
Logo 生成方法#
以下示例介绍如何将 PNG 图片转换为 800 x 1280 屏幕所需的 Logo 文件:
# 强制转换为 800x1280 分辨率
ffmpeg -i logo.png -vf "scale=800:1280" -y output.png
# 逆时针旋转 90 度并转换为 NV12 格式
# (K230 LCD 默认为竖屏显示,需要旋转)
ffmpeg -i output.png -vf "transpose=2" -pix_fmt nv12 -f rawvideo logo_new.yuv
# 可选:将 NV12 转回 PNG 查看效果
ffmpeg -f rawvideo -pix_fmt nv12 -s 1280x800 -i logo.yuv \
-vf "transpose=1" -frames:v 1 logo_new.png
K230 屏幕时序工具使用#
工具地址:K230 MIPI DSI Connector Info Generator
Linux 设备树时序参数计算#
操作步骤:
打开工具页面,输入屏幕时序参数(hactive、vactive、hfront-porch 等)
点击 Generate 按钮
工具自动生成配置代码,
resolution.pclk值乘以 1000 即为设备树中clock-frequency的值

工具生成代码示例:
{
// this configure is generated by tools.
.connector_name = "test", // 根据实际修改
.screen_test_mode = 0,
.dsi_test_mode = 0,
.bg_color = BACKGROUND_BLACK_COLOR,
.intr_line = 10, // 1024 lines
.pixclk_div = 14,
.lan_num = K_DSI_2LAN,
.work_mode = K_BURST_MODE,
.cmd_mode = K_VO_LP_MODE,
.phy_attr = {
.n = 4,
.m = 97,
.voc = 0x17, // 0b00010111
.hs_freq = 0x80 | 0x26, // 0b10100110
},
.resolution = {
.pclk = 39600, // 像素时钟:39600 * 1000 = 39600000 Hz
.phyclk = 475200,
.htotal = (480 + 20 + 20 + 80), // 600
.hdisplay = 480,
.hsync_len = 20,
.hback_porch = 20,
.hfront_porch = 80,
.vtotal = (800 + 10 + 70 + 220), // 1100
.vdisplay = 800,
.vsync_len = 10,
.vback_porch = 70,
.vfront_porch = 220,
},
.type = 0, // 根据实际修改
}
U-Boot 时序参数转换#
U-Boot 中的 k_connector_info 结构体与工具生成代码的对应关系如下:
结构体成员 |
工具字段 |
说明 |
|---|---|---|
第 1 个参数 |
|
像素时钟(MHz) |
第 2 个参数 |
|
物理时钟(kHz) |
第 3 个参数 |
|
水平总周期 |
第 4 个参数 |
|
水平显示宽度 |
第 5 个参数 |
|
水平同步长度 |
第 6 个参数 |
|
水平后肩 |
第 7 个参数 |
|
水平前肩 |
第 8 个参数 |
|
垂直总周期 |
第 9 个参数 |
|
垂直显示高度 |
第 10 个参数 |
|
垂直同步长度 |
第 11 个参数 |
|
垂直后肩 |
第 12 个参数 |
|
垂直前肩 |
|
|
DSI PHY 参数 n |
|
|
DSI PHY 参数 m |
|
|
DSI PHY 参数 voc |
|
|
DSI PHY 参数 hs_freq |
说明:
k_connector_info结构体完整形式如下:info = (k_connector_info){ 0, // connector_name 索引 BACKGROUND_PINK_COLOR, // bg_color 10, // intr_line 14, // pixclk_div 1, // lan_num K_DSI_2LAN, // work_mode K_VO_LP_MODE, // cmd_mode { 9, 196, 0x17, 0xa3 }, // phy_attr {n, m, voc, hs_freq} { 39600, 475200, ... }, // resolution 字段 };提示:使用工具计算时序参数可避免手动计算错误,确保屏幕时序配置正确。
HDMI 支持#
K230 CANMV 和 K230 01 Studio 平台已支持 HDMI 显示,通过 LT9611 桥接芯片实现。
配置文件:arch/riscv/boot/dts/canaan/k230-canmv.dts
/ {
hdmi: connector {
compatible = "hdmi-connector";
label = "hdmi";
type = "a";
port {
hdmi_connector_in: endpoint {
remote-endpoint = <<9611_out>;
};
};
};
};
&i2c4 {
status = "okay";
lt9611: hdmi-bridge@3b {
compatible = "lontium,lt9611";
reg = <0x3b>;
reset-gpios = <&gpio1_ports 10 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio1_ports>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
lt9611_in: endpoint {
remote-endpoint = <&dsi_out_lt9611>;
};
};
port@2 {
reg = <2>;
lt9611_out: endpoint {
remote-endpoint = <&hdmi_connector_in>;
};
};
};
};
};
&dsi {
ports {
port@1 {
reg = <1>;
dsi_out_lt9611: endpoint {
remote-endpoint = <<9611_in>;
};
};
};
};
配置要点:
添加 LT9611 桥接芯片节点,配置 I2C 地址和 GPIO 复位
建立 DSI -> LT9611 -> HDMI Connector 的连接路径
需要 HDMI 移植时可参考此配置结构
测试验证#
基础参数查看#
使用 modetest 工具查看显示系统所有参数:
modetest -M canaan-drm
OSD 层测试#
# OSD 层测试:在 HDMI(48) 上叠加 OSD(39),格式 RG16
modetest -M canaan-drm -D 0 -a -s 48@46:1920x1080 -P 39@46:640x480@RG16 -v -F tiles
LAYER 层测试#
# LAYER 层测试:在 HDMI(48) 上叠加 LAYER(43),格式 NV12
# 注意:LAYER43 支持 Rotation 和 Mirror 功能
modetest -M canaan-drm -D 0 -a -s 48@46:1920x1080 -P 43@46:640x480@NV12 -v -F tiles
测试参数说明:
参数 |
说明 |
|---|---|
|
指定 DSI 接口 |
|
自动设置平面 |
|
设置连接器模式(connector@crtc:resolution) |
|
设置平面属性(plane@crtc:resolution@format) |
|
显示帧率信息 |
|
设置帧缓冲格式 |
配置文件参考路径#
文件 |
说明 |
|---|---|
|
ST7701 3.5寸屏幕配置示例 |
|
ILI9881 8寸屏幕配置示例 |
