uboot阶段 logo.bmp 可以正常显示,并且持续到 logo_kernel.bmp开始显示那一刻, 但是logo_kernel.bmp 虽然能显示,但是一闪而过,之后屏幕就持续黑屏直到显示桌面内容……
[
4.212505
] ##################show_loader_logo#######################
[
4.262751] ############fb_find_logo depth =
24
#############
[
4.262751
] Freeing drm_logo memory: 3348K
[
4.325082] Console: switching to colour frame buffer device 10
0x80
[
4.375269] rockchip-drm display-subsystem: fb0: frame buffer device
发现drm memory被free,查看 show_loader_logo 函数
struct drm_atomic_state *state, *old_state;
struct device_node *np = drm_dev->dev->of_node;
struct drm_mode_config *mode_config = &drm_dev->mode_config;
struct device_node *root, *route;
struct rockchip_drm_mode_set *set, *tmp, *unset;
struct list_head mode_set_list;
struct list_head mode_unset_list;
unsigned plane_mask = 0;
int ret;
printk("##################%s#######################\r\n",__func__);
root = of_get_child_by_name(np, "route");
if (!root) {
dev_warn(drm_dev->dev, "failed to parse display resources\n");
return;
}
if (init_loader_memory(drm_dev)) {
dev_warn(drm_dev->dev, "failed to parse loader memory\n");
return;
}
INIT_LIST_HEAD(&mode_set_list);
INIT_LIST_HEAD(&mode_unset_list);
drm_modeset_lock_all(drm_dev);
state = drm_atomic_state_alloc(drm_dev);
if (!state) {
dev_err(drm_dev->dev, "failed to alloc atomic state\n");
ret = -ENOMEM;
goto err_unlock;
}
state->acquire_ctx = mode_config->acquire_ctx;
for_each_child_of_node(root, route) {
if (!of_device_is_available(route))
continue;
set = of_parse_display_resource(drm_dev, route);
if (!set)
continue;
if (setup_initial_state(drm_dev, state, set)) {
drm_framebuffer_unreference(set->fb);
INIT_LIST_HEAD(&set->head);
list_add_tail(&set->head, &mode_unset_list);
continue;
}
INIT_LIST_HEAD(&set->head);
list_add_tail(&set->head, &mode_set_list);
}
/*
* the mode_unset_list store the unconnected route, if route's crtc
* isn't used, we should close it.
*/
list_for_each_entry_safe(unset, tmp, &mode_unset_list, head) {
struct rockchip_drm_mode_set *tmp_set;
int found_used_crtc = 0;
list_for_each_entry_safe(set, tmp_set, &mode_set_list, head) {
if (set->crtc == unset->crtc) {
printk("############found 1 used crtc###########\r\n");
found_used_crtc = 1;
continue;
}
}
if (!found_used_crtc) {
struct drm_crtc *crtc = unset->crtc;
int pipe = drm_crtc_index(crtc);
struct rockchip_drm_private *priv =
drm_dev->dev_private;
if (unset->hdisplay && unset->vdisplay){
printk("############close the unused crtc###########\r\n");
priv->crtc_funcs[pipe]->crtc_close(crtc);
}
}
list_del(&unset->head);
kfree(unset);
}
if (list_empty(&mode_set_list)) {
dev_warn(drm_dev->dev, "can't not find any loader display\n");
ret = -ENXIO;
goto err_free_state;
}
/*
* The state save initial devices status, swap the state into
* drm deivces as old state, so if new state come, can compare
* with this state to judge which status need to update.
*/
drm_atomic_helper_swap_state(drm_dev, state);
drm_atomic_state_free(state);
old_state = drm_atomic_helper_duplicate_state(drm_dev,
mode_config->acquire_ctx);
if (IS_ERR(old_state)) {
dev_err(drm_dev->dev, "failed to duplicate atomic state\n");
ret = PTR_ERR_OR_ZERO(old_state);
goto err_free_state;
}
state = drm_atomic_helper_duplicate_state(drm_dev,
mode_config->acquire_ctx);
if (IS_ERR(state)) {
dev_err(drm_dev->dev, "failed to duplicate atomic state\n");
ret = PTR_ERR_OR_ZERO(state);
goto err_free_old_state;
}
state->acquire_ctx = mode_config->acquire_ctx;
list_for_each_entry(set, &mode_set_list, head)
/*
* We don't want to see any fail on update_state.
*/
WARN_ON(update_state(drm_dev, state, set, &plane_mask));
ret = drm_atomic_commit(state);
drm_atomic_clean_old_fb(drm_dev, plane_mask, ret);
list_for_each_entry_safe(set, tmp, &mode_set_list, head) {
list_del(&set->head);
kfree(set);
}
/*
* Is possible get deadlock here?
*/
WARN_ON(ret == -EDEADLK);
if (ret) {
/*
* restore display status if atomic commit failed.
*/
drm_atomic_helper_swap_state(drm_dev, old_state);
goto err_free_old_state;
}
// rockchip_free_loader_memory(drm_dev);
// drm_atomic_state_free(old_state);
drm_modeset_unlock_all(drm_dev);
return;
err_free_old_state:
drm_atomic_state_free(old_state);
err_free_state:
drm_atomic_state_free(state);
err_unlock:
drm_modeset_unlock_all(drm_dev);
if (ret)
dev_err(drm_dev->dev, "failed to show loader logo\n");
rockchip_free_loader_memory(drm_dev);
}
大致的意思是有个备份区存储上个framebuffer内容,如果之后重新分配并且填充了frambuffer则更新备份区内容,也就是显示屏显示内容会更新……
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_kms_helper_poll_fini;
drm_for_each_crtc(crtc, drm_dev) {
struct drm_fb_helper *helper = private->fbdev_helper;
struct rockchip_crtc_state *s = NULL;
if (!helper)
break;
s = to_rockchip_crtc_state(crtc->state);
//#ifndef MODULE
if (is_support_hotplug(s->output_type)) {
s->crtc_primary_fb = crtc->primary->fb;
crtc->primary->fb = helper->fb;
drm_framebuffer_reference(helper->fb);
}
//#endif
}
drm_dev->mode_config.allow_fb_modifiers = true;
RK官方也提供了不少解决方案,但对于我这个现象不适用;这个问题的根源应该是RK希望配置linux内核里面 logo.c 文件里面指定的内核图片显示,但是这会影响到 kernel目录下 logo_kernel.bmp文件的显示,如果不按如上步骤操作, 在logo.c文件内把 fb_logo_late_init 函数里面的 logos_freed 设为false, 则会显示 logo.c 指定的图片,我的版本是几只企鹅…… 启动过程的现象就是:uboot阶段显示logo.bmp正常,接着logo_kernel.bmp一闪而过,接着显示企鹅画面直到进入桌面……