QC MSM平台显示屏Framebuffer设备注册过程

本文是Android Display部分分析的一部分,描述屏Framebuffer设备注册过程。

QC MSM7xxx/MSM8xxx平台本身就提供了很多接口的屏的支持,每种屏对应一个驱动文件。由于QC MSM平台显示驱动架构做了绝大部分的工作,驱动一块新的屏仅需要做很少量的工作。下面的过程是屏Framebuffer注册过程的分析。

设备资源申请是在MACHINE_DESC中实现的。示例如下:

3463MACHINE_START(MSM8930_CDP, "QCT MSM8930 CDP")3464	.map_io = msm8930_map_io,3465	.reserve = msm8930_reserve,3466	.init_irq = msm8930_init_irq,3467	.handle_irq = gic_handle_irq,3468	.timer = &msm_timer,3469	.init_machine = msm8930_cdp_init,3470	.init_early = msm8930_allocate_memory_regions,3471	.init_very_early = msm8930_early_memory,3472	.restart = msm_restart,3473MACHINE_END

machine_desc{.init_very_early, .init_early, .init_machine, .restart}, module_init driver的初始化顺序参考Machine_desc & boot & Kernel_init & initcall & module_init
在machine_desc.init中做了许多machine级别设备的注册工作,主要意图是做设备资源分配。该.init函数部分示例代码如下:

static void __init msm8930_cdp_init(void) @ kernel/arch/arm/mach-msm/board-8930.c{    …platform_add_devices(common_devices, ARRAY_SIZE(common_devices));	msm8930_init_gpu();    	msm8930_init_mmc();	msm8930_init_cam();	msm8930_init_fb();}

其中,msm8930_cdp_init中与display相关的是msm8930_init_fb()函数,这个函数注册了几个id为0的设备。各主要设备名如下,

“msm_fb” msm framebuffer设备,注意不是linux framebuffer设备,但是有对应关系;

“wfd” wifi显示设备;

“mipi_dsi_cmd_samsung_fwvga”  mipi-dsi接口cmd模式LCD屏设备;

“hdmi_msm” HDMI显示器设备;

“mdp” mobile display station显示引擎设备;

“mipi-dsi” MIPI-DSI显示器驱动设备(id例外用了1,可能有的平台两个MIPI-DSI,另外一个id为0);

1168void __init msm8930_init_fb(void) @ kernel/arch/arm/mach-msm/board-8930-display.c1169{1170	platform_device_register(&msm_fb_device);11711172#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL1173	platform_device_register(&wfd_panel_device);1174	platform_device_register(&wfd_device);1175#endif11761178#ifdef CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT1179	platform_device_register(&mipi_dsi_novatek_panel_device);1180#endif11811184#ifdef CONFIG_FB_MSM_MIPI_SA77_CMD_FWVGA_PANEL1185	platform_device_register(&mipi_dsi_cmd_chimei_fwvga_panel_device);1186	platform_device_register(&mipi_dsi_cmd_samsung_fwvga_panel_device);1187#endif11891190#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL1191	platform_device_register(&hdmi_msm_device);1192#endif11931194	platform_device_register(&mipi_dsi_toshiba_panel_device);11951196	msm_fb_register_device("mdp", &mdp_pdata);1197	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);1198#ifdef CONFIG_MSM_BUS_SCALING1199#ifdef CONFIG_FB_MSM_DTV 1200	msm_fb_register_device("dtv", &dtv_pdata);1201#endif 1202#endif1203}

因为注册这些设备的意图主要是资源申请和初步初始化设备,所以各设备注册顺序并无关紧要。其初始化顺序还与后来的驱动实际注册顺序有关。

 

首先注册paltform_device msm_fb_device,该设备定义如下:

71static struct resource msm_fb_resources[] = {72	{73		.flags = IORESOURCE_DMA,74	}75}; 135static struct msm_fb_platform_data msm_fb_pdata = http://blog.csdn.net/zirconsdu/article/details/{136	.detect_client = msm_fb_detect_panel,137};138139static struct platform_device msm_fb_device = {140	.name   = "msm_fb",141	.id     = 0,142	.num_resources     = ARRAY_SIZE(msm_fb_resources),143	.resource          = msm_fb_resources,144	.dev.platform_data = &msm_fb_pdata,145};

然后注册panel设备,定义如下:

845static struct mipi_dsi_panel_platform_data samsung_pdata = http://blog.csdn.net/zirconsdu/article/details/{846	.enable_wled_bl_ctrl = 0x1,847};848849static struct platform_device mipi_dsi_cmd_samsung_fwvga_panel_device = {850	.name = "dsi_cmd_samsung_fwvga",851	.id = 0,852	.dev = {853		.platform_data = &samsung_pdata,854	}855};

然后关键的注册mdp和mipi-dsi controller.

1749void __init msm_fb_register_device(char *name, void *data)1750{1751	if (!strncmp(name, "mdp", 3))1752		msm_register_device(&msm_mdp_device, data);1753	else if (!strncmp(name, "lcdc", 4))1754		msm_register_device(&msm_lcdc_device, data);1755	else if (!strncmp(name, "mipi_dsi", 8))1756		msm_register_device(&msm_mipi_dsi_device, data);1757#ifdef CONFIG_FB_MSM_TVOUT1758	else if (!strncmp(name, "tvenc", 5))1759		msm_register_device(&msm_tvenc_device, data);1760	else if (!strncmp(name, "tvout_device", 12))1761		msm_register_device(&msm_tvout_device, data);1762#endif1763#ifdef CONFIG_MSM_BUS_SCALING1764	else if (!strncmp(name, "dtv", 3))1765		msm_register_device(&msm_dtv_device, data);1766#endif1767	else1768		printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);1769}

mdp和mipi-dsi设备及寄存器映射和中断需求如下

1484#define MIPI_DSI_HW_BASE	0x047000001485#define ROTATOR_HW_BASE	0x04E000001486#define TVENC_HW_BASE		0x04F000001487#define MDP_HW_BASE		0x0510000014881489static struct resource msm_mipi_dsi_resources[] = {1490	{1491		.name   = "mipi_dsi",1492		.start  = MIPI_DSI_HW_BASE,1493		.end    = MIPI_DSI_HW_BASE + 0x000F0000 - 1,1494		.flags  = IORESOURCE_MEM,1495	},1496	{1497		.start  = DSI_IRQ,1498		.end    = DSI_IRQ,1499		.flags  = IORESOURCE_IRQ,1500	},1501};15021503static struct platform_device msm_mipi_dsi_device = {1504	.name   = "mipi_dsi",1505	.id     = 1,1506	.num_resources  = ARRAY_SIZE(msm_mipi_dsi_resources),1507	.resource       = msm_mipi_dsi_resources,1508};15091510static struct resource msm_mdp_resources[] = {1511	{1512		.name   = "mdp",1513		.start  = MDP_HW_BASE,1514		.end    = MDP_HW_BASE + 0x000F0000 - 1,1515		.flags  = IORESOURCE_MEM,1516	},1517	{1518		.start  = INT_MDP,1519		.end    = INT_MDP,1520		.flags  = IORESOURCE_IRQ,1521	},1522};15231524static struct platform_device msm_mdp_device = {1525	.name   = "mdp",1526	.id     = 0,1527	.num_resources  = ARRAY_SIZE(msm_mdp_resources),1528	.resource       = msm_mdp_resources,1529};

以上设备注册时,其驱动并未加载,因为machine_desc.init_machine设备注册的arch_initcall是在.initcall3.init中,而module_init driver注册是在.initcall6.init中。等其驱动加载时,在对应的probe函数中,判断设备id,初步初始化设备,保存其资源分配。

此时,以下设备中id为0,mipi-dsi id为1的设备已经注册进系统了。

dsi_cmd_chimei_fwvga.0

dsi_cmd_samsung_fwvga.0

dsi_cmd_samsung_fwvga.1281

dtv.0

dtv.458753

hdmi_msm.0

hdmi_msm.1

 

mdp.0

mdp.458753

mdp.591105

mdp.655361

mipi_dsi.1

mipi_dsi.591105

mipi_toshiba.0

 

msm_fb.0

msm_fb.458753

msm_fb.591105

msm_fb.655361


 

下面描述各驱动注册,各驱动都是module_init的。

msm_fb驱动注册如下

module_init(msm_fb_init);3898int __init msm_fb_init(void) @ kernel/drivers/video/msm/msm_fb.c3899{3900	int rc = -ENODEV;39013902	if (msm_fb_register_driver())3903		return rc;	….}3705static int msm_fb_register_driver(void)3706{3707	return platform_driver_register(&msm_fb_driver);3708}

msm_fb_driver驱动定义如下

734static struct platform_driver msm_fb_driver = {735	.probe = msm_fb_probe,736	.remove = msm_fb_remove,737#ifndef CONFIG_HAS_EARLYSUSPEND738	.suspend = msm_fb_suspend,739	.resume = msm_fb_resume,740#endif741	.shutdown = NULL,742	.driver = {743		   /* Driver name must match the device name added in platform.c. */744		   .name = "msm_fb",745		   .pm = &msm_fb_dev_pm_ops,746		   },747};

platform_device “msm_fb”的resource[0]是一块DMA内存,是framebuffer内存,但是在资源定义中并没有设置size,而在msm_fb_probe中从其使用可以看到该DMA内存已经分配。其size是在machine的init_early中从bootmem中分配的,比machine级别设备注册要早!

                .init_early = msm8930_allocate_memory_regions,

msm8930_allocate_memory_regions(void) @ kernel/arch/arm/mach-msm/board-8930.c

1006static void __init msm8930_allocate_memory_regions(void)1007{1008	msm8930_allocate_fb_region();1009}

msm8930_allocate_fb_region() @ kernel/arch/arm/mach-msm/board-8930-display.c

1205void __init msm8930_allocate_fb_region(void) 1206{1207	void *addr;1208	unsigned long size;12091210	size = MSM_FB_SIZE;1211	addr = alloc_bootmem_align(size, 0x1000);1212	msm_fb_resources[0].start = __pa(addr);1213	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;1214	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", size, addr, __pa(addr));1216}

MSM_FB_SIZE宏定义如下,TRIPLE_BUFFER已是主流;对应地SurfaceFlinger中FB layer也会分配有3个buffer。

32#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER33#define MSM_FB_PRIM_BUF_SIZE \34		(roundup((1920 * 1088 * 4), 4096) * 3) /* 4 bpp x 3 pages */35#else36#define MSM_FB_PRIM_BUF_SIZE \37		(roundup((1920 * 1088 * 4), 4096) * 2) /* 4 bpp x 2 pages */38#endif39/* Note: must be multiple of 4096 */40#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE, 4096)

当”msm_fb”注册时,msm_fb_probe在设备和驱动match后被调用。对于msm_fb_device id=0,只做fbram保存和ION client创建;这时probe到的设备对应/sys/bus/platform/devices /msm_fb.0。msm_ion_client_create(-1, pdev->name); ”mipi-dsi” driver定义和注册如下 (in kernel/drivers/video/msm/mipi_dsi.c)

55static struct platform_driver mipi_dsi_driver = {56	.probe = mipi_dsi_probe,57	.remove = mipi_dsi_remove,58	.shutdown = NULL,59	.driver = {60		   .name = "mipi_dsi",61		   },62};603static int mipi_dsi_register_driver(void)604{605	return platform_driver_register(&mipi_dsi_driver);606}607608static int __init mipi_dsi_driver_init(void)609{610	int ret;611612	mipi_dsi_init();613614	ret = mipi_dsi_register_driver();615616	device_initialize(&dsi_dev);617618	if (ret) {619		pr_err("mipi_dsi_register_driver() failed!\n");620		return ret;621	}622623	return ret;624}625626module_init(mipi_dsi_driver_init);

“mdp” driver定义和注册如下(in kernel/drivers/video/msm/mdp.c)

2094static struct platform_driver mdp_driver = {2095	.probe = mdp_probe,2096	.remove = mdp_remove,2097#ifndef CONFIG_HAS_EARLYSUSPEND2098	.suspend = mdp_suspend,2099	.resume = NULL,2100#endif2101	.shutdown = NULL,2102	.driver = {2103		/*2104		 * Driver name must match the device name added in2105		 * platform.c.2106		 */2107		.name = "mdp",2108		.pm = &mdp_dev_pm_ops,2109	},2110};3001static int mdp_register_driver(void)3002{3003#ifdef CONFIG_HAS_EARLYSUSPEND3004	early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;3005	early_suspend.suspend = mdp_early_suspend;3006	early_suspend.resume = mdp_early_resume;3007	register_early_suspend(&early_suspend);3008#endif30093010	return platform_driver_register(&mdp_driver);3011}30123013static int __init mdp_driver_init(void)3014{3015	int ret;30163017	mdp_drv_init();30183019	ret = mdp_register_driver();3020	if (ret) {3021		printk(KERN_ERR "mdp_register_driver() failed!\n");3022		return ret;3023	}30243025#if defined(CONFIG_DEBUG_FS)3026	mdp_debugfs_init();3027#endif30283029	return 0;30303031}30323033module_init(mdp_driver_init);

当真正从屏驱动中添加一块显示设备时,为了让上级设备(“mipi-dsi” “mdp” “msm_fb” “fb”)使用下级设备,高通实现为下级设备创建了每个上级设备的实例,通过从下到上的设备probe链一级一级向上注册。这时保证从下到上的设备注册顺序就是至关重要的了,probe链做注册来保证这一点。

当然为了达到上级设备使用和管理下级设备的目标,另一种方法是下级设备向上级设备做register,这时要保证下级设备向上级设备注册时,上级设备的用于管理的相关数据结构已经准备好。

下面描述由屏驱动添加屏到注册linux framebuffer设备的流程。

在各自的屏设备注册文件中,会去探测屏,这种探测不是做真正扫描,仅仅是使用设备名字验证一下,以SAMSUNG MIPI DSI CMD屏为例,驱动会使用相应规则ID注册一块屏。

static int __init mipi_cmd_samsung_fwvga_pt_init(void) @ kernel/drivers/video/msm/mipi_samsung_cmd_fwvga_pt.c{37	int ret;3839	if (msm_fb_detect_client("mipi_cmd_samsung_fwvga"))40		return 0;	……88	ret = mipi_samsung_device_register(&pinfo, MIPI_DSI_PRIM, MIPI_DSI_PANEL_QHD_PT);90	if (ret)91		pr_err("%s: failed to register device!\n", __func__);9293	return ret;94}9596module_init(mipi_cmd_samsung_fwvga_pt_init);

探测函数int msm_fb_detect_client(const char *name)首先使用主屏和外屏名字匹配,匹配不成则使用msm_fd_device.dev.platform .detect_client = msm_fb_detect_panel去匹配。上面欲同时注册SAMSUNG和CHIMEI两块屏设备,当然不能同时detect_panel成功,使用GPIO管脚配置做了二次匹配。实际不同批次的手机可能用到两块屏中的一种。

然后mipi_samsung_device_register()(对CHIMEI则是mipi_chimei_device_register)注册屏驱动和屏设备。驱动定义和注册具体如下,

358static struct platform_driver this_driver = {359	.probe  = mipi_samsung_lcd_probe,360	.driver = {361		.name   = "dsi_cmd_samsung_fwvga",362	},363};364365static struct msm_fb_panel_data samsung_panel_data = http://blog.csdn.net/zirconsdu/article/details/{366	.on		= mipi_samsung_lcd_on,367	.off		= mipi_samsung_lcd_off,368	.set_backlight = mipi_samsung_set_backlight,369};373int mipi_samsung_device_register(struct msm_panel_info *pinfo, u32 channel, u32 panel)375{376	struct platform_device *pdev = NULL;377	int ret;378379	if ((channel >= 3) || ch_used[channel])380		return -ENODEV;381382	ch_used[channel] = TRUE;383384	ret = mipi_samsung_lcd_init();385	if (ret) {386		pr_err("mipi_samsung_lcd_init() failed with ret %u/n", ret);387		return ret;388	}389390	pdev = platform_device_alloc("dsi_cmd_samsung_fwvga", (panel << 8)|channel);391	if (!pdev)392		return -ENOMEM;393394	samsung_panel_data.panel_info = *pinfo;395396	ret = platform_device_add_data(pdev, &samsung_panel_data,397		sizeof(samsung_panel_data));398	if (ret) {399		printk(KERN_ERR400		  "%s: platform_device_add_data failed!/n", __func__);401		goto err_device_put;402	}403404	ret = platform_device_add(pdev);405	if (ret) {406		printk(KERN_ERR407		  "%s: platform_device_register failed!/n", __func__);408		goto err_device_put;409	}410411	return 0;412413err_device_put:414	platform_device_put(pdev);415	return ret;416}417418static int mipi_samsung_lcd_init(void)419{420421	led_trigger_register_simple("bkl_trigger", &bkl_led_trigger);422	pr_info("%s: SUCCESS (WLED TRIGGER)/n", __func__);423	wled_trigger_initialized = 1;424425	mipi_dsi_buf_alloc(&samsung_tx_buf, DSI_BUF_SIZE);426	mipi_dsi_buf_alloc(&samsung_rx_buf, DSI_BUF_SIZE);427428	return platform_driver_register(&this_driver);429}

在mipi_samsung_lcd_init()中注册platform_driver屏驱动,然后分配注册platform_device屏设备;platform_data设置为msm_fb_panel_data向上传递参数并用于上级设备调用控制屏开关和背光。

屏设备注册后,platform_device和platform_driver match,驱动的probe函数被调用,把参数一级一级向上带,用于设置上级设备参数,向上一级一级注册设备(“mipi-dsi”, “mdp”, “msm_fb”, “framebuffer”)。

一个类似的调用栈如下

------------[ cut here ]------------WARNING: at /home/CORPUSERS/xp010548/myworkdroid/7x25a/LINUX/kernel/drivers/video/msm/msm_fb.c:1221 msm_fb_probe+0xf4/0xcbc()msm_fb_probeModules linked in: [<c003fe0c>] (unwind_backtrace+0x0/0x12c) from [<c00adccc>] (warn_slowpath_common+0x4c/0x64) [<c00adccc>] (warn_slowpath_common+0x4c/0x64) from [<c00add64>] (warn_slowpath_fmt+0x2c/0x3c) [<c00add64>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0223c44>] (msm_fb_probe+0xf4/0xcbc) [<c0223c44>] (msm_fb_probe+0xf4/0xcbc) from [<c026e624>] (platform_drv_probe+0x18/0x1c) [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264) [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84) [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0) [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40) [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570) [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0) [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02264b4>] (mdp_probe+0x828/0x940) [<c02264b4>] (mdp_probe+0x828/0x940) from [<c026e624>] (platform_drv_probe+0x18/0x1c) [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264) [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84) [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0) [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40) [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570) [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0) [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c023db98>] (mipi_dsi_probe+0x514/0x5d0) [<c023db98>] (mipi_dsi_probe+0x514/0x5d0) from [<c026e624>] (platform_drv_probe+0x18/0x1c) [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264) [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84) [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0) [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40) [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570) [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0) [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02223b8>] (msm_fb_add_device+0x150/0x1b4) [<c02223b8>] (msm_fb_add_device+0x150/0x1b4) from [<c051e830>] (mipi_himax_lcd_probe+0x38/0x108) [<c051e830>] (mipi_himax_lcd_probe+0x38/0x108) from [<c026e624>] (platform_drv_probe+0x18/0x1c) [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264) [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84) [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0) [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40) [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570) [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0) [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02409ec>] (mipi_himax_device_register+0x7c/0xc0) [<c02409ec>] (mipi_himax_device_register+0x7c/0xc0) from [<c001ac34>] (mipi_cmd_himax_hvga_pt_init+0x148/0x180) [<c001ac34>] (mipi_cmd_himax_hvga_pt_init+0x148/0x180) from [<c0034388>] (do_one_initcall+0x94/0x164) [<c0034388>] (do_one_initcall+0x94/0x164) from [<c00083d8>] (kernel_init+0x98/0x144) [<c00083d8>] (kernel_init+0x98/0x144) from [<c003b0d0>] (kernel_thread_exit+0x0/0x8)---[ end trace 65f8ea860415c051 ]---

下面考察设备probe链。

311static int __devinit mipi_samsung_lcd_probe(struct platform_device *pdev)312{	…..338	current_pdev = msm_fb_add_device(pdev);339340	if (current_pdev) {341		mfd = platform_get_drvdata(current_pdev);342		if (!mfd)343			return -ENODEV;344		if (mfd->key != MFD_KEY)345			return -EINVAL;346347		mipi  = &mfd->panel_info.mipi;348349		if (phy_settings != NULL)350			mipi->dsi_phy_db = phy_settings;351352		if (dlane_swap)353			mipi->dlane_swap = dlane_swap;354	}355	return 0;356}

msm_fb_add_device做如下事情:

调用struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata, u32 type, u32 id)函数分配platform_device “mipi-dsi.type_devid”并设置其platform_data为msm_fb_panel_data。

以额外msm_fb_data_type结构分配framebuffer。

注册”mipi-dsi”设备platform_device_add(this_dev)。

“mipi-dsi”设备和驱动进行attach, match后,“mipi-dsi” driver的probe被调用到。

static int mipi_dsi_probe(struct platform_device *pdev) @ kernel/drivers/video/msm/mipi_dsi.c做如下事情(这次的设备ID是真正实例的了,不是1了):

分配”mdp”设备实例并设置其数据,设置”mipi-dsi”设备操作函数,用于向下操作一级一级设备;

继续设置linux framebuffer的参数;

根据屏分辨率设置mipi-dsi工作频率;

注册该”mdp”设备实例;

“mdp”设备和驱动进行attach, match后,“mdp” driver的probe被调用到。

static int mdp_probe(struct platform_device *pdev) @ kernel/drivers/video/msm/mdp.c

分配”msm_fb”实例并设置其数据;

配置”mdp”工作模式;

注册”msm_fb”实例;

“msm_fb”设备和驱动进行attach, match后,“msm_fb” driver的probe被调用到。

static int msm_fb_probe(struct platform_device *pdev) @ kernel/drivers/video/msm/msm_fb.c

调用msm_fb_register设置linux framebuffer并register_framebuffer。

至此,系统中相关设备如下:

dsi_cmd_chimei_fwvga.0

dsi_cmd_samsung_fwvga.0

dsi_cmd_samsung_fwvga.1281 ->mipi_dsi.591105 -> mdp.591105 -> msm_fb.591105 -> fbx

dtv.0

dtv.458753 ->mdp.458753 -> msm_fb.458753  -> fbx

hdmi_msm.0

hdmi_msm.1 ->mdp.655361 -> msm_fb.655361 -> fbx (hdmi)

mdp.0

mipi_dsi.1

mipi_toshiba.0

msm_fb.0

Framebuffer设备注册后,使用FBIOCPUT_VSCREEN或FBIOCPAN_DISPLAY,驱动都会使用msmfb_pan_display进行响应显示,由于涉及到MDP,另文分析。

[END]



 

 

赞 (0) 评论 分享 ()