comip-lm49350.c 是CPU的音频模块+ codec lm49350 统一成一个整体的设备结构。他会先注册成一个platform device。
代码分析如下:
1. init/exit
static int __init comip_soc_init(void)
{
int ret;
printk(KERN_INFO "COMIP_LM49350 SoC Audio driver\n");
comip_snd_lm49350_device = platform_device_alloc("soc-audio", -1); //分配一块platform device 内存空间
if (!comip_snd_lm49350_device) {
printk(KERN_ERR "Platform device allocation failed\n");
return -ENOMEM;
}
platform_set_drvdata(comip_snd_lm49350_device, &comip_snd_devdata); //把comip_snd_devdata 设置进platform device中
comip_snd_devdata.dev = &comip_snd_lm49350_device->dev; //dev -> snd_soc_device.dev
ret = platform_device_add(comip_snd_lm49350_device); //添加platform 设备
if (ret) {
printk(KERN_ERR "COMIP_LM49350 Soc Audio: Unable to add \n");
platform_device_put(comip_snd_lm49350_device); //如失败,则去除platform设备
}
return ret;
}
module_init(comip_soc_init);
static void __exit comip_soc_exit(void)
{
platform_device_unregister(comip_snd_lm49350_device); //注销platform device
}
module_exit(comip_soc_exit);
static struct platform_device *comip_snd_lm49350_device; //定义platform设备,comip_snd_lm49350_device 最上层的数据结构
2.
struct snd_soc_device comip_snd_devdata; /* Audio subsystem */
static struct snd_soc_device comip_snd_devdata = {
.card = &snd_soc_comip, //卡card
.codec_dev = &soc_codec_dev_lm49350, //codec 设备 lm49350 操作。
};
snd_soc_device 原型 定义如下,代表一个SOC音频控制器和CODEC,即系统中的整个音频模块。/* SoC Device - the audio subsystem */
struct snd_soc_device {
struct device *dev;
struct snd_soc_card *card;
struct snd_soc_codec_device *codec_dev;
void *codec_data;
};
3. struct snd_soc_card snd_soc_comip : 代表一个 card/* Audio machine driver */
static struct snd_soc_card snd_soc_comip = {
.name = "COMIP_LM49350",
.platform = &comip_soc_platform,
.dai_link = comip_lm49350_dai,
.num_links = ARRAY_SIZE(comip_lm49350_dai),
};
snd_soc_card 原型定义如下:/* SoC card */
struct snd_soc_card {
char *name;
struct device *dev;
struct list_head list;
int instantiated;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
/* the pre and post PM functions are used to do any PM work before and
* after the codec and DAI's do any PM work. */
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
int (*resume_pre)(struct platform_device *pdev);
int (*resume_post)(struct platform_device *pdev);
/* callbacks */
int (*set_bias_level)(struct snd_soc_card *,
enum snd_soc_bias_level level);
long pmdown_time;
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link;
int num_links;
struct snd_soc_device *socdev;
struct snd_soc_codec *codec;
struct snd_soc_platform *platform;
struct delayed_work delayed_work;
struct work_struct deferred_resume_work;
};