mipi分析调试

如标题所说,居然在网上找不到人分析过mipi lcd驱动,表示很无奈,话说这些接口协议讲道理已经出来很久了,但是依然没人写过相应的文章去分析,大部分文章都是转载抄袭,觉得很没意思,连参考的文章都没有,更多的文章是写的怎么调试

现在只有自己去分析 ,猜测这个drm下面的应该和以前在2440上面搞得lcd驱动总的流程应该都差不多,当然这个是我的猜想,等我搞清楚了才完整记录,hahahaha 水贴

Boot阶段

 

#Boot ver: 2018-11-18#1.09
empty serial no.
normal boot.
checkKey
vbus = 1
no fuel gauge found								power_rockchip.c(uboot)
no fuel gauge found
read logo on state from dts [1]					fastboot.c(uboot)
no fuel gauge found
Using display timing dts						rockchip_display.c(uboot)
Detailed mode clock 100000 kHz, flags[a]		rockchip_display.c(uboot)
    H: 1200 1260 1262 1342
    V: 1920 1934 1937 1947
bus_format: 100e								rockchip_display.c(uboot)
rk lcdc - 0 dclk set: dclk = 100000000HZ, pll select = 1, div = 1	clock-rk3399.c(uboot)
rockchip_phy_power_on: failed to find phy power on funcs	rockchip_phy.c(uboot)
final DSI-Link bandwidth: 750 Mbps x 4			rockchip-dw-mipi-dsi.c(uboot)

				read logo on state from dts [1]					fastboot.c(uboot)
					void board_fbt_preboot(void)
						#if defined(CONFIG_LCD) || defined(CONFIG_ROCKCHIP_DISPLAY)
						if (gd->fdt_blob) {
							if (g_logo_on_state != 0) {
									lcd_enable_logo(true);
									drv_lcd_init();
										lcd_base = map_sysmem(gd->fb_base, 0);

										lcd_init(lcd_base);
											/* Initialize the lcd controller */
											debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);

											lcd_ctrl_init(lcdbase);
								}
						gd->uboot_logo = g_logo_on_state;
						printf("read logo on state from dts [%d]\n", g_logo_on_state);





				common/lcd.c:657:	return show_resource_image(file_path) ? 0 : -1;
				common/cmd_charge.c:529:	return show_resource_image(path);

				Using display timing dts						rockchip_display.c(uboot)
				Detailed mode clock 100000 kHz, flags[a]		rockchip_display.c(uboot)
					H: 1200 1260 1262 1342
					V: 1920 1934 1937 1947
				bus_format: 100e	


					U_BOOT_CMD(
						cls,	1,	1,	do_lcd_clear,
						"clear screen",
						""
					);
					static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc,
						lcd_clear();
							if (lcd_show_logo)
								debug("[LCD] Drawing the logo...\n");
								lcd_console_address = lcd_logo();
									bitmap_plot((panel_info.vl_col - BMP_LOGO_WIDTH)/2, (panel_info.vl_row - BMP_LOGO_HEIGHT)/2);
										rk_bitmap_from_resource((unsigned short*)fb)
											const char* file_path = "logo.bmp";
											return show_resource_image(file_path) ? 0 : -1;
												if (g_is_new_display)
													return rockchip_show_bmp(image_path);
														display_logo(s);
															display_init(state);
																ret = display_get_timing(state);
																	if (!display_get_timing_from_dts(panel, blob, mode)) {
																		printf("Using display timing dts\n");
																			static int display_get_timing_from_dts(int panel, const void *blob,struct drm_display_mode *mode)
																			{
																				int timing, phandle, native_mode;
																				int hactive, vactive, pixelclock;
																				int hfront_porch, hback_porch, hsync_len;
																				int vfront_porch, vback_porch, vsync_len;
																				int val, flags = 0;

																				timing = fdt_subnode_offset(blob, panel, "display-timings");
																				if (timing < 0)
																					return -ENODEV;

																				native_mode = fdt_subnode_offset(blob, timing, "timing");
																				if (native_mode < 0) {
																					phandle = fdt_getprop_u32_default_node(blob, timing, 0,
																										   "native-mode", -1);
																					native_mode = fdt_node_offset_by_phandle_node(blob, timing, phandle);
																					if (native_mode <= 0) {
																						printf("failed to get display timings from DT\n");
																						return -ENXIO;
																					}
																				}

																			#define FDT_GET_INT(val, name) \
																				val = fdtdec_get_int(blob, native_mode, name, -1); \
																				if (val < 0) { \
																					printf("Can't get %s\n", name); \
																					return -ENXIO; \
																				}

																				FDT_GET_INT(hactive, "hactive");
																				FDT_GET_INT(vactive, "vactive");
																				FDT_GET_INT(pixelclock, "clock-frequency");
																				FDT_GET_INT(hsync_len, "hsync-len");
																				FDT_GET_INT(hfront_porch, "hfront-porch");
																				FDT_GET_INT(hback_porch, "hback-porch");
																				FDT_GET_INT(vsync_len, "vsync-len");
																				FDT_GET_INT(vfront_porch, "vfront-porch");
																				FDT_GET_INT(vback_porch, "vback-porch");
																				FDT_GET_INT(val, "hsync-active");
																				flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
																				FDT_GET_INT(val, "vsync-active");
																				flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;

																				mode->hdisplay = hactive;
																				mode->hsync_start = mode->hdisplay + hfront_porch;
																				mode->hsync_end = mode->hsync_start + hsync_len;
																				mode->htotal = mode->hsync_end + hback_porch;

																				mode->vdisplay = vactive;
																				mode->vsync_start = mode->vdisplay + vfront_porch;
																				mode->vsync_end = mode->vsync_start + vsync_len;
																				mode->vtotal = mode->vsync_end + vback_porch;

																				mode->clock = pixelclock / 1000;
																				mode->flags = flags;

																				return 0;
																			}
																		goto done;
																		printf("Detailed mode clock %u kHz, flags[%x]\n"
																	   "    H: %04d %04d %04d %04d\n"
																	   "    V: %04d %04d %04d %04d\n"
																	   "bus_format: %x\n",
																	   mode->clock, mode->flags,
																	   mode->hdisplay, mode->hsync_start,
																	   mode->hsync_end, mode->htotal,
																	   mode->vdisplay, mode->vsync_start,
																	   mode->vsync_end, mode->vtotal,
																	   conn_state->bus_format);
																		
				board/rockchip/common/rkboot/fastboot.c:519:				drv_lcd_init();
				common/stdio.c:257:	drv_lcd_init ();
															

				arch/arm/lib/board.c:707:	board_late_init();
				void board_init_r(gd_t *id, ulong dest_addr)
					board_late_init();
				common/board_r.c:859:	board_late_init,
				init_sequence_r[]
					board_late_init,
						
						
				rk lcdc - 0 dclk set: dclk = 100000000HZ, pll select = 1, div = 1

				void board_init_r(gd_t *id, ulong dest_addr)
					board_late_init();
						board/rockchip/rk33xx/rk33xx.c:238:	board_fbt_preboot();
						board_fbt_preboot
							if (g_logo_on_state != 0) 
								lcd_enable_logo(true);
								drv_lcd_init();
									lcd_init(lcd_base);	
										common/lcd.c:547:	lcd_ctrl_init(lcdbase);
										void lcd_ctrl_init(void *lcdbase)  //rockchip_fb.c
											int ret = rk_fb_parse_dt(fb, gd->fdt_blob);//获取dts里边的参数
											panel_info.real_freq = rkclk_lcdc_clk_set(panel_info.lcdc_id,panel_info.vl_freq);
												rkclk_lcdc_aclk_set(lcdc_id, VIO_ACLK_MAX);
												rkclk_lcdc_hclk_set(lcdc_id, VIO_HCLK_MAX);
												dclk_info = rkclk_lcdc_dclk_set(lcdc_id, dclk_hz);
													printf("rk lcdc - %d dclk set: dclk = %dHZ, pll select = %d, div = %d\n", lcdc_id, dclk_hz, pll_sel, div);




				const struct rockchip_connector_funcs rockchip_dw_mipi_dsi_funcs = {
					.init = rockchip_dw_mipi_dsi_init,
					.deinit = rockchip_dw_mipi_dsi_deinit,
					.prepare = rockchip_dw_mipi_dsi_prepare,
					.enable = rockchip_dw_mipi_dsi_enable,
					.disable = rockchip_dw_mipi_dsi_disable,
					.transfer = rockchip_dw_mipi_dsi_transfer,
				};

				rockchip_dw_mipi_dsi_prepare
					rockchip_dsi_grf_config(pdata, dsi, crtc_state->crtc_id);

					rockchip_dw_dsi_pre_init(state, dsi);
						if (dsi->slave)
							rockchip_dw_dsi_pre_init(state, dsi->slave);
								printf("final DSI-Link bandwidth: %u Mbps x %d\n",
								   dsi->lane_mbps, dsi->lanes);
					rockchip_dw_dsi_controller_init(dsi);
Starting kernel ...
[    1.432697] [drm:drm_core_init] Initialized drm 1.1.0 20060810
[    1.435926] init panel
[    1.436837] register ok
[    1.437096] dts get ok 
[    1.437105] 1111122222222222222222222222222222222222111111111111111111111111[24;80H[24;80H
[    1.437134] register mipi dsi ok
Initialized drm 1.1.0 20060810
module_init(drm_core_init);
	static int __init drm_core_init(void)
		
		DRM_INFO("Initialized %s %d.%d.%d %s\n",CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);

gpu/drm/tegra/dsi.c:1433:	.attach = tegra_dsi_host_attach,
gpu/drm/drm_prime.c:323:	.attach = drm_gem_map_attach,
gpu/drm/udl/udl_dmabuf.c:190:	.attach			= udl_attach_dma_buf,

gpu/drm/rockchip/dw-mipi-dsi.c:796:	.attach = dw_mipi_dsi_host_attach,

gpu/drm/msm/dsi/dsi_host.c:1342:	.attach = dsi_host_attach,
gpu/drm/msm/msm_iommu.c:120:		.attach = msm_iommu_attach,

drivers/gpu/drm/drm_fb_helper.c:1461:	if (register_framebuffer(info) < 0)

drivers/gpu/drm/drm_fb_cma_helper.c:354:	ret = drm_fb_helper_initial_config(helper, preferred_bpp);

drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c:180:	ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
int rockchip_drm_fbdev_init(struct drm_device *dev)
	ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
	
drivers/gpu/drm/rockchip/rockchip_drm_drv.c:1310:	ret = rockchip_drm_fbdev_init(drm_dev);
rk3399.dtsi:2040:		compatible = "rockchip,display-subsystem";//内核能匹配上的
static int rockchip_drm_bind(struct device *dev)
	ret = rockchip_drm_fbdev_init(drm_dev);

dw-mipi-dsi.c

module_platform_driver(dw_mipi_dsi_driver);
	dw_mipi_dsi_probe
		dsi_id = of_alias_get_id(np, "dsi");
		dsi->id = dsi_id;
		dsi->dev = dev;
		dsi->pdata = of_device_get_match_data(dev);
		platform_set_drvdata(pdev, dsi);
		dsi->base = devm_ioremap_resource(dev, res);
		dsi->pclk = devm_clk_get(dev, "pclk");
		ret = mipi_dphy_attach(dsi);
			dsi->dphy.phy = devm_phy_optional_get(dev, "mipi_dphy");
		dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
			static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = {
				.attach = dw_mipi_dsi_host_attach,//.attach = dw_mipi_dsi_host_attach,
					dsi->lanes = device->lanes;
					dsi->channel = device->channel;
					dsi->format = device->format;
					dsi->mode_flags = device->mode_flags;

					dsi->panel = of_drm_find_panel(device->dev.of_node);
				.detach = dw_mipi_dsi_host_detach,
				.transfer = dw_mipi_dsi_host_transfer,
			};
		dsi->dsi_host.dev = dev;

		ret = mipi_dsi_host_register(&dsi->dsi_host);//mipi_dsi_host_register
		ret = component_add(dev, &dw_mipi_dsi_ops);//component_add  dw_mipi_dsi_ops
			static const struct component_ops dw_mipi_dsi_ops = {
				.bind	= dw_mipi_dsi_bind,
					ret = rockchip_dsi_dual_channel_probe(dsi);
					ret = dw_mipi_dsi_register(drm, dsi);
						drm_encoder_helper_add(&dsi->encoder,&dw_mipi_dsi_encoder_helper_funcs);//drm_encoder_helper_add
							dw_mipi_dsi_encoder_helper_funcs = {
								.mode_fixup = dw_mipi_dsi_encoder_mode_fixup,
								.mode_set = dw_mipi_dsi_encoder_mode_set,
								.enable = dw_mipi_dsi_encoder_enable,
								.disable = dw_mipi_dsi_encoder_disable,
								.atomic_check = dw_mipi_dsi_encoder_atomic_check,
							};
						ret = drm_encoder_init(drm, &dsi->encoder, &dw_mipi_dsi_encoder_funcs,DRM_MODE_ENCODER_DSI, NULL);
							encoder->dev = dev;
							encoder->encoder_type = encoder_type;
							encoder->funcs = funcs;
							encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
										  drm_encoder_enum_list[encoder_type].name,
										  encoder->base.id);
							list_add_tail(&encoder->head, &dev->mode_config.encoder_list);//list_add_tail encoder
							dev->mode_config.num_encoder++;
						drm_connector_helper_add(connector,&dw_mipi_dsi_connector_helper_funcs);//drm_connector_helper_add
						drm_panel_attach(dsi->panel, &dsi->connector);
							panel->connector = connector;
							panel->drm = connector->dev;
						drm_mode_connector_attach_encoder(connector, encoder);
				.unbind	= dw_mipi_dsi_unbind,
			};
			component = kzalloc(sizeof(*component), GFP_KERNEL);
			component->ops = ops;
			component->dev = dev;
			list_add_tail(&component->node, &component_list);//list_add_tail component
			ret = try_to_bring_up_masters(component);
				list_for_each_entry(m, &masters, node) {
				ret = try_to_bring_up_master(m, component);
					if (master->bound)
						return 0;

					/*
					 * Search the list of components, looking for components that
					 * belong to this master, and attach them to the master.
					 */
					if (find_components(master)) 
						..........
					/* Found all components */
					ret = master->ops->bind(master->dev);//dw_mipi_dsi_bind
					master->bound = true;
				if (ret != 0)
					break;
dw_mipi_dsi_bind//dw_mipi_dsi_bind
						ret = dw_mipi_dsi_register(drm, dsi);		
							drm_connector_helper_add(connector,&dw_mipi_dsi_connector_helper_funcs);
									
								static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = {
									.loader_protect = dw_mipi_loader_protect,
									.get_modes = dw_mipi_dsi_connector_get_modes,//dw_mipi_dsi_connector_get_modes
									.mode_valid = dw_mipi_dsi_mode_valid,
									.best_encoder = dw_mipi_dsi_connector_best_encoder,
								};		
								dw_mipi_dsi_connector_get_modes//dw_mipi_dsi_connector_get_modes
									return drm_panel_get_modes(dsi->panel);	
										return panel->funcs->get_modes(panel);//获取屏幕参数
		
								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,//panel_simple_get_modes
									.get_timings = panel_simple_get_timings,
								};		
										
								panel_simple_get_modes		//panel_simple_get_modes
									num += panel_simple_of_get_native_mode(p);		
										ret = of_get_drm_display_mode(panel->dev->of_node, mode,OF_USE_NATIVE_MODE);		//drivers/gpu/drm/drm_modes.c:672:int of_get_drm_display_mode(s
											ret = of_get_videomode(np, &vm, index);//of_videomode.c
												of_get_display_timings//drivers/video/of_display_timing.c:190:struct
													r = of_parse_display_timing(entry, dt);
														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);
													disp->timings[disp->num_timings] = dt;
													disp->num_timings++;//存起来
												ret = videomode_from_timings(disp, vm, index);//drivers/video/videomode.c:32:
													dt = display_timings_get(disp, index);
														if (disp->num_timings > index)//返回index下标的timing
															return disp->timings[index];
													videomode_from_timing(dt, vm);//把dt里相应的赋给vm
														vm->pixelclock = dt->pixelclock.typ;
														vm->hactive = dt->hactive.typ;
														vm->hfront_porch = dt->hfront_porch.typ;
														vm->hback_porch = dt->hback_porch.typ;
														vm->hsync_len = dt->hsync_len.typ;

														vm->vactive = dt->vactive.typ;
														vm->vfront_porch = dt->vfront_porch.typ;
														vm->vback_porch = dt->vback_porch.typ;
														vm->vsync_len = dt->vsync_len.typ;

														vm->flags = dt->flags;
											drm_display_mode_from_videomode(&vm, dmode);		
												dmode->hdisplay = vm->hactive;
												dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
												dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
												dmode->htotal = dmode->hsync_end + vm->hback_porch;

												dmode->vdisplay = vm->vactive;
												dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
												dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
												dmode->vtotal = dmode->vsync_end + vm->vback_porch;

												dmode->clock = vm->pixelclock / 1000;	
													
										drm_mode_probed_add(connector, mode);
											list_add_tail(&mode->head, &connector->probed_modes);//list_add_tail mode
											

panel-simple.c

	panel_simple_dsi_probe
			.......
		panel_simple_probe
			.........
			if (!of_property_read_u32(dev->of_node, "bus-format", &val))
				of_desc->bus_format = val;
			if (!of_property_read_u32(dev->of_node, "prepare-delay-ms", &val))
				of_desc->delay.prepare = val;
			if (!of_property_read_u32(dev->of_node, "enable-delay-ms", &val))
				of_desc->delay.enable = val;
			if (!of_property_read_u32(dev->of_node, "disable-delay-ms", &val))
			.........
			panel->supply = devm_regulator_get(dev, "power");
			panel->enable_gpio = devm_gpiod_get_optional(dev, "enable", 0);
			panel->reset_gpio = devm_gpiod_get_optional(dev, "reset", 0);
			.........
			drm_panel_init(&panel->base);
			panel->base.dev = dev;
			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,
						panel_simple_prepare
							panel_simple_dsi_send_cmds
					.enable = panel_simple_enable,
					.get_modes = panel_simple_get_modes,
					.get_timings = panel_simple_get_timings,
				};
			err = drm_panel_add(&panel->base);
			list_add_tail(&panel->list, &panel_list);//list_add_tail panel
		panel = dev_get_drvdata(&dsi->dev);
		panel->dsi = dsi;	
		
		if (!of_property_read_u32(dsi->dev.of_node, "dsi,flags", &val))
			dsi->mode_flags = val;

		if (!of_property_read_u32(dsi->dev.of_node, "dsi,format", &val))
			dsi->format = val;

		if (!of_property_read_u32(dsi->dev.of_node, "dsi,lanes", &val))
			dsi->lanes = val;

		data = of_get_property(dsi->dev.of_node, "panel-init-sequence", &len);
		data = of_get_property(dsi->dev.of_node, "panel-exit-sequence", &len);
		return mipi_dsi_attach(dsi);
			const struct mipi_dsi_host_ops *ops = dsi->host->ops;
			return ops->attach(dsi->host, dsi);//dw-mipi-dsi.c
				.attach = dw_mipi_dsi_host_attach,
					dsi->lanes = device->lanes;
					dsi->channel = device->channel;
					dsi->format = device->format;
					dsi->mode_flags = device->mode_flags;

					dsi->panel = of_drm_find_panel(device->dev.of_node);

rockchip-drm-drv.c

static int rockchip_drm_platform_probe(struct platform_device *pdev)    ->rockchip-drm-drv.c
	return component_master_add_with_match(dev, &rockchip_drm_ops, match);
		ret = try_to_bring_up_master(master, NULL);
			ret = master->ops->bind(master->dev);
			static const struct component_master_ops rockchip_drm_ops = {
				.bind = rockchip_drm_bind,
				.unbind = rockchip_drm_unbind,
			};
			rockchip_drm_bind
				drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
				
				ret = rockchip_drm_fbdev_init(drm_dev);//rockchip_drm_fbdev.c
					drm_fb_helper_prepare(dev, helper, &rockchip_drm_fb_helper_funcs);
					ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
						return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
							/* push down into drivers */
							ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);//fb_probe   分配framebuffer
							info = fb_helper->fbdev;
							if (register_framebuffer(info) < 0)//register_framebuffer
							............	
							dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",info->node, info->fix.id);
							............
							list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
					//fb_probe
					static const struct drm_fb_helper_funcs rockchip_drm_fb_helper_funcs = {
						..........
						.fb_probe = rockchip_drm_fbdev_create,
					};
						static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,struct drm_fb_helper_surface_size *sizes)
							fbi = drm_fb_helper_alloc_fbi(helper);//分配framebuffer
								info = framebuffer_alloc(0, dev);//framebuffer_alloc
							helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd,private->fbdev_bo);
								fb = rockchip_fb_alloc(dev, mode_cmd, &obj, NULL, 1);
									ret = drm_framebuffer_init(dev, &rockchip_fb->fb,&rockchip_drm_fb_funcs);
										dev->mode_config.num_fb++;
										list_add(&fb->head, &dev->mode_config.fb_list);//加到链表
							fbi->par = helper;
							fbi->flags = FBINFO_FLAG_DEFAULT;
							fbi->fbops = &rockchip_drm_fbdev_ops;

				ret = drm_dev_register(drm_dev, 0);




component:vop,edp
encoder:编码器,与component相关
CRTC:vopb,vopl
vop:lcd控制器

想想,可能大多数人对于驱动这块也就是持一种会改会用会移植的态度,所以分析的人很少,确实一般这种复杂的驱动一般不会有什么问题,总结一下调试一块1200*1920屏幕中遇到过的问题,

首先屏幕驱动是有的,主要是调试,调试过程中遇到的问题:

1.显示不正常,屏幕四等分,左下角那一块无显示(解决的方式:修改频率,不要太低不要太高,慢慢试)

2.休眠唤醒后显示不正常(频率问题)

3.切换画面闪屏(屏幕配置问题,初始化序列这一块要引起注意,屏厂提供)

4.搞了这么久,都是忽略了初始化序列这一块的问题,说来话长,到此为止

你可能感兴趣的:(Linux驱动,RK3399平台)