基于mini2440的Linux音频驱动完全解读(一)


根据内核打印的信息“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驱动初始化的主要步骤就完成了。后面再深入分析。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值