本文是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.c
1169{
1170 platform_device_register(&msm_fb_device);
1171
1172#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
1173 platform_device_register(&wfd_panel_device);
1174 platform_device_register(&wfd_device);
1175#endif
1176
1178#ifdef CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
1179 platform_device_register(&mipi_dsi_novatek_panel_device);
1180#endif
1181
1184#ifdef CONFIG_FB_MSM_MIPI_SA77_CMD_FWVGA_PANEL
1185 platform_device_register(&mipi_dsi_cmd_chimei_fwvga_panel_device);
1186 platform_device_register(&mipi_dsi_cmd_samsung_fwvga_panel_device);
1187#endif
1189
1190#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1191 platform_device_register(&hdmi_msm_device);
1192#endif
1193
1194 platform_device_register(&mipi_dsi_toshiba_panel_device);
1195
1196 msm_fb_register_device("mdp", &mdp_pdata);
1197 msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
1198#ifdef CONFIG_MSM_BUS_SCALING
1199#ifdef CONFIG_FB_MSM_DTV
1200 msm_fb_register_device("dtv", &dtv_pdata);
1201#endif
1202#endif
1203}
因为注册这些设备的意图主要是资源申请和初步初始化设备,所以各设备注册顺序并无关紧要。其初始化顺序还与后来的驱动实际注册顺序有关。
首先注册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 = {
136 .detect_client = msm_fb_detect_panel,
137};
138
139static 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 = {
846 .enable_wled_bl_ctrl = 0x1,
847};
848
849static 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_TVOUT
1758 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#endif
1763#ifdef CONFIG_MSM_BUS_SCALING