版权声明:转载请说明出处 https://blog.csdn.net/qq_33166886/article/details/84852678
首先分析了一下uboot启动流程中的一部分代码,如下
第一部分:开机logo
1.
board_late_init //rk33xx.c
board/rockchip/rk33xx/rk33xx.c:238: board_fbt_preboot();
board_late_init
board_fbt_preboot(); //fastboot.c
1. if (gd->fdt_blob) {
int node = fdt_path_offset(gd->fdt_blob, "/display-subsystem");//找到display-subsystem这个noded,在rk3399-android.dtsi中指定为有效。
if (!fdt_device_is_available(gd->fdt_blob, node) || node < 0) {
#if defined(CONFIG_LCD)
g_is_new_display = 0;
node = fdt_path_offset(gd->fdt_blob, "/fb");
g_logo_on_state = fdtdec_get_int(gd->fdt_blob, node, "rockchip,uboot-logo-on", 0);
if (g_logo_on_state != 0) {
lcd_enable_logo(true);
drv_lcd_init();//drv_lcd_init
}
#else
drv_lcd_init:
drv_lcd_init();//drv_lcd_init //lcd.c
lcd_init(lcd_base); //lcd.c
lcd_ctrl_init(lcdbase);//rockchip_fb.c
rk_lcdc_init(panel_info.lcdc_id);
rk_lcdc_load_screen(&panel_info);
........
vop_config_timing(vop_dev, screen);//vop
h_total = hsync_len + left_margin + x_res + right_margin;
v_total = vsync_len + upper_margin + y_res + lower_margin;
val = V_DSP_HS_END(hsync_len) | V_DSP_HTOTAL(h_total);
vop_msk_reg(vop_dev, DSP_HTOTAL_HS_END, val);
val = V_DSP_HACT_END(hsync_len + left_margin + x_res) |
V_DSP_HACT_ST(hsync_len + left_margin);
vop_msk_reg(vop_dev, DSP_HACT_ST_END, val);
if (screen->mode.vmode & FB_VMODE_INTERLACED) {
/* First Field Timing */
val = V_DSP_VS_END(vsync_len) |
V_DSP_VTOTAL(2 * (vsync_len + upper_margin +
lower_margin) + y_res + 1);
vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val);
val = V_DSP_VACT_END(vsync_len + upper_margin + y_res / 2) |
V_DSP_VACT_ST(vsync_len + upper_margin);
vop_msk_reg(vop_dev, DSP_VACT_ST_END, val);
/* Second Field Timing */
vs_st_f1 = vsync_len + upper_margin + y_res / 2 + lower_margin;
vs_end_f1 = 2 * vsync_len + upper_margin + y_res / 2 +
lower_margin;
val = V_DSP_VS_ST_F1(vs_st_f1) | V_DSP_VS_END_F1(vs_end_f1);
vop_msk_reg(vop_dev, DSP_VS_ST_END_F1, val);
vact_end_f1 = 2 * (vsync_len + upper_margin) + y_res +
lower_margin + 1;
vact_st_f1 = 2 * (vsync_len + upper_margin) + y_res / 2 +
lower_margin + 1;
val = V_DSP_VACT_END_F1(vact_end_f1) |
V_DSP_VACT_ST_F1(vact_st_f1);
vop_msk_reg(vop_dev, DSP_VACT_ST_END_F1, val);
vop_msk_reg(vop_dev, DSP_CTRL0,
V_DSP_INTERLACE(1) | V_DSP_FIELD_POL(0));
val = V_DSP_LINE_FLAG_NUM_0(lower_margin ?
vact_end_f1 : vact_end_f1 - 1);
val |= V_DSP_LINE_FLAG_NUM_1(lower_margin ?
vact_end_f1 : vact_end_f1 - 1);
vop_msk_reg(vop_dev, LINE_FLAG, val);
}else
...........
vop_vop_post_cfg(vop_dev, screen);
.........
post_dsp_vact_st = screen->post_dsp_sty / 2 +
screen->mode.vsync_len +
screen->mode.upper_margin;
post_dsp_vact_end = post_dsp_vact_st +
screen->post_ysize / 2;
.........
val = V_DSP_HACT_END_POST(post_dsp_hact_end) |
V_DSP_HACT_ST_POST(post_dsp_hact_st);
vop_msk_reg(vop_dev, POST_DSP_HACT_INFO, val);
val = V_DSP_VACT_END_POST(post_dsp_vact_end) |
V_DSP_VACT_ST_POST(post_dsp_vact_st);
........
lcd_clear();
lcd_enable();
2.
2. rockchip_display_init()
fdt_path_offset(blob, "/display-subsystem/route"); //寻找route node.
fdt_device_is_available //查看route是否是okay的
init_display_buffer //获取fb地址
fdt_for_each_subnode //依次解析route下的子节点,当前用的edp,所以只解析route_edp节点。
fdt_node_offset_by_phandle //获取connect node.
find_crtc_node//获取对应的ctrl node.
rockchip_get_crtc //根据ctrl node从g_crtc数组中找到具体的元素,这里compatible是"rockchip,rk3399-vop-big",在rk3399.dtsi中定义
find_connector_node //获取对应的connector node
rockchip_get_connector //根据connector node从g_connector数组中找到具体的元素,这里compatible是"rockchip,rk3399-edp",在rk3399.dtsi中定义
malloc(sizeof(*s)); //display相关信息都放在struct display_state *s中
fdt_get_string(blob, child, "logo,uboot", &s->ulogo_name); //分别获取uboot/kernel中的logo name以及模式
fdt_get_string(blob, child, "logo,kernel", &s->klogo_name);
fdt_get_string(blob, child, "logo,mode", &name);
connector_phy_init //无phy node,3368平台需要配置。
connector_panel_init ->
get_panel_node //获取edp panel node
rockchip_get_panel //根据panel node从g_panel数组中找到具体型号panel,因此要添加一块新panel,那么对应timing信息需要添加到此数组中
connector_pclist_parse_dt //解析电源控制节点power_ctr,即lcd的enable以及reset gpio.
rockchip_panel_init ->
panel->funcs->init ->
panel_simple_init ->
panel_simple_parse_dt -> //此函数参数解析针对mipi屏
gpio_direction_output(enable_gpio->gpio, !!(enable_gpio->flags & OF_GPIO_ACTIVE_LOW)); //初始化之前先关屏
rk_pwm_bl_config(0); //关背光
3.
3. rockchip_show_logo();
list_for_each_entry(s, &rockchip_display_list, head) {
s->logo.mode = s->logo_mode;
if (load_bmp_logo(&s->logo, s->ulogo_name))//获取图片,提取bpp、width、height这些信息
printf("failed to display uboot logo\n");
else
display_logo(s);//display_logo
if (load_bmp_logo(&s->logo, s->klogo_name))
printf("failed to display kernel logo\n");
}
display_logo(s);//display_logo
........
display_init(state);
display_get_timing(state);
printf("Using display timing dts\n");
........
display_set_plane(state);
display_enable(state);
4.
4. lcd_standby(0);//使能
if (enable == 0) {
rk32_dsi_enable();
5.
5. rk_pwm_bl_config(-1);//背光
6.修改:找一张bmp格式的图片,替换kernel下的logo.bmp图片即可
第二部分:开机动画(没测试过)
https://blog.csdn.net/liuyingyanhuo/article/details/81567150
参考文章:https://blog.csdn.net/ooonebook/article/details/53206623(uboot阶段对dts的处理 fdt_xxx_xxx等函数说明)