整理一下px30移植时,panel-simple.c的调用堆栈逻辑,这一块主要是涉及到panel-simple.c 和 rockchip_rgb.c的逻辑调用 ,其中panel-simple.c 主要是实现读取设备树中设置并且提供设置函数,rockchip_rgb.c 的初始化会调用到panel-simple.c中提供的相应底层初始化设备。
panel {
compatible = "simple-panel";
backlight = <&backlight>;
//电源
power-supply = <&vcc_lcd>;
#gpio的使能引脚0_A2 默认高电平
enable-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
// prepare-delay-ms = <120>;
// enable-delay-ms = <120>;
// disable-delay-ms = <120>;
// unprepare-delay-ms = <120>;
bus-format = <MEDIA_BUS_FMT_RBG888_1X24>;
width-mm = <108>;
height-mm = <64>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
//时序信息,需要根据芯片手册去修改
clock-frequency = <33300000>;
hactive = <800>;
vactive = <480>;
hback-porch = <36>;
hfront-porch = <210>;
vback-porch = <13>;
vfront-porch = <22>;
hsync-len = <10>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <1>;
};
};
分析一下panel-simple.c
static const struct of_device_id platform_of_match[] = {
{
.compatible = "simple-panel",
.data = NULL,
},
...
, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, platform_of_match);
//初始化panel
static int panel_simple_platform_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
id = of_match_node(platform_of_match, pdev->dev.of_node);
if (!id)
return -ENODEV;
return panel_simple_probe(&pdev->dev, id->data);
}
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,
};
panel_simple_probe
panel_simple_get_cmds
drm_panel_init(&panel->base);
panel->base.dev = dev;
panel->base.funcs = &panel_simple_funcs;//提供panel操作函数
err = drm_panel_add(&panel->base);
看一下如何取得设备树中的时序信息的
panel_simple_get_modes
panel_simple_of_get_native_mode
of_get_drm_display_mode
of_get_videomode
of_get_display_timings
of_parse_display_timing
ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
ret |= parse_timing_property(np, "hactive", &dt->hactive);
ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
ret |= parse_timing_property(np, "vactive", &dt->vactive);
ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
of_property_read_u32(np, "vsync-active", &val)
of_property_read_u32(np, "hsync-active", &val)
of_property_read_u32(np, "de-active", &val)
struct drm_encoder_helper_funcs rockchip_rgb_encoder_helper_funcs = {
.enable = rockchip_rgb_encoder_enable,
.disable = rockchip_rgb_encoder_disable,
.atomic_check = rockchip_rgb_encoder_atomic_check,
.loader_protect = rockchip_rgb_encoder_loader_protect,
};
struct drm_connector_helper_funcs rockchip_rgb_connector_helper_funcs = {
.get_modes = rockchip_rgb_connector_get_modes,
.best_encoder = rockchip_rgb_connector_best_encoder,
};
rockchip_rgb_probe
component_add(dev, &rockchip_rgb_component_ops)
rockchip_rgb_bind
drm_encoder_helper_add(encoder, &rockchip_rgb_encoder_helper_funcs);
if (rgb->panel) {
drm_connector_helper_add(connector,&rockchip_rgb_connector_helper_funcs);
}
后续更新