rk3399 startup log_kernel fleeting problem

Environment: rk3399 linux SDK linux kernel version 4.4.179 uboot version 201709

Symptoms:

  uboot stage logo.bmp can be normal, and continued to logo_kernel.bmp beginning to show the moment, but logo_kernel.bmp although able to show, however fleeting, a black screen after screen to continue until the desktop content ......

 

  Troubleshooting:

  View startup log:

  

[    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 100x80
[    4.375269] rockchip-drm display-subsystem: fb0:  frame buffer device

  I found drm memory is free, see show_loader_logo function

  

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");
		K = -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");
		K = -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);

}


  Generally means that there is a backup storage area on a framebuffer content, and reassigned after filling If the contents of the backup frambuffer area is updated, that is, the display shows the contents will be updated ......

  Prohibit start-up phase fb update can solve the core problem of fleeting images:

  

RK government has also provided a lot of solutions, but for me, this phenomenon does not apply; root of the problem should be the RK for compatibility framebuffer old mechanism, if the configuration file inside the linux kernel inside logo.c specified kernel image shows, but this logo_kernel.bmp will affect the display files in the kernel directory, if you do not follow the above steps in logo.c file to fb_logo_late_init function inside logos_freed set to false, logo.c specified picture is displayed, my version is phenomenon a few penguins ...... startup process is: uboot stage show logo.bmp normal, then logo_kernel.bmp flash, then the display screen until the penguin into the desktop ...... 

Official guidance document attached:

 

 

 

 

Guess you like

Origin www.cnblogs.com/weishengzhong/p/12050400.html