zoukankan      html  css  js  c++  java
  • 设备注册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()函数,这个函数注册了几个id0的设备。各主要设备名如下,

        “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
    1764	else if (!strncmp(name, "dtv", 3))
    1765		msm_register_device(&msm_dtv_device, data);
    1766#endif
    1767	else
    1768		printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
    1769}

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

    1484#define MIPI_DSI_HW_BASE	0x04700000
    1485#define ROTATOR_HW_BASE	0x04E00000
    1486#define TVENC_HW_BASE		0x04F00000
    1487#define MDP_HW_BASE		0x05100000
    1488
    1489static 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};
    1502
    1503static 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};
    1509
    1510static 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};
    1523
    1524static 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,初步初始化设备,保存其资源分配。

        此时,以下设备中id0mipi-dsi id1的设备已经注册进系统了。

        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.c
    3899{
    3900	int rc = -ENODEV;
    3901
    3902	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_EARLYSUSPEND
    738	.suspend = msm_fb_suspend,
    739	.resume = msm_fb_resume,
    740#endif
    741	.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是在machineinit_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;
    1209
    1210	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_BUFFER
    33#define MSM_FB_PRIM_BUF_SIZE \
    34		(roundup((1920 * 1088 * 4), 4096) * 3) /* 4 bpp x 3 pages */
    35#else
    36#define MSM_FB_PRIM_BUF_SIZE \
    37		(roundup((1920 * 1088 * 4), 4096) * 2) /* 4 bpp x 2 pages */
    38#endif
    39/* 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.0msm_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}
    607
    608static int __init mipi_dsi_driver_init(void)
    609{
    610	int ret;
    611
    612	mipi_dsi_init();
    613
    614	ret = mipi_dsi_register_driver();
    615
    616	device_initialize(&dsi_dev);
    617
    618	if (ret) {
    619		pr_err("mipi_dsi_register_driver() failed!\n");
    620		return ret;
    621	}
    622
    623	return ret;
    624}
    625
    626module_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_EARLYSUSPEND
    2098	.suspend = mdp_suspend,
    2099	.resume = NULL,
    2100#endif
    2101	.shutdown = NULL,
    2102	.driver = {
    2103		/*
    2104		 * Driver name must match the device name added in
    2105		 * 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_EARLYSUSPEND
    3004	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#endif
    3009
    3010	return platform_driver_register(&mdp_driver);
    3011}
    3012
    3013static int __init mdp_driver_init(void)
    3014{
    3015	int ret;
    3016
    3017	mdp_drv_init();
    3018
    3019	ret = mdp_register_driver();
    3020	if (ret) {
    3021		printk(KERN_ERR "mdp_register_driver() failed!\n");
    3022		return ret;
    3023	}
    3024
    3025#if defined(CONFIG_DEBUG_FS)
    3026	mdp_debugfs_init();
    3027#endif
    3028
    3029	return 0;
    3030
    3031}
    3032
    3033module_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;
    38
    39	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__);
    92
    93	return ret;
    94}
    95
    96module_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去匹配。下面欲同时注册SAMSUNGCHIMEI两块屏设备,当然不能同时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};
    364
    365static struct msm_fb_panel_data samsung_panel_data = {
    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;
    378
    379	if ((channel >= 3) || ch_used[channel])
    380		return -ENODEV;
    381
    382	ch_used[channel] = TRUE;
    383
    384	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	}
    389
    390	pdev = platform_device_alloc("dsi_cmd_samsung_fwvga", (panel << 8)|channel);
    391	if (!pdev)
    392		return -ENOMEM;
    393
    394	samsung_panel_data.panel_info = *pinfo;
    395
    396	ret = platform_device_add_data(pdev, &samsung_panel_data,
    397		sizeof(samsung_panel_data));
    398	if (ret) {
    399		printk(KERN_ERR
    400		  "%s: platform_device_add_data failed!\n", __func__);
    401		goto err_device_put;
    402	}
    403
    404	ret = platform_device_add(pdev);
    405	if (ret) {
    406		printk(KERN_ERR
    407		  "%s: platform_device_register failed!\n", __func__);
    408		goto err_device_put;
    409	}
    410
    411	return 0;
    412
    413err_device_put:
    414	platform_device_put(pdev);
    415	return ret;
    416}
    417
    418static int mipi_samsung_lcd_init(void)
    419{
    420
    421	led_trigger_register_simple("bkl_trigger", &bkl_led_trigger);
    422	pr_info("%s: SUCCESS (WLED TRIGGER)\n", __func__);
    423	wled_trigger_initialized = 1;
    424
    425	mipi_dsi_buf_alloc(&samsung_tx_buf, DSI_BUF_SIZE);
    426	mipi_dsi_buf_alloc(&samsung_rx_buf, DSI_BUF_SIZE);
    427
    428	return platform_driver_register(&this_driver);
    429}

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

        屏设备注册后,platform_deviceplatform_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_probe
    Modules 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);
    339
    340	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;
    346
    347		mipi  = &mfd->panel_info.mipi;
    348
    349		if (phy_settings != NULL)
    350			mipi->dsi_phy_db = phy_settings;
    351
    352		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_datamsm_fb_panel_data

        以额定msm_fb_data_type结构分配framebuffer

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

        “mipi-dsi”设备和驱动停止attach, match后,“mipi-dsi” driverprobe被调用到。

        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” driverprobe被调用到。

        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” driverprobe被调用到。

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

        调用msm_fb_register设置linux framebufferregister_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]

        
     

    文章结束给大家分享下程序员的一些笑话语录: IT业众生相
    第一级:神人,天资过人而又是技术狂热者同时还拥有过人的商业头脑,高瞻远瞩,技术过人,大器也。如丁磊,求伯君。
    第二级:高人,有天赋,技术过人但没有过人的商业头脑,通常此类人不是顶尖黑客就是技术总监之流。
    第三级:牛人,技术精湛,熟悉行业知识,敢于创新,有自己的公司和软件产品。
    第四级:工头,技术精湛,有领导团队的能力,此类人大公司项目经理居多。
    第五级:技术工人,技术精湛,熟悉行业知识但领导能力欠加,此类人大多为系分人员或资深程序员,基本上桀骜不逊,自视清高,不愿于一般技术人员为伍,在论坛上基本以高手面目出现。
    第六级:熟练工人,技术有广度无深度,喜欢钻研但浅尝辄止。此类人大多为老程序员,其中一部分喜欢利用工具去查找网上有漏洞的服务器,干点坏事以获取成绩感。如果心情好,在论坛上他们会回答菜鸟的大部分问题。此级别为软件业苦力的重要组成部分。
    第七级:工人,某些技术较熟练但缺乏深度和广度,此类人大多为程序员级别,经常在论坛上提问偶尔也回答菜鸟的问题。为软件产业苦力的主要组成部分。
    第八级:菜鸟,入门时间不长,在论坛上会反复提问很初级的问题,有一种唐僧的精神。虽然招人烦但基本很可爱。只要认真钻研,一两年后就能升级到上一层。
    第九级:大忽悠,利用中国教育的弊病,顶着一顶高学历的帽子,在小公司里混个软件部经理,设计不行,代码不行,只会胡乱支配下属,拍领导马屁,在领导面前胡吹海侃,把自己打扮成技术高手的模样。把勾心斗角的办公室文化引入技术部门,实在龌龊!
    第十级:驴或傻X,会写SELECT语句就说自己精通ORALCE,连寄存器有几种都不知道就说自己懂汇编,建议全部送到日本当IT产业工人,挣了日本人的钱还严重打击日本的软件业!

    --------------------------------- 原创文章 By
    设备和注册
    ---------------------------------

  • 相关阅读:
    剑指Offer--复杂链表的复制
    剑指offer--第43题 1~n整数中1出现的次数
    剑指Offer--第50题 第一次只出现一次的字符
    剑指offer--扑克牌顺子
    MySQL免安装使用教程
    TortoiseGit的使用参考
    剑指Offer-- 第58题 翻转字符串
    剑指Offer-- 第45题 把数组排成最小数
    剑指Offer-- 第49题 丑数
    SpringBoot-data-jpa的简单使用
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3106650.html
Copyright © 2011-2022 走看看