devm_snd_soc_register_component 是音频驱动框架中比较关键的一个函数,单独分析下。
一、函数原型
/**
* devm_snd_soc_register_component - resource managed component registration
* @dev: Device used to manage component
* @cmpnt_drv: Component driver
* @dai_drv: DAI driver
* @num_dai: Number of DAIs to register
*
* Register a component with automatic unregistration when the device is
* unregistered.
*/
int devm_snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *cmpnt_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai)
{
struct device **ptr;
int ret;
ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
if (ret == 0) {
*ptr = dev;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return ret;
}
作用:构造一个component,并add到全局的component_list中,并将dai_driver与component建立联系。
二、函数实现(省略部分细节)
snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai)
{
struct snd_soc_component *component; // 创建一个component
... ...
snd_soc_add_component(dev, component, component_driver, dai_drv, num_dai)
{
snd_soc_component_initialize(component, component_driver, dev)
{
component->name = fmt_single_name(dev, &component->id);
component->dev = dev; // component->dev指向dev,即platform_device->dev
component->driver = driver; // component->driver指向component_driver
}
snd_soc_register_dais(component, dai_drv, num_dai)
{
// 一个component可以有多个dai_driver
for (i = 0; i < count; i++)
{
soc_add_dai(component, dai_drv + i, count == 1 && !component->driver->non_legacy_dai_naming)
{
struct snd_soc_dai *dai; // 创建一个soc_dai
dai->component = component; // dai->component指向component
dai->dev = dev; // dai->dev指向component->dev
dai->driver = dai_drv; // dai->driver指向dai_drv
list_add_tail(&dai->list, &component->dai_list); // 把dai->list加到component->dai_list中
}
}
}
snd_soc_component_add(component)
{
list_add(&component->list, &component_list); // 把component->list加入到全局的component_list中
}
// 暂时先跳过
snd_soc_try_rebind_card()
{
... ...
}
}
}