LVDS屏
MIPI DTS配置
Neardi-3568的SDK有MIPI DSI的DTS文件: rk3568-neardi-linux-ld120-mipi2lvds-EV101WXM-N10.dtsi
,此 DTS 文件为 MIPI_EV101WXM-N10 10.1寸屏配置。
VP 分配
从DTS文件中我们可以看到以下语句:
&video_phy1 {
status = "okay";
};
&dsi1_in_vp0 {
status = "okay";
};
&dsi1_in_vp1 {
status = "disabled";
};
&route_dsi1 {
status = "okay";
connect = <&vp0_out_dsi1>;
};
vp 是视频接口的意思,这一段表示 DSI1 开启并使用 vp1,HDMI 开启并使用 vp0 DSI1 和 HDMI 交换 vp 也是可以的,要保证不同的屏幕需要使用不同的 vp
引脚配置
&dsi1 {
status = "okay";
rockchip,lane-rate = <854>;
enable-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; // lvds_pwren
reset-gpios = <&gpio3 RK_PC7 GPIO_ACTIVE_HIGH>; // lvds_rst
......
&pinctrl {
backlight {
/* for edp and dsi2lvds */
lcd_en: lcd-en {
rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
};
这里定义了LCD的控制引脚:
NAME | GPIO | GPIO_ACTIVE |
---|---|---|
enable-gpios(lvds_pwren) | RK_PC7 | GPIO_ACTIVE_HIGH |
reset-gpios(lvds_rst) | GPIO0_B0 | GPIO_ACTIVE_LOW |
在硬件信号上LCD_EN引脚高电平有效,具体的引脚配置请参考《GPIO 使用》一节。
背光配置
在DTS文件中配置了背光信息,如下:
backlight1: backlight1 {
compatible = "pwm-backlight";
pwms = <&pwm5 0 25000 0>;
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
......
......
>;
default-brightness-level = <200>;
enable-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&lcd_en>;
};
enable-gpios:背光使能脚,高电平有效。
pwms属性:配置PWM,范例里面默认使用pwm5。
brightness-levels属性:配置背光亮度数组,一般以值 255 为一个 scale,当 PWM 设置为正极性时,从 0~255 表示背光为正极,占空比从 0%~100% 变化,255~0 为负极性,占空比从 100%~0% 变化;当 PWM 设置为负极性时,反之。
default-brightness-level属性:开机时默认背光亮度,范围为0-255。 具体请参考kernel中的说明文档:
kernel/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
显示时序配置
Power on/off sequence
MIPI屏的上下电时序通常都在规格书的Power on/off sequence
章节中,可根据规格书的上下电时序修改dts,panel节点中有如下属性:
&dsi1 {
...
dsi1_panel: panel@0 {
status = "okay";
compatible = "simple-panel-dsi";
reg = <0>;
backlight = <&backlight1>;
reset-delay-ms = <60>;
enable-delay-ms = <60>;
prepare-delay-ms = <60>;
unprepare-delay-ms = <60>;
disable-delay-ms = <60>;
...
};
};
MIPI屏所需时序,调试屏幕时可根据本身上下电时序是否需要再配置此属性。MIPI上下电后需要发送初始化或退出指令才能使之正常工作,列表如下:
&dsi1 {
status = "okay";
rockchip,lane-rate = <854>;
dsi1_panel: panel@0 {
...
panel-init-sequence = [
23 02 02 27 AA
23 02 02 48 02
23 02 02 B6 20
...
];
};
};
范例 dts 中的 init-sequence ,只是配置了上电指令, 其他的初始化指令已经烧录在 EV101WXM-N10 这款MIPI屏里,dts 无需配置。接下来我们来看看上下电时序在驱动中的实现, 具体实现在kernel/drivers/gpu/drm/panel/panel-simple.c
中:
static int panel_simple_disable(struct drm_panel *panel)
{
...
if (p->backlight) {
p->backlight->props.power = FB_BLANK_POWERDOWN;
p->backlight->props.state |= BL_CORE_FBBLANK;
backlight_update_status(p->backlight);
}
if (p->desc->delay.disable)
panel_simple_sleep(p->desc->delay.disable);
if (p->cmd_type == CMD_TYPE_MCU) {
err = panel_simple_xfer_mcu_cmd_seq(p, p->desc->exit_seq);
if (err)
dev_err(panel->dev, "failed to send exit cmds seq\n");
}
...
}
static int panel_simple_unprepare(struct drm_panel *panel)
{
...
if (p->desc->exit_seq) {
if (p->dsi)
panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq);
else if (p->cmd_type == CMD_TYPE_SPI)
err = panel_simple_xfer_spi_cmd_seq(p, p->desc->exit_seq);
if (err)
dev_err(panel->dev, "failed to send exit cmds seq\n");
}
gpiod_direction_output(p->reset_gpio, 1);
if(!p->enable_on_always){
gpiod_direction_output(p->enable_gpio, 0);
}
...
}
static int panel_simple_prepare(struct drm_panel *panel)
{
...
gpiod_direction_output(p->enable_gpio, 1);
if (p->desc->delay.prepare)
panel_simple_sleep(p->desc->delay.prepare);
...
gpiod_direction_output(p->reset_gpio, 1);
if (p->desc->delay.reset)
panel_simple_sleep(p->desc->delay.reset);
gpiod_direction_output(p->reset_gpio, 0); //由于驱动在控制reset脚时序的时候使用了`gpiod`这类的API
//如果在DTS配置了低电平有效,那么这里就会将reset引脚拉高,即取反。
if (p->desc->delay.init)
panel_simple_sleep(p->desc->delay.init);
if (p->desc->init_seq) {
if (p->dsi)
panel_simple_xfer_dsi_cmd_seq(p, p->desc->init_seq);
else if (p->cmd_type == CMD_TYPE_SPI)
err = panel_simple_xfer_spi_cmd_seq(p, p->desc->init_seq);
if (err)
dev_err(panel->dev, "failed to send init cmds seq\n");
}
if(p->desc->delay.mipi_data){
panel_simple_sleep(p->desc->delay.mipi_data);
}
...
}
static int panel_simple_enable(struct drm_panel *panel)
{
...
if (p->cmd_type == CMD_TYPE_MCU) {
err = panel_simple_xfer_mcu_cmd_seq(p, p->desc->init_seq);
if (err)
dev_err(panel->dev, "failed to send init cmds seq\n");
}
if (p->desc->delay.enable)
panel_simple_sleep(p->desc->delay.enable);
if (p->backlight) {
p->backlight->props.state &= ~BL_CORE_FBBLANK;
p->backlight->props.power = FB_BLANK_UNBLANK;
backlight_update_status(p->backlight);
}
...
}
uboot实现在u-boot/drivers/video/drm/rockchip_panel.c
中的panel_simple_unprepare、panel_simple_prepare、panel_simple_enable 、panel_simple_disable 4个函数中,具体实现可以自己查看。
Display-Timings
display_timings在dts中定义:
disp_timings1: display-timings {
native-mode = <&dsi1_timing0>;
dsi1_timing0: timing0 {
clock-frequency = <72600000>;//<80000000>;
hactive = <800>;//<768>;
vactive = <1280>;
hsync-len = <14>; //20, 50,10
hback-porch = <26>; //50, 56,10
hfront-porch = <32>;//50, 30,180
vsync-len = <8>;//4
vback-porch = <20>;//4
vfront-porch = <80>;//8
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
相关的参数一般可以在屏的规格书中找到,如下在kernel/drivers/gpu/drm/panel/panel-simple.c
的panel_simple_probe中初始化了获取时序的函数。
static int panel_simple_probe(struct device *dev, const struct panel_desc *desc){
...
panel->base.funcs = &panel_simple_funcs;
...
}
...
static const struct drm_panel_funcs panel_simple_funcs = {
.loader_protect = panel_simple_loader_protect,
.disable = panel_simple_disable,
.unprepare = panel_simple_unprepare,
.prepare = panel_simple_prepare,
.enable = panel_simple_enable,
.get_modes = panel_simple_get_modes,
.get_timings = panel_simple_get_timings,
};
...
该函数在kernel/drivers/gpu/drm/panel/panel-simple.c
中定义:
static int panel_simple_get_timings(struct drm_panel *panel, unsigned int num_timings, struct display_timing *timings)
{
struct panel_simple *p = to_panel_simple(panel);
unsigned int i;
if (p->desc->num_timings < num_timings)
num_timings = p->desc->num_timings;
if (timings)
for (i = 0; i < num_timings; i++)
timings[i] = p->desc->timings[i];
return p->desc->num_timings;
}
详细说明可参考以下附件: Rockchip DRM Panel Porting Guide.pdf
EV101WXM-N10
屏资料: BOE原装 宽温工业屏 EV101WXM-N10.pdf
FAQ
EV101WXM-N10 10.1寸屏不显示
确认固件是否支持
默认版本无LVDS功能,烧录Neardi-3568 LVDS 固件百度网盘 烧录方法请参阅《使用USB线升级固件》一章。