根据内核打印的信息“S3C24XX_UDA134X SoC Audio driver“我们来开始着手分析。搜索这个字符串,定位到文件s3c24xx_uda134x.c,查看module_init找到初始化函数。
static int __init s3c24xx_uda134x_init(void)
{
returnplatform_driver_register(&s3c24xx_uda134x_driver);
}
发现注册的是platform_driver,这个platform_driver定义如下
static struct platform_driver s3c24xx_uda134x_driver = {
.probe = s3c24xx_uda134x_probe,
.remove= s3c24xx_uda134x_remove,
.driver= {
.name= "s3c24xx_uda134x",
.owner= THIS_MODULE,
},
};我们知道,platform_driver与platform_device匹配的条件是platform_driver->driver->name与platform_device->name相同,如匹配成功,就会调用platfrom_driver->probe函数。为了证明我的说法是正确,贴一下platform_driver和platform_device的代码。
static int platform_match(struct device*dev, struct device_driver *drv)
{
structplatform_device *pdev = to_platform_device(dev);
structplatform_driver *pdrv = to_platform_driver(drv);
/*match against the id table first */
if(pdrv->id_table)
returnplatform_match_id(pdrv->id_table, pdev) != NULL;
/*fall-back to driver name match */
return(strcmp(pdev->name, drv->name) == 0);
}
那么下面我就找找另外一个name"s3c24xx_uda134x"是在什么地方定义的。根据男人的直觉以及阅读了无所linux代码之后积累的经验,这个"s3c24xx_uda134x"应该就在mach文件中,由于我用的是mini2440,因此这个设备的定义就在mach-mini2440.c中。果然,在这个问题中找到了这个设备的定义
static struct platform_devicemini2440_audio __initdata = {
.name = "s3c24xx_uda134x",
.id = 0,
.dev = {
.platform_data = &mini2440_audio_pins,
},
};
既然已经匹配成功,那我们来看看platform_driver->probe函数,这里的probe函数为s3c24xx_uda134x_probe,我们顺着这个函数往下看,将一些解释写到注释中。
static int s3c24xx_uda134x_probe(struct platform_device *pdev)
{
intret;
printk(KERN_INFO"S3C24XX_UDA134XSoC Audio driver\n");
/*将mini2440_audio->platform_data,即将mini2440_audio_pins 赋给全局变量s3c24xx_uda134x_l3_pins ,这里面定义了uda134x这个芯片用到的GPIO*/
s3c24xx_uda134x_l3_pins =pdev->dev.platform_data;
if(s3c24xx_uda134x_l3_pins ==NULL) {
printk(KERN_ERR"S3C24XX_UDA134XSoC Audio: "
"unable to find platformdata\n");
return-ENODEV;
}
s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
if(s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
"data") < 0)
return-EBUSY;
if(s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
"clk") < 0) {
gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
return-EBUSY;
}
if(s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
"mode") < 0) {
gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
return-EBUSY;
}
/*又分配了一个platform_device,platform_device->name为"soc-audio",这个platform_device叫做 s3c24xx_uda134x_snd_device */
s3c24xx_uda134x_snd_device =platform_device_alloc("soc-audio", -1);
if(!s3c24xx_uda134x_snd_device) {
printk(KERN_ERR"S3C24XX_UDA134XSoC Audio: "
"Unable to register\n");
return-ENOMEM;
}
/*s3c24xx_uda134x_snd_device->dev->p->driver= s3c24xx_uda134x_snd_devdata */
/*将s3c24xx_uda134x_snd_devdata这个全局变量赋给s3c24xx_uda134x_snd_device的私有数据 */
platform_set_drvdata(s3c24xx_uda134x_snd_device,
&s3c24xx_uda134x_snd_devdata);
s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
/*将刚才分配的那个name成员为"soc-audio"的platform_device注册到内核中*/
ret= platform_device_add(s3c24xx_uda134x_snd_device);
if(ret) {
printk(KERN_ERR"S3C24XX_UDA134XSoC Audio: Unable to add\n");
platform_device_put(s3c24xx_uda134x_snd_device);
}
returnret;
}
看到这里我们发现,已经出现了一个platform_driver和两个platform_device,这一个platform_driver的driver->name成员是"s3c24xx_uda134x",这两个platform_device的name成员变量一个是"s3c24xx_uda134x",另外一个是"soc-audio",那么这个成员变量name为"soc-audio"的platform_device和哪个platform_driver匹配呢?还是老办法,搜索。
static struct platform_driver soc_driver = {
.driver = {
.name = "soc-audio",
.owner = THIS_MODULE,
.pm = &soc_pm_ops,
},
.probe = soc_probe,
.remove = soc_remove,
};
这样,s3c24xx_uda134x_snd_device就和soc_driver匹配成功,匹配成功则调用probe函数,这里的probe函数为soc_probe。
static int soc_probe(struct platform_device*pdev)
{
intret = 0;
/*将s3c24xx_uda134x_probe函数中设置的私有变量s3c24xx_uda134x_snd_devdata取出来,赋给socdev,即socdev = s3c24xx_uda134x_snd_devdata */
structsnd_soc_device *socdev = platform_get_drvdata(pdev);
structsnd_soc_card *card = socdev->card;
/*Bodge while we push things out of socdev */
/*这里实质上是card_socdev= s3c24xx_uda134x_snd_devdata */
card->socdev= socdev;
/*Bodge while we unpick instantiation */
card->dev= &pdev->dev;
/*想内核注册一个声卡,声卡card= socdev->card = snd_soc_s3c24xx_uda134x*/
ret= snd_soc_register_card(card);
if(ret != 0) {
dev_err(&pdev->dev,"Failed to register card\n");
returnret;
}
return0;
}到此,我们S3C2440上的UDA134x驱动初始化的主要步骤就完成了。后面再深入分析。
849

被折叠的 条评论
为什么被折叠?



