这里先分析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_FSpcm->component.debugfs_prefix = "dma";
#endifpcm->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;
}
以上代码可以得到这样一张链接关系图,都只是挂载到链表,并没有实际的注册动作