许多学习嵌入式的进入MTK开发平台,很多东西都会感到很陌生。在MTK平台上你可以简简单单几分钟就点亮一块屏。加上MTK快速开发的节奏,也很少有时间自己整理学习。如果不思进取,不加班加点学习。很容易就慢慢……。这也难怪有些人说MTK造就了一批懒人,毁掉了一批工程师。但其实都是基于linux开发,核心的东西都是一样一样的。我刚入行业,在迷茫之际,自己整理跟踪源码。想慢慢找回自己熟悉的感觉,掌握MTK的整体框架。也希望能给有需要的人带来些帮助。好吧!前话说到这,开始正题。
本文可能有的地方会出现错误,或不够深入,欢迎批评指正。毕竟都是个人理解,希望能和大家多多交流。大家一起慢慢吃透MTK。随便提一句,如果不熟悉“linux平台设备驱动”模型的,可以找相关资料看看。
注:-->表示函数之间的调用
一、平台驱动:Mtkfb.c
就从Mtkfb.c文件开始说起吧。路径在:alps\mediatek\platform\common\kernel\drivers\video\Mtkfb.c
在该文件中,我们能非常熟悉的看到内核的原态。下面我删截了一部分大家最熟悉的源码。
static struct platform_driver mtkfb_driver =
{
.driver = {
.name = MTKFB_DRIVER,
#ifdef CONFIG_PM
.pm = &mtkfb_pm_ops,
#endif
.bus = &platform_bus_type,
.probe = mtkfb_probe,
.remove = mtkfb_remove,
.suspend = mtkfb_suspend,
.resume = mtkfb_resume,
.shutdown = mtkfb_shutdown,
},
};
/* Register both the driver and the device */
int __init mtkfb_init(void)
{
int r = 0;
MSG_FUNC_ENTER();
#ifdef DEFAULT_MMP_ENABLE
MMProfileEnable(1);
init_mtkfb_mmp_events();
init_ddp_mmp_events();
MMProfileStart(1);
#endif
/* Register the driver with LDM */
if (platform_driver_register(&mtkfb_driver)) {
PRNERR("failed to register mtkfb driver\n");
r = -ENODEV;
goto exit;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
register_early_suspend(&mtkfb_early_suspend_handler);
#endif
DBG_Init();
//#ifdef MTK_DISP_CONFIG_SUPPORT
ConfigPara_Init();//In order to Trigger Display Customization Tool..
//#endif
exit:
MSG_FUNC_LEAVE();
return r;
}
module_init(mtkfb_init);
module_exit(mtkfb_cleanup);
看了上面代码,大家肯定知道mtkfb_probe函数是核心。但暂时我还不想说这一块,因为底层框架还没分析完,熟悉平台设备驱动的都知道:仅仅有driver是跑不到probe函数的。在入口函数上面的注视,有写同时注册driver和device。不知道是MTK掩人耳目还是同事的错误标注,反正我没在里面找到注册device相关的代码。这一块希望看过本文的人能提供解释。
二、平台设备:Mt_devs.c
事实上我在另外的地方跟到了device的注册函数。在Mt_devs.c中,路径在:mediatek\platform\common\kernel\drivers\video(在bootable\bootloader\lk目录下也有一份一样的,目前不能给出明确解释。)
1、在该文件中:__init int mt_board_init(void)函数-->platform_device_register(&mt6575_device_fb),在mt6575_device_fb结构体中我们能看到disp_device.name = "mtkfb"。对比Mtkfb.c中的结构体mtkfb_driver.name = MTKFB_DRIVER。我们能发现两者同名。这又到了我们熟悉的地方。出现同名设备,不管先后,内核会调用Mtkfb.c中的probe函数。这时我们可以开始分析probe函数了。
2、在这之前,有个问题我得说明,我们先来看看__init int mt_board_init(void)函数的调用过程:Main.c里的kmain函数-->platform_early_init-->board_init-->mt_board_init。源头追溯到了C函数的入口Main.c。我之所以去跟,是因为Mt_devs.c中并不是以我们熟悉的模块的形式注册的设备,也就是根本没有module_init()入口标记,而且mt_board_init一个函数中做了几乎所有平台设备的注册工作。这是和平时学习有别的地方,所以特意说明。也免得大家和我开始一样,一直疑惑设备驱动文件为啥没入口函数。
时候不早了,该下班了。下次接着“第三点”,说说mtkfb_probe函数里边的工作
待续…………