这里先分析platform
对应的dts内容如下
i2s0_8ch: i2s@ff800000 {
compatible = "rockchip,rv1126-i2s-tdm";
reg = <0xff800000 0x1000>;
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru MCLK_I2S0_TX>, <&cru MCLK_I2S0_RX>, <&cru HCLK_I2S0>;
clock-names = "mclk_tx", "mclk_rx", "hclk";
dmas = <&dmac 20>, <&dmac 19>;
dma-names = "tx", "rx";
resets = <&cru SRST_I2S0_TX_M>, <&cru SRST_I2S0_RX_M>;
reset-names = "tx-m", "rx-m";
rockchip,cru = <&cru>;
rockchip,grf = <&grf>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0m0_sclk_tx
&i2s0m0_sclk_rx
&i2s0m0_lrck_tx
&i2s0m0_lrck_rx
&i2s0m0_sdi0
&i2s0m0_sdo0
&i2s0m0_sdo1_sdi3
&i2s0m0_sdo2_sdi2
&i2s0m0_sdo3_sdi1>;
status = "disabled";
};
&i2s0_8ch {
status = "okay";
#sound-dai-cells = <0>;
rockchip,clk-trcm = <0>;
rockchip,i2s-rx-route = <0 1 2 3>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0m0_lrck_rx
&i2s0m0_sclk_rx
&i2s0m0_sdi0>;
rockchip,capture-only;
};
对应的驱动代码位置
kernel/sound/soc/rockchip/rockchip_i2s_tdm.c
这里只关注alsa相关的代码
static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
{
...
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_tdm_component,
soc_dai, 1);
...
ret = rockchip_pcm_platform_register(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Could not register PCM\n");
return ret;
}
...
}
rockchip_i2s_tdm_probe()->devm_snd_soc_register_component()
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;
}
int snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
struct snd_soc_component *component;
component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
if (!component)
return -ENOMEM;
return snd_soc_add_component(dev, component, component_driver,
dai_drv, num_dai);
}
int snd_soc_add_component(struct device *dev,
struct snd_soc_component *component,
const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
int ret;
int i;
/* 初始化componment
* 关联dev和component_driver
*/
ret = snd_soc_component_initialize(component, component_driver, dev);
if (ret)
goto err_free;
if (component_driver->endianness) {
for (i = 0; i < num_dai; i++) {
convert_endianness_formats(&dai_drv[i].playback);
convert_endianness_formats(&dai_drv[i].capture);
}
}
/* 1. 创建dai
* 2. 关联component dev dai_drv
* 3. 将dai通过list挂载到component的dai_list
* 4. 更新component->num_dai
*/
ret = snd_soc_register_dais(component, dai_drv, num_dai);
if (ret < 0) {
dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
goto err_cleanup;
}
/* 将component通过list挂载到 component_list (全局) 上*/
snd_soc_component_add(component);
return 0;
err_cleanup:
snd_soc_component_cleanup(component);
err_free:
return ret;
}
rockchip_i2s_tdm_probe()->rockchip_pcm_platform_register()
int rockchip_pcm_platform_register(struct device *dev)
{
return devm_snd_dmaengine_pcm_register(dev, &rk_dmaengine_pcm_config,
SND_DMAENGINE_PCM_FLAG_COMPAT);
}
int devm_snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
struct device **ptr;
int ret;
ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = snd_dmaengine_pcm_register(dev, config, flags);
if (ret == 0) {
*ptr = dev;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return ret;
}
int snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
struct dmaengine_pcm *pcm;
int ret;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
#ifdef CONFIG_DEBUG_FS
pcm->component.debugfs_prefix = "dma";
#endif
pcm->config = config;
pcm->flags = flags;
/* dma相关
* 这里会关联到dma 获取dts中rx tx channel
* channel存放在pcm->chan[]数组
*/
ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
if (ret)
goto err_free_dma;
if (config && config->process)
ret = snd_soc_add_component(dev, &pcm->component,
&dmaengine_pcm_component_process,
NULL, 0);
else
/* 增加一个新的component 主要用于dma相关
* 同样component通过list挂载到 component_list (全局) 上
*/
ret = snd_soc_add_component(dev, &pcm->component,
&dmaengine_pcm_component, NULL, 0);
if (ret)
goto err_free_dma;
return 0;
err_free_dma:
dmaengine_pcm_release_chan(pcm);
kfree(pcm);
return ret;
}
以上代码可以得到这样一张链接关系图,都只是挂载到链表,并没有实际的注册动作