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

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

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

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

[cpp]  view plain copy
  1. 3463MACHINE_START(MSM8930_CDP, "QCT MSM8930 CDP")  
  2. 3464    .map_io = msm8930_map_io,  
  3. 3465    .reserve = msm8930_reserve,  
  4. 3466    .init_irq = msm8930_init_irq,  
  5. 3467    .handle_irq = gic_handle_irq,  
  6. 3468    .timer = &msm_timer,  
  7. 3469    .init_machine = msm8930_cdp_init,  
  8. 3470    .init_early = msm8930_allocate_memory_regions,  
  9. 3471    .init_very_early = msm8930_early_memory,  
  10. 3472    .restart = msm_restart,  
  11. 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函数部分示例代码如下:

[cpp]  view plain copy
  1. <span style="font-size:12px;">static void __init msm8930_cdp_init(void) @ kernel/arch/arm/mach-msm/board-8930.c  
  2. {  
  3.     …  
  4. platform_add_devices(common_devices, ARRAY_SIZE(common_devices));  
  5.     msm8930_init_gpu();      
  6.     msm8930_init_mmc();  
  7.     msm8930_init_cam();  
  8.     msm8930_init_fb();  
  9. }</span>  

其中,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);

[cpp]  view plain copy
  1. <span style="font-size:12px;">1168void __init msm8930_init_fb(void) @ kernel/arch/arm/mach-msm/board-8930-display.c  
  2. 1169{  
  3. 1170    platform_device_register(&msm_fb_device);  
  4. 1171  
  5. 1172#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL  
  6. 1173    platform_device_register(&wfd_panel_device);  
  7. 1174    platform_device_register(&wfd_device);  
  8. 1175#endif  
  9. 1176  
  10. 1178#ifdef CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT  
  11. 1179    platform_device_register(&mipi_dsi_novatek_panel_device);  
  12. 1180#endif  
  13. 1181  
  14. 1184#ifdef CONFIG_FB_MSM_MIPI_SA77_CMD_FWVGA_PANEL  
  15. 1185    platform_device_register(&mipi_dsi_cmd_chimei_fwvga_panel_device);  
  16. 1186    platform_device_register(&mipi_dsi_cmd_samsung_fwvga_panel_device);  
  17. 1187#endif  
  18. 1189  
  19. 1190#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL  
  20. 1191    platform_device_register(&hdmi_msm_device);  
  21. 1192#endif  
  22. 1193  
  23. 1194    platform_device_register(&mipi_dsi_toshiba_panel_device);  
  24. 1195  
  25. 1196    msm_fb_register_device("mdp", &mdp_pdata);  
  26. 1197    msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);  
  27. 1198#ifdef CONFIG_MSM_BUS_SCALING  
  28. 1199#ifdef CONFIG_FB_MSM_DTV   
  29. 1200    msm_fb_register_device("dtv", &dtv_pdata);  
  30. 1201#endif   
  31. 1202#endif  
  32. 1203}</span>  

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

 

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">71static struct resource msm_fb_resources[] = {  
  2. 72  {  
  3. 73      .flags = IORESOURCE_DMA,  
  4. 74  }  
  5. 75};   
  6. 135static struct msm_fb_platform_data msm_fb_pdata = {  
  7. 136 .detect_client = msm_fb_detect_panel,  
  8. 137};  
  9. 138  
  10. 139static struct platform_device msm_fb_device = {  
  11. 140 .name   = "msm_fb",  
  12. 141 .id     = 0,  
  13. 142 .num_resources     = ARRAY_SIZE(msm_fb_resources),  
  14. 143 .resource          = msm_fb_resources,  
  15. 144 .dev.platform_data = &msm_fb_pdata,  
  16. 145};</span>  

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">845static struct mipi_dsi_panel_platform_data samsung_pdata = {  
  2. 846 .enable_wled_bl_ctrl = 0x1,  
  3. 847};  
  4. 848  
  5. 849static struct platform_device mipi_dsi_cmd_samsung_fwvga_panel_device = {  
  6. 850 .name = "dsi_cmd_samsung_fwvga",  
  7. 851 .id = 0,  
  8. 852 .dev = {  
  9. 853     .platform_data = &samsung_pdata,  
  10. 854 }  
  11. 855};</span>  

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">1749void __init msm_fb_register_device(char *name, void *data)  
  2. 1750{  
  3. 1751    if (!strncmp(name, "mdp", 3))  
  4. 1752        msm_register_device(&msm_mdp_device, data);  
  5. 1753    else if (!strncmp(name, "lcdc", 4))  
  6. 1754        msm_register_device(&msm_lcdc_device, data);  
  7. 1755    else if (!strncmp(name, "mipi_dsi", 8))  
  8. 1756        msm_register_device(&msm_mipi_dsi_device, data);  
  9. 1757#ifdef CONFIG_FB_MSM_TVOUT  
  10. 1758    else if (!strncmp(name, "tvenc", 5))  
  11. 1759        msm_register_device(&msm_tvenc_device, data);  
  12. 1760    else if (!strncmp(name, "tvout_device", 12))  
  13. 1761        msm_register_device(&msm_tvout_device, data);  
  14. 1762#endif  
  15. 1763#ifdef CONFIG_MSM_BUS_SCALING  
  16. 1764    else if (!strncmp(name, "dtv", 3))  
  17. 1765        msm_register_device(&msm_dtv_device, data);  
  18. 1766#endif  
  19. 1767    else  
  20. 1768        printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);  
  21. 1769}</span>  

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">1484#define MIPI_DSI_HW_BASE  0x04700000  
  2. 1485#define ROTATOR_HW_BASE 0x04E00000  
  3. 1486#define TVENC_HW_BASE       0x04F00000  
  4. 1487#define MDP_HW_BASE     0x05100000  
  5. 1488  
  6. 1489static struct resource msm_mipi_dsi_resources[] = {  
  7. 1490    {  
  8. 1491        .name   = "mipi_dsi",  
  9. 1492        .start  = MIPI_DSI_HW_BASE,  
  10. 1493        .end    = MIPI_DSI_HW_BASE + 0x000F0000 - 1,  
  11. 1494        .flags  = IORESOURCE_MEM,  
  12. 1495    },  
  13. 1496    {  
  14. 1497        .start  = DSI_IRQ,  
  15. 1498        .end    = DSI_IRQ,  
  16. 1499        .flags  = IORESOURCE_IRQ,  
  17. 1500    },  
  18. 1501};  
  19. 1502  
  20. 1503static struct platform_device msm_mipi_dsi_device = {  
  21. 1504    .name   = "mipi_dsi",  
  22. 1505    .id     = 1,  
  23. 1506    .num_resources  = ARRAY_SIZE(msm_mipi_dsi_resources),  
  24. 1507    .resource       = msm_mipi_dsi_resources,  
  25. 1508};  
  26. 1509  
  27. 1510static struct resource msm_mdp_resources[] = {  
  28. 1511    {  
  29. 1512        .name   = "mdp",  
  30. 1513        .start  = MDP_HW_BASE,  
  31. 1514        .end    = MDP_HW_BASE + 0x000F0000 - 1,  
  32. 1515        .flags  = IORESOURCE_MEM,  
  33. 1516    },  
  34. 1517    {  
  35. 1518        .start  = INT_MDP,  
  36. 1519        .end    = INT_MDP,  
  37. 1520        .flags  = IORESOURCE_IRQ,  
  38. 1521    },  
  39. 1522};  
  40. 1523  
  41. 1524static struct platform_device msm_mdp_device = {  
  42. 1525    .name   = "mdp",  
  43. 1526    .id     = 0,  
  44. 1527    .num_resources  = ARRAY_SIZE(msm_mdp_resources),  
  45. 1528    .resource       = msm_mdp_resources,  
  46. 1529};</span>  

以上设备注册时,其驱动并未加载,因为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驱动注册如下

[cpp]  view plain copy
  1. <span style="font-size:12px;">module_init(msm_fb_init);  
  2. 3898int __init msm_fb_init(void) @ kernel/drivers/video/msm/msm_fb.c  
  3. 3899{  
  4. 3900    int rc = -ENODEV;  
  5. 3901  
  6. 3902    if (msm_fb_register_driver())  
  7. 3903        return rc;  
  8.     ….  
  9. }  
  10. 3705static int msm_fb_register_driver(void)  
  11. 3706{  
  12. 3707    return platform_driver_register(&msm_fb_driver);  
  13. 3708}</span>  

msm_fb_driver驱动定义如下

[cpp]  view plain copy
  1. <span style="font-size:12px;">734static struct platform_driver msm_fb_driver = {  
  2. 735 .probe = msm_fb_probe,  
  3. 736 .remove = msm_fb_remove,  
  4. 737#ifndef CONFIG_HAS_EARLYSUSPEND  
  5. 738 .suspend = msm_fb_suspend,  
  6. 739 .resume = msm_fb_resume,  
  7. 740#endif  
  8. 741 .shutdown = NULL,  
  9. 742 .driver = {  
  10. 743        /* Driver name must match the device name added in platform.c. */  
  11. 744        .name = "msm_fb",  
  12. 745        .pm = &msm_fb_dev_pm_ops,  
  13. 746        },  
  14. 747};</span>  

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

[cpp]  view plain copy
  1. 1006static void __init msm8930_allocate_memory_regions(void)  
  2. 1007{  
  3. 1008    msm8930_allocate_fb_region();  
  4. 1009}  

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

[cpp]  view plain copy
  1. 1205void __init msm8930_allocate_fb_region(void)   
  2. 1206{  
  3. 1207    void *addr;  
  4. 1208    unsigned long size;  
  5. 1209  
  6. 1210    size = MSM_FB_SIZE;  
  7. 1211    addr = alloc_bootmem_align(size, 0x1000);  
  8. 1212    msm_fb_resources[0].start = __pa(addr);  
  9. 1213    msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;  
  10. 1214    pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", size, addr, __pa(addr));  
  11. 1216}  

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">32#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER  
  2. 33#define MSM_FB_PRIM_BUF_SIZE \  
  3. 34      (roundup((1920 * 1088 * 4), 4096) * 3) /* 4 bpp x 3 pages */  
  4. 35#else  
  5. 36#define MSM_FB_PRIM_BUF_SIZE \  
  6. 37      (roundup((1920 * 1088 * 4), 4096) * 2) /* 4 bpp x 2 pages */  
  7. 38#endif  
  8. 39/* Note: must be multiple of 4096 */  
  9. 40#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE, 4096)</span>  

”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)

[cpp]  view plain copy
  1. <span style="font-size:12px;">55static struct platform_driver mipi_dsi_driver = {  
  2. 56  .probe = mipi_dsi_probe,  
  3. 57  .remove = mipi_dsi_remove,  
  4. 58  .shutdown = NULL,  
  5. 59  .driver = {  
  6. 60         .name = "mipi_dsi",  
  7. 61         },  
  8. 62};  
  9. 603static int mipi_dsi_register_driver(void)  
  10. 604{  
  11. 605 return platform_driver_register(&mipi_dsi_driver);  
  12. 606}  
  13. 607  
  14. 608static int __init mipi_dsi_driver_init(void)  
  15. 609{  
  16. 610 int ret;  
  17. 611  
  18. 612 mipi_dsi_init();  
  19. 613  
  20. 614 ret = mipi_dsi_register_driver();  
  21. 615  
  22. 616 device_initialize(&dsi_dev);  
  23. 617  
  24. 618 if (ret) {  
  25. 619     pr_err("mipi_dsi_register_driver() failed!\n");  
  26. 620     return ret;  
  27. 621 }  
  28. 622  
  29. 623 return ret;  
  30. 624}  
  31. 625  
  32. 626module_init(mipi_dsi_driver_init);</span>  

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">2094static struct platform_driver mdp_driver = {  
  2. 2095    .probe = mdp_probe,  
  3. 2096    .remove = mdp_remove,  
  4. 2097#ifndef CONFIG_HAS_EARLYSUSPEND  
  5. 2098    .suspend = mdp_suspend,  
  6. 2099    .resume = NULL,  
  7. 2100#endif  
  8. 2101    .shutdown = NULL,  
  9. 2102    .driver = {  
  10. 2103        /* 
  11. 2104         * Driver name must match the device name added in 
  12. 2105         * platform.c. 
  13. 2106         */  
  14. 2107        .name = "mdp",  
  15. 2108        .pm = &mdp_dev_pm_ops,  
  16. 2109    },  
  17. 2110};  
  18. 3001static int mdp_register_driver(void)  
  19. 3002{  
  20. 3003#ifdef CONFIG_HAS_EARLYSUSPEND  
  21. 3004    early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;  
  22. 3005    early_suspend.suspend = mdp_early_suspend;  
  23. 3006    early_suspend.resume = mdp_early_resume;  
  24. 3007    register_early_suspend(&early_suspend);  
  25. 3008#endif  
  26. 3009  
  27. 3010    return platform_driver_register(&mdp_driver);  
  28. 3011}  
  29. 3012  
  30. 3013static int __init mdp_driver_init(void)  
  31. 3014{  
  32. 3015    int ret;  
  33. 3016  
  34. 3017    mdp_drv_init();  
  35. 3018  
  36. 3019    ret = mdp_register_driver();  
  37. 3020    if (ret) {  
  38. 3021        printk(KERN_ERR "mdp_register_driver() failed!\n");  
  39. 3022        return ret;  
  40. 3023    }  
  41. 3024  
  42. 3025#if defined(CONFIG_DEBUG_FS)  
  43. 3026    mdp_debugfs_init();  
  44. 3027#endif  
  45. 3028  
  46. 3029    return 0;  
  47. 3030  
  48. 3031}  
  49. 3032  
  50. 3033module_init(mdp_driver_init);</span>  

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

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

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

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

[cpp]  view plain copy
  1. <span style="font-size:12px;">static int __init mipi_cmd_samsung_fwvga_pt_init(void) @ kernel/drivers/video/msm/mipi_samsung_cmd_fwvga_pt.c  
  2. {  
  3. 37  int ret;  
  4. 38  
  5. 39  if (msm_fb_detect_client("mipi_cmd_samsung_fwvga"))  
  6. 40      return 0;  
  7.     ……  
  8. 88  ret = mipi_samsung_device_register(&pinfo, MIPI_DSI_PRIM, MIPI_DSI_PANEL_QHD_PT);  
  9. 90  if (ret)  
  10. 91      pr_err("%s: failed to register device!\n", __func__);  
  11. 92  
  12. 93  return ret;  
  13. 94}  
  14. 95  
  15. 96module_init(mipi_cmd_samsung_fwvga_pt_init);</span>  

探测函数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)注册屏驱动和屏设备。驱动定义和注册具体如下,

[cpp]  view plain copy
  1. <span style="font-size:12px;">358static struct platform_driver this_driver = {  
  2. 359 .probe  = mipi_samsung_lcd_probe,  
  3. 360 .driver = {  
  4. 361     .name   = "dsi_cmd_samsung_fwvga",  
  5. 362 },  
  6. 363};  
  7. 364  
  8. 365static struct msm_fb_panel_data samsung_panel_data = {  
  9. 366 .on     = mipi_samsung_lcd_on,  
  10. 367 .off        = mipi_samsung_lcd_off,  
  11. 368 .set_backlight = mipi_samsung_set_backlight,  
  12. 369};  
  13. 373int mipi_samsung_device_register(struct msm_panel_info *pinfo, u32 channel, u32 panel)  
  14. 375{  
  15. 376 struct platform_device *pdev = NULL;  
  16. 377 int ret;  
  17. 378  
  18. 379 if ((channel >= 3) || ch_used[channel])  
  19. 380     return -ENODEV;  
  20. 381  
  21. 382 ch_used[channel] = TRUE;  
  22. 383  
  23. 384 ret = mipi_samsung_lcd_init();  
  24. 385 if (ret) {  
  25. 386     pr_err("mipi_samsung_lcd_init() failed with ret %u\n", ret);  
  26. 387     return ret;  
  27. 388 }  
  28. 389  
  29. 390 pdev = platform_device_alloc("dsi_cmd_samsung_fwvga", (panel << 8)|channel);  
  30. 391 if (!pdev)  
  31. 392     return -ENOMEM;  
  32. 393  
  33. 394 samsung_panel_data.panel_info = *pinfo;  
  34. 395  
  35. 396 ret = platform_device_add_data(pdev, &samsung_panel_data,  
  36. 397     sizeof(samsung_panel_data));  
  37. 398 if (ret) {  
  38. 399     printk(KERN_ERR  
  39. 400       "%s: platform_device_add_data failed!\n", __func__);  
  40. 401     goto err_device_put;  
  41. 402 }  
  42. 403  
  43. 404 ret = platform_device_add(pdev);  
  44. 405 if (ret) {  
  45. 406     printk(KERN_ERR  
  46. 407       "%s: platform_device_register failed!\n", __func__);  
  47. 408     goto err_device_put;  
  48. 409 }  
  49. 410  
  50. 411 return 0;  
  51. 412  
  52. 413err_device_put:  
  53. 414 platform_device_put(pdev);  
  54. 415 return ret;  
  55. 416}  
  56. 417  
  57. 418static int mipi_samsung_lcd_init(void)  
  58. 419{  
  59. 420  
  60. 421 led_trigger_register_simple("bkl_trigger", &bkl_led_trigger);  
  61. 422 pr_info("%s: SUCCESS (WLED TRIGGER)\n", __func__);  
  62. 423 wled_trigger_initialized = 1;  
  63. 424  
  64. 425 mipi_dsi_buf_alloc(&samsung_tx_buf, DSI_BUF_SIZE);  
  65. 426 mipi_dsi_buf_alloc(&samsung_rx_buf, DSI_BUF_SIZE);  
  66. 427  
  67. 428 return platform_driver_register(&this_driver);  
  68. 429}</span>  

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”)

一个类似的调用栈如下

[plain]  view plain copy
  1. <span style="font-size:12px;">------------[ cut here ]------------  
  2. WARNING: at /home/CORPUSERS/xp010548/myworkdroid/7x25a/LINUX/kernel/drivers/video/msm/msm_fb.c:1221 msm_fb_probe+0xf4/0xcbc()  
  3. msm_fb_probe  
  4. Modules linked in:  
  5.  [<c003fe0c>] (unwind_backtrace+0x0/0x12c) from [<c00adccc>] (warn_slowpath_common+0x4c/0x64)  
  6.  [<c00adccc>] (warn_slowpath_common+0x4c/0x64) from [<c00add64>] (warn_slowpath_fmt+0x2c/0x3c)  
  7.  [<c00add64>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0223c44>] (msm_fb_probe+0xf4/0xcbc)  
  8.  [<c0223c44>] (msm_fb_probe+0xf4/0xcbc) from [<c026e624>] (platform_drv_probe+0x18/0x1c)  
  9.  [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264)  
  10.  [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84)  
  11.  [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0)  
  12.  [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40)  
  13.  [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570)  
  14.  [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0)  
  15.  [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02264b4>] (mdp_probe+0x828/0x940)  
  16.  [<c02264b4>] (mdp_probe+0x828/0x940) from [<c026e624>] (platform_drv_probe+0x18/0x1c)  
  17.  [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264)  
  18.  [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84)  
  19.  [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0)  
  20.  [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40)  
  21.  [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570)  
  22.  [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0)  
  23.  [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c023db98>] (mipi_dsi_probe+0x514/0x5d0)  
  24.  [<c023db98>] (mipi_dsi_probe+0x514/0x5d0) from [<c026e624>] (platform_drv_probe+0x18/0x1c)  
  25.  [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264)  
  26.  [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84)  
  27.  [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0)  
  28.  [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40)  
  29.  [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570)  
  30.  [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0)  
  31.  [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02223b8>] (msm_fb_add_device+0x150/0x1b4)  
  32.  [<c02223b8>] (msm_fb_add_device+0x150/0x1b4) from [<c051e830>] (mipi_himax_lcd_probe+0x38/0x108)  
  33.  [<c051e830>] (mipi_himax_lcd_probe+0x38/0x108) from [<c026e624>] (platform_drv_probe+0x18/0x1c)  
  34.  [<c026e624>] (platform_drv_probe+0x18/0x1c) from [<c026d354>] (driver_probe_device+0x144/0x264)  
  35.  [<c026d354>] (driver_probe_device+0x144/0x264) from [<c026c78c>] (bus_for_each_drv+0x48/0x84)  
  36.  [<c026c78c>] (bus_for_each_drv+0x48/0x84) from [<c026d5d0>] (device_attach+0x74/0xa0)  
  37.  [<c026d5d0>] (device_attach+0x74/0xa0) from [<c026c5a4>] (bus_probe_device+0x24/0x40)  
  38.  [<c026c5a4>] (bus_probe_device+0x24/0x40) from [<c026b4c4>] (device_add+0x3f0/0x570)  
  39.  [<c026b4c4>] (device_add+0x3f0/0x570) from [<c026ec54>] (platform_device_add+0x13c/0x1a0)  
  40.  [<c026ec54>] (platform_device_add+0x13c/0x1a0) from [<c02409ec>] (mipi_himax_device_register+0x7c/0xc0)  
  41.  [<c02409ec>] (mipi_himax_device_register+0x7c/0xc0) from [<c001ac34>] (mipi_cmd_himax_hvga_pt_init+0x148/0x180)  
  42.  [<c001ac34>] (mipi_cmd_himax_hvga_pt_init+0x148/0x180) from [<c0034388>] (do_one_initcall+0x94/0x164)  
  43.  [<c0034388>] (do_one_initcall+0x94/0x164) from [<c00083d8>] (kernel_init+0x98/0x144)  
  44.  [<c00083d8>] (kernel_init+0x98/0x144) from [<c003b0d0>] (kernel_thread_exit+0x0/0x8)  
  45. ---[ end trace 65f8ea860415c051 ]---</span>  

下面考察设备probe链。

[cpp]  view plain copy
  1. <span style="font-size:12px;">311static int __devinit mipi_samsung_lcd_probe(struct platform_device *pdev)  
  2. 312{  
  3.     …..  
  4. 338 current_pdev = msm_fb_add_device(pdev);  
  5. 339  
  6. 340 if (current_pdev) {  
  7. 341     mfd = platform_get_drvdata(current_pdev);  
  8. 342     if (!mfd)  
  9. 343         return -ENODEV;  
  10. 344     if (mfd->key != MFD_KEY)  
  11. 345         return -EINVAL;  
  12. 346  
  13. 347     mipi  = &mfd->panel_info.mipi;  
  14. 348  
  15. 349     if (phy_settings != NULL)  
  16. 350         mipi->dsi_phy_db = phy_settings;  
  17. 351  
  18. 352     if (dlane_swap)  
  19. 353         mipi->dlane_swap = dlane_swap;  
  20. 354 }  
  21. 355 return 0;  
  22. 356}</span>  

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]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值