Spacemit 屏幕调试文档
介绍spacemit k1平台 Uboot 和 kernel 的 mipi 与 hdmi 屏幕驱动用例和调试方法。
模块介绍
spacemit 平台 Display 模块使用 DRM 框架,DRM 全称是 Direct Rendering Manager,是Linux系统目前主流的显示框架,适应当前显示硬件的特性。

一、Uboot 屏幕调试
1.1. 源码结构介绍
spacemit 平台 Uboot 显示驱动源码结构:
uboot-2022.10/drivers/video$ tree spacemit
spacemit
├── dsi
│ ├── drv
│ │ ├── spacemit_dphy.c // mipi dsi dphy驱动
│ │ ├── spacemit_dphy.h
│ │ ├── spacemit_dsi_common.c
│ │ ├── spacemit_dsi_drv.c // mipi dsi 驱动
│ │ ├── spacemit_dsi_drv.h
│ │ └── spacemit_dsi_hw.h
│ ├── include
│ │ ├── spacemit_dsi_common.h
│ │ └── spacemit_video_tx.h
│ ├── Makefile
│ └── video
│ ├── lcd // panel 配置
│ │ ├── lcd_ft8201sinx101.c
│ │ ├── lcd_gx09inx101.c
│ │ ├── lcd_icnl9911c.c
│ │ ├── lcd_icnl9951r.c
│ │ ├── lcd_jd9365dah3.c
│ │ └── lcd_lt8911ext_edp_1080p.c
│ ├── spacemit_mipi_port.c
│ └── spacemit_video_tx.c
├── Kconfig
├── Makefile
├── spacemit_dpu.c // dpu 驱动
├── spacemit_dpu.h
├── spacemit_edp.c // eDP panel驱动
├── spacemit_hdmi.c // HDMI 驱动
├── spacemit_hdmi.h
├── spacemit_mipi.c // mipi 驱动
└─ ─ spacemit_mipi.h
1.2. 配置介绍
1.2.1. CONFIG配置
执行 make uboot-menuconfig,进入 Device Drivers -> Graphics support,将以下配置打开(默认情况下已开启)。
Device Drivers --->
Graphics support --->
<*> Enable SPACEMIT Video Suppor
<*> HDMI port
<*> MIPI Port
<*> EDP Port
1.2.2. HDMI dts配置
配置 hdmi 相关设备树
//uboot-2022.10/arch/riscv/dts/k1-x_deb1.dts
&dpu {
status = "okay";
};
&hdmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hdmi_0>; //pinctrl
status = "okay";
};
1.2.3. MIPI dts配置
MIPI DSI
Gpio
MIPI DSI panel gpio相关配置,以k1-x_deb1方案为例: gpio81配置为panel复位pin,gpio82和gpio83配置为panel电源控制pin。
//uboot-2022.10/arch/riscv/dts/k1-x_deb1.dts
&dpu {
status = "okay";
};
&mipi_dsi {
status = "okay";
};
&panel {
dcp-gpios = <&gpio 82 0>; // 配置panel 电源控制 gpio
dcn-gpios = <&gpio 83 0>; // 配置panel 电源控制 gpio
backlight = <&backlight>; // 配置背光 pwm
reset-gpios = <&gpio 81 0>; // 配置panel 复位 gpio
status = "okay";
};
DSI电源配置
MIPI DSI需要配置MIPI DSI 1.2v电源。
以k1-x_deb1方案为例: 需配置pmic ldo_5为MIPI DSI 1.2v。(方案实际可不需要配置,默认已开启)
//uboot-2022.10/arch/riscv/dts/k1-x_deb1.dts
&ldo_27 {
regulator-init-microvolt = <1200000>;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
//uboot-2022.10/arch/riscv/dts/k1-x_spm8821.dtsi
/* dldo */
ldo_27: LDO_REG5 {
regulator-name = "ldo5";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
PWM
通过pwm控制背光
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "okay";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "okay";
};
1.2.4. display timing配置
Uboot阶段默认使用88000000作为pix-clock,614400000作为bit-clcok,无需额外配置
//uboot-2022.10/drivers/video/spacemit/spacemit_mipi.c
pix_clk = dev_read_u32_default(dev, "pix-clk", 88000000);
ret = clk_set_rate(&priv->pxclk, pix_clk);
if (ret < 0) {
pr_err("clk_set_rate mipi dsi pxclk failed: %d\n", ret);
return ret;
}
bit_clk = dev_read_u32_default(dev, "bit-clk", 614400000);
ret = clk_set_rate(&priv->bitclk, bit_clk);
if (ret < 0) {
pr_err("clk_set_rate mipi dsi bitclk failed: %d\n", ret);
return ret;
}
已完 成功能调试的MIPI DSI panel,相关c文件放置在lcd目录。
uboot-2022.10/drivers/video/spacemit/dsi/video$ tree lcd
lcd
├── lcd_ft8201sinx101.c
├── lcd_gx09inx101.c
├── lcd_icnl9911c.c
├── lcd_icnl9951r.c
├── lcd_jd9365dah3.c
└── lcd_lt8911ext_edp_1080p.c
1.3. 新增 mipi panel 配置参考实例
以lcd_gx09inx101为例
- 在uboot-2022.10/drivers/video/spacemit/dsi/video/lcd/路径下新建lcd_gx09inx101.c
/ SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 Spacemit Co., Ltd.
*
*/
#include <linux/kernel.h>
#include "../../include/spacemit_dsi_common.h"
#include "../../include/spacemit_video_tx.h"
#include <linux/delay.h>
#define UNLOCK_DELAY 0
struct spacemit_mode_modeinfo gx09inx101_spacemit_modelist[] = {
{
.name = "1200x1920-60",
.refresh = 60, //fps
.xres = 1200, // width 像素
.yres = 1920, // height 像素
.real_xres = 1200,
.real_yres = 1920,
.left_margin = 40, //hbp
.right_margin = 80, //hfp
.hsync_len = 10, //hsync
.upper_margin = 16, //vbp
.lower_margin = 20, //vfp
.vsync_len = 4, //vsync
.hsync_invert = 0,
.vsync_invert = 0,
.invert_pixclock = 0,
.pixclock_freq = 156*1000, // 像素时钟
.pix_fmt_out = OUTFMT_RGB888,
.width = 142, //显示屏物理宽度
.height = 228, //显示屏物理长度
},
};
struct spacemit_mipi_info gx09inx101_mipi_info = {
.height = 1920, // mipi dsi dphy中配置屏幕高
.width = 1200, // mipi dsi dphy中配置屏幕宽
.hfp = 80, // mipi dsi dphy中配置水平前肩(Horizontal Front Porch)
.hbp = 40, // mipi dsi dphy中配置水平后肩(Horizontal Back Porch)
.hsync = 10, // mipi dsi dphy中配置水平同步信号(Horizontal Sync)
.vfp = 20, // mipi dsi dphy中配置垂直前肩(Vertical Front Porch)
.vbp = 16, // mipi dsi dphy中配置垂直后肩(Vertical Back Porch)
.vsync = 4, // mipi dsi dphy中配置垂直同步信号(Vertical Sync)
.fps = 60, // mipi dsi dphy中配置帧率
.work_mode = SPACEMIT_DSI_MODE_VIDEO, /*command_mode, video_mode*/
.rgb_mode = DSI_INPUT_DATA_RGB_MODE_888,// panel中配置mipi dsi 数据格式
.lane_number = 4, // mipi dsi dphy中配置mipi dsi lane数量
.phy_bit_clock = 614400000, // mipi dsi dphy中配置mipi dsi dphy bit clock
.phy_esc_clock = 51200000, // mipi dsi dphy中配置mipi dsi dphy esc clock
.split_enable = 0, // mipi dsi dphy中配置mipi dsi使能split
.eotp_enable = 0, // mipi dsi dphy中配置mipi dsi使能eotp
.burst_mode = DSI_BURST_MODE_BURST,
};
static struct spacemit_dsi_cmd_desc gx09inx101_set_id_cmds[] = {
{SPACEMIT_DSI_SET_MAX_PKT_SIZE, SPACEMIT_DSI_LP_MODE, UNLOCK_DELAY, 1, {0x01}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_read_id_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_LP_MODE, UNLOCK_DELAY, 1, {0xfb}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_set_power_cmds[] = {
{SPACEMIT_DSI_SET_MAX_PKT_SIZE, SPACEMIT_DSI_HS_MODE, UNLOCK_DELAY, 1, {0x1}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_read_power_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_HS_MODE, UNLOCK_DELAY, 1, {0xA}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_init_cmds[] = {
//8279 + INX10.1
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xB0,0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC3,0x4F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC4,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC5,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC6,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC7,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC8,0x4D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC9,0x52}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCA,0x51}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCD,0x5D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCE,0x5B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCF,0x4B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xD0,0x49}},
·······
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDA,0x19}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDB,0x17}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDC,0x17}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDD,0x18}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDE,0x1A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDF,0x1E}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0,0x20}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE1,0x23}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE2,0x07}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 200, 2, {0x11, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 50, 2, {0x29, 0x00}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_sleep_out_cmds[] = {
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,200,1,{0x11}},
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,50,1,{0x29}},
};
static struct spacemit_dsi_cmd_desc gx09inx101_sleep_in_cmds[] = {
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,50,1,{0x28}},
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,200,1,{0x10}},
};
struct lcd_mipi_panel_info lcd_gx09inx101 = {
.lcd_name = "gx09inx101",
.lcd_id = 0x8279,
.panel_id0 = 0x1,
.power_value = 0x14,
.panel_type = LCD_MIPI,
.width_mm = 142,
.height_mm = 228,
.dft_pwm_bl = 128,
.set_id_cmds_num = ARRAY_SIZE(gx09inx101_set_id_cmds),
.read_id_cmds_num = ARRAY_SIZE(gx09inx101_read_id_cmds),
.init_cmds_num = ARRAY_SIZE(gx09inx101_init_cmds),
.set_power_cmds_num = ARRAY_SIZE(gx09inx101_set_power_cmds),
.read_power_cmds_num = ARRAY_SIZE(gx09inx101_read_power_cmds),
.sleep_out_cmds_num = ARRAY_SIZE(gx09inx101_sleep_out_cmds),
.sleep_in_cmds_num = ARRAY_SIZE(gx09inx101_sleep_in_cmds),
//.drm_modeinfo = gx09inx101_modelist,
.spacemit_modeinfo = gx09inx101_spacemit_modelist,
.mipi_info = &gx09inx101_mipi_info,
.set_id_cmds = gx09inx101_set_id_cmds,
.read_id_cmds = gx09inx101_read_id_cmds,
.set_power_cmds = gx09inx101_set_power_cmds,
.read_power_cmds = gx09inx101_read_power_cmds,
.init_cmds = gx09inx101_init_cmds,
.sleep_out_cmds = gx09inx101_sleep_out_cmds,
.sleep_in_cmds = gx09inx101_sleep_in_cmds,
.bitclk_sel = 3,
.bitclk_div = 1,
.pxclk_sel = 2,
.pxclk_div = 6,
};
int lcd_gx09inx101_init(void)
{
int ret;
ret = lcd_mipi_register_panel(&lcd_gx09inx101);
return ret;
}
以下各项根据屏幕相关信息进行配置。
initial-cmd:
static struct spacemit_dsi_cmd_desc gx09inx101_init_cmds[] = {
//8279 + INX10.1
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xB0,0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC3,0x4F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC4,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC5,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC6,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC7,0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC8,0x4D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xC9,0x52}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCA,0x51}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCD,0x5D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCE,0x5B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xCF,0x4B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xD0,0x49}},
·······
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDA,0x19}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDB,0x17}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDC,0x17}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDD,0x18}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDE,0x1A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xDF,0x1E}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0,0x20}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE1,0x23}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE2,0x07}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 200, 2, {0x11, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 50, 2, {0x29, 0x00}},
};
通过配置 read id 读取 panel_id
lcd_gx09inx101读取0xfb寄存器
//uboot-2022.10/drivers/video/spacemit/dsi/video/lcd/lcd_gx09inx101.c
static struct spacemit_dsi_cmd_desc gx09inx101_read_id_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_LP_MODE, UNLOCK_DELAY, 1, {0xfb}},
};
0xfb寄存器理应读取的到值为0x1
//uboot-2022.10/drivers/video/spacemit/dsi/video/lcd/lcd_gx09inx101.c
struct lcd_mipi_panel_info lcd_gx09inx101 = {
.lcd_name = "gx09inx101",
.panel_id0 = 0x1,
通过读取power_value进行esd check
lcd_gx09inx10读取0xA寄存器进行esd check
//uboot-2022.10/drivers/video/spacemit/dsi/video/lcd/lcd_gx09inx101.c
static struct spacemit_dsi_cmd_desc gx09inx101_read_power_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_HS_MODE, UNLOCK_DELAY, 1, {0xA}},
};
power_value:0xA寄存器理应读取到的值
//uboot-2022.10/drivers/video/spacemit/dsi/video/lcd/lcd_gx09inx101.c
struct lcd_mipi_panel_info lcd_gx09inx101 = {
.power_value = 0x10,
- 修改Makefile
//uboot-2022.10/drivers/video/spacemit/dsi/Makefile
# SPDX-License-Identifier: GPL-2.0
obj-y += video/spacemit_video_tx.o \
video/spacemit_mipi_port.o \
drv/spacemit_dphy.o \
drv/spacemit_dsi_common.o \
drv/spacemit_dsi_drv.o
obj-y += video/lcd/lcd_icnl9911c.o
obj-y += video/lcd/lcd_icnl9951r.o
obj-y += video/lcd/lcd_jd9365dah3.o
obj-y += video/lcd/lcd_gx09inx101.o
obj-y += video/lcd/lcd_lt8911ext_edp_1080p.o
- 修改 spacemit_dsi_common.h
//uboot-2022.10/drivers/video/spacemit/dsi/include/spacemit_dsi_common.h
int lcd_icnl9911c_init(void);
int lcd_icnl9951r_init(void);
int lcd_gx09inx101_init(void); // 增加 lcd_gx09inx101.c实现的相应函数的声明
int lcd_jd9365dah3_init(void);
int lcd_lt8911ext_edp_1080p_init(void);
- 修改 spacemit_mipi_port.c
//uboot-2022.10/drivers/video/spacemit/dsi/video/spacemit_mipi_port.c
if (strcmp("lt8911ext_edp_1080p", priv->panel_name) == 0) {
tx_device_client.panel_type = LCD_EDP;
tx_device.panel_type = tx_device_client.panel_type;
lcd_lt8911ext_edp_1080p_init();
} else if(strcmp("icnl9951r", priv->panel_name) == 0) {
tx_device_client.panel_type = LCD_MIPI;
tx_device.panel_type = tx_device_client.panel_type;
lcd_icnl9951r_init();
} else if(strcmp("jd9365dah3", priv->panel_name) == 0) {
tx_device_client.panel_type = LCD_MIPI;
tx_device.panel_type = tx_device_client.panel_type;
lcd_jd9365dah3_init();
} else {
// lcd_icnl9911c_init();
lcd_gx09inx101_init(); //增加gx09inx101 panel识别,新增其它panel参考以上三个
}
1.4. Uboot 启动相关 log
[ 0.842] Found device 'mipi@d421a800', disp_uc_priv=000000007deb1aa0
/* read id ,在lcd_gx09inx101.c 中
struct lcd_mipi_panel_info lcd_gx09inx101.id0 配置 */
[ 1.001] read panel id OK: read value = 0x1, 0x0, 0x0
[ 1.003] Panel is gx09inx101
[ 1.260] fb=7f700000, size=1200x1920