创建声卡

可以在/proc/asound查看系统使用的声卡.

以7715芯片为例

shell@scx15_sp7715ga:/proc/asound $ ll
lrwxrwxrwx root     root              2014-09-06 00:56 VIRTUALAUDIOW -> card1
lrwxrwxrwx root     root              2014-09-06 00:56 alli2s -> card3
dr-xr-xr-x root     root              2014-09-06 00:56 card0
dr-xr-xr-x root     root              2014-09-06 00:56 card1
dr-xr-xr-x root     root              2014-09-06 00:56 card2
dr-xr-xr-x root     root              2014-09-06 00:56 card3
-r--r--r-- root     root            0 2014-09-06 00:56 cards
-r--r--r-- root     root            0 2014-09-06 00:56 devices
-r--r--r-- root     root            0 2014-09-06 00:56 pcm
lrwxrwxrwx root     root              2014-09-06 00:56 saudiovoip -> card2
lrwxrwxrwx root     root              2014-09-06 00:56 sprdphone -> card0
-r--r--r-- root     root            0 2014-09-06 00:56 timers
-r--r--r-- root     root            0 2014-09-06 00:56 version

这里有四张声卡。

接下来看声卡的创建过程

sound card

注册声卡使用 snd_card_register接口,这个函数被调用四次,分别注册上面的4个声卡

card 1 

snd_card_register card->number 1 driver VIRTUAL AUDIO W
c0 CPU: 0 PID: 65 Comm: saudio-2-10 Tainted: G        W    3.10.17-dirty #3
snd_card_register
saudio_snd_init_card
saudio_ctrl_thread

card 2

snd_card_register card->number 2 driver saudiovoip
c0 CPU: 0 PID: 69 Comm: saudio-2-14 Tainted: G        W    3.10.17-dirty #3
snd_card_register
saudio_snd_init_card
saudio_ctrl_thread

card 0

snd_card_register card->number 0 driver sprdphone                                                                                       
c0 CPU: 0 PID: 1 Comm: swapper Tainted: G        W    3.10.17-dirty #3
c0 [<c0013a1c>] (unwind_backtrace+0x0/0x11c) from [<c0012174>] (show_stack+0x10/0x14)
c0 [<c0012174>] (show_stack+0x10/0x14) from [<c03da6d8>] (snd_card_register+0x150/0x214)
c0 [<c03da6d8>] (snd_card_register+0x150/0x214) from [<c03f4dc8>] (snd_soc_register_card+0x10dc/0x11b8)
c0 [<c03f4dc8>] (snd_soc_register_card+0x10dc/0x11b8) from [<c0288eb4>] (platform_drv_probe+0x14/0x18)
c0 [<c0288eb4>] (platform_drv_probe+0x14/0x18) from [<c0287ba4>] (driver_probe_device+0x11c/0x330)
c0 [<c0287ba4>] (driver_probe_device+0x11c/0x330) from [<c0286020>] (bus_for_each_drv+0x48/0x8c)
c0 [<c0286020>] (bus_for_each_drv+0x48/0x8c) from [<c0287a10>] (device_attach+0x64/0x88)
c0 [<c0287a10>] (device_attach+0x64/0x88) from [<c0286f44>] (bus_probe_device+0x28/0x98)
c0 [<c0286f44>] (bus_probe_device+0x28/0x98) from [<c0285580>] (device_add+0x3f4/0x5a8)
c0 [<c0285580>] (device_add+0x3f4/0x5a8) from [<c0289400>] (platform_device_add+0x168/0x200)
c0 [<c0289400>] (platform_device_add+0x168/0x200) from [<c028960c>] (platform_add_devices+0x20/0x5c)
c0 [<c028960c>] (platform_add_devices+0x20/0x5c) from [<c07904a0>] (init_machine_late+0x1c/0x28)
c0 [<c07904a0>] (init_machine_late+0x1c/0x28) from [<c0009470>] (do_one_initcall_debug+0x34/0xac)
c0 [<c0009470>] (do_one_initcall_debug+0x34/0xac) from [<c0009524>] (do_one_initcall+0x28/0xbc)
c0 [<c0009524>] (do_one_initcall+0x28/0xbc) from [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac)
c0 [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac) from [<c055cdd0>] (kernel_init+0x8/0xe4)
c0 [<c055cdd0>] (kernel_init+0x8/0xe4) from [<c000f4d8>] (ret_from_fork+0x14/0x3c)

card 3

snd_card_register card->number 3 driver all-i2s shortname all-i2s longname all-i2s
c0 CPU: 0 PID: 1 Comm: swapper Tainted: G        W    3.10.17-dirty #3
c0 [<c0013a1c>] (unwind_backtrace+0x0/0x11c) from [<c0012174>] (show_stack+0x10/0x14)
c0 [<c0012174>] (show_stack+0x10/0x14) from [<c03da6d8>] (snd_card_register+0x150/0x214)
c0 [<c03da6d8>] (snd_card_register+0x150/0x214) from [<c03f4dc8>] (snd_soc_register_card+0x10dc/0x11b8)
c0 [<c03f4dc8>] (snd_soc_register_card+0x10dc/0x11b8) from [<c0288eb4>] (platform_drv_probe+0x14/0x18)
c0 [<c0288eb4>] (platform_drv_probe+0x14/0x18) from [<c0287ba4>] (driver_probe_device+0x11c/0x330)
c0 [<c0287ba4>] (driver_probe_device+0x11c/0x330) from [<c0286020>] (bus_for_each_drv+0x48/0x8c)
c0 [<c0286020>] (bus_for_each_drv+0x48/0x8c) from [<c0287a10>] (device_attach+0x64/0x88)
c0 [<c0287a10>] (device_attach+0x64/0x88) from [<c0286f44>] (bus_probe_device+0x28/0x98)
c0 [<c0286f44>] (bus_probe_device+0x28/0x98) from [<c0285580>] (device_add+0x3f4/0x5a8)
c0 [<c0285580>] (device_add+0x3f4/0x5a8) from [<c0289400>] (platform_device_add+0x168/0x200)
c0 [<c0289400>] (platform_device_add+0x168/0x200) from [<c028960c>] (platform_add_devices+0x20/0x5c)
c0 [<c028960c>] (platform_add_devices+0x20/0x5c) from [<c07904a0>] (init_machine_late+0x1c/0x28)
c0 [<c07904a0>] (init_machine_late+0x1c/0x28) from [<c0009470>] (do_one_initcall_debug+0x34/0xac)
c0 [<c0009470>] (do_one_initcall_debug+0x34/0xac) from [<c0009524>] (do_one_initcall+0x28/0xbc)
c0 [<c0009524>] (do_one_initcall+0x28/0xbc) from [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac)
c0 [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac) from [<c055cdd0>] (kernel_init+0x8/0xe4)
c0 [<c055cdd0>] (kernel_init+0x8/0xe4) from [<c000f4d8>] (ret_from_fork+0x14/0x3c)
接下来一card0注册分析snd_soc_register_card的流程

snd_soc_register_card

先把card 0注册的相关的代码贴出来
static struct snd_soc_dai_link vbc_r2p0_codec_v3_dai[] = {
    {
     .name = "vbc(r2)-codec(v3)-ap",
     .stream_name = "HiFi",

     .codec_name = "sprd-codec-v3",
     .platform_name = "sprd-pcm-audio",
     .cpu_dai_name = "vbc-r2p0",
     .codec_dai_name = "sprd-codec-v3-i2s",
     },
#ifdef CONFIG_SND_SOC_SPRD_VAUDIO
    {
     .name = "vbc(r2)-codec(v3)-dsp",
     .stream_name = "Voice",

     .codec_name = "sprd-codec-v3",
     .platform_name = "sprd-pcm-audio",
     .cpu_dai_name = "vaudio",
     .codec_dai_name = "sprd-codec-v3-vaudio",
     },
#endif
    {
     .name = "aux-captrue",
     .stream_name = "AuxRecord",

     .codec_name = "sprd-codec-v3",
     .platform_name = "sprd-pcm-audio",
     .cpu_dai_name = "vbc-r2p0-ad23",
     .codec_dai_name = "codec-i2s-ext",
     },
#ifdef CONFIG_SND_SOC_SPRD_VAUDIO
    {
     .name = "aux-dsp-captrue",
     .stream_name = "AuxDSPCaptrue",

     .codec_name = "sprd-codec-v3",
     .platform_name = "sprd-pcm-audio",
     .cpu_dai_name = "vaudio-ad23",
     .codec_dai_name = "codec-vaudio-ext",
     },
#endif
    {
     .name = "vbc(r2)-dfm",
     .stream_name = "Dfm",

     .codec_name = "sprd-codec-v3",
     .platform_name = "sprd-pcm-audio",
     .cpu_dai_name = "vbc-dfm",
     .codec_dai_name = "sprd-codec-v3-fm",
     .ops = &dfm_ops,
     },
}; 

static struct snd_soc_card vbc_r2p0_codec_v3_card = {                                                                                                                                                                                        
    .name = "sprdphone",
    .dai_link = vbc_r2p0_codec_v3_dai,
    .num_links = ARRAY_SIZE(vbc_r2p0_codec_v3_dai),
    .owner = THIS_MODULE,

    .controls = vbc_r2p0_codec_v3_controls,
    .num_controls = ARRAY_SIZE(vbc_r2p0_codec_v3_controls),
    .dapm_widgets = sprd_codec_dapm_widgets,
    .num_dapm_widgets = ARRAY_SIZE(sprd_codec_dapm_widgets),
    .dapm_routes = vbc_r2p0_codec_v3_map,
    .num_dapm_routes = ARRAY_SIZE(vbc_r2p0_codec_v3_map),
    .late_probe = board_late_probe,
};

static int sprd_asoc_probe(struct platform_device *pdev,                                                                                                                                                                                     
               struct snd_soc_card *card)
{
    snd_soc_register_card(card);
}

static int vbc_r2p0_codec_v3_probe(struct platform_device *pdev)
{
    return sprd_asoc_probe(pdev, &vbc_r2p0_codec_v3_card);
}

static struct platform_driver vbc_r2p0_codec_v3_driver = { 
    .driver = { 
           .name = "vbc-r2p0-sprd-codec-v3",
           .owner = THIS_MODULE,
           .pm = &snd_soc_pm_ops,
           .of_match_table = of_match_ptr(vbc_r2p0_codec_v3_of_match),
           },  
    .probe = vbc_r2p0_codec_v3_probe,
    .remove = sprd_asoc_remove,
    .shutdown = sprd_asoc_shutdown,
};

module_platform_driver(vbc_r2p0_codec_v3_driver);
看snd_soc_register_card这个函数
snd_soc_register_card
{
    for (i = 0; i < card->num_links; i++) 
        card->rtd[i].dai_link = &card->dai_link[i];

    snd_soc_instantiate_card(card);
}

static int snd_soc_instantiate_card(struct snd_soc_card *card)                                                                                                                                                                               
{
    /* bind DAIs */
    for (i = 0; i < card->num_links; i++) {
        ret = soc_bind_dai_link(card, i);
        if (ret != 0)
            goto base_error;
    }

    for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
            order++) {
        for (i = 0; i < card->num_links; i++) {
            ret = soc_probe_link_dais(card, i, order);                                                                                                                                                                                       
            if (ret < 0) { 
                dev_err(card->dev,
                    "ASoC: failed to instantiate card %d\n",
                    ret);
                goto probe_dai_err;
            }    
        }    
    }    
}

soc_bind_dai_link
{
    /* Find CPU DAI from registered DAIs*/
    list_for_each_entry(cpu_dai, &dai_list, list) {
        if (dai_link->cpu_of_node &&
            (cpu_dai->dev->of_node != dai_link->cpu_of_node))
            continue;
        if (dai_link->cpu_name &&
            strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name))
            continue;
        if (dai_link->cpu_dai_name &&
            strcmp(cpu_dai->name, dai_link->cpu_dai_name))
            continue;


        rtd->cpu_dai = cpu_dai;
    }  

    rtd->codec = codec;
    rtd->codec_dai = codec_dai;
    rtd->platform = platform;
}
snd_soc_register_card中最主要的是调用snd_soc_instantiate_card
snd_soc_instantiate_card中有一些比较重要的函数,如soc_bind_dai_link和soc_probe_link_dais。后面在分析soc_probe_link_dais

看soc_bind_dai_link,主要是从注册的dai driver\platform driver和codec 找到与该dai_link对应的驱动。匹配主要是通过name进行

以dai为例,看下dai_list怎么来的

dai_list

dai_list来自两个接口snd_soc_register_dais/snd_soc_register_dai
上层通过snd_soc_register_codec/snd_soc_register_component调用上面两个函数注册dai driver

c0 [<c0012174>] (show_stack+0x10/0x14) from [<c03f1010>] (snd_soc_register_dais+0x174/0x220)
c0 [<c03f1010>] (snd_soc_register_dais+0x174/0x220) from [<c03f16f0>] (snd_soc_register_codec+0x1f8/0x2e0)
c0 [<c03f16f0>] (snd_soc_register_codec+0x1f8/0x2e0) from [<c040bd90>] (sprd_codec_probe+0x194/0x32c)
c0 [<c040bd90>] (sprd_codec_probe+0x194/0x32c) from [<c0288eb4>] (platform_drv_probe+0x14/0x18)
c0 [<c0288eb4>] (platform_drv_probe+0x14/0x18) from [<c0287ba4>] (driver_probe_device+0x11c/0x330)
c0 [<c0287ba4>] (driver_probe_device+0x11c/0x330) from [<c0286020>] (bus_for_each_drv+0x48/0x8c)
c0 [<c0286020>] (bus_for_each_drv+0x48/0x8c) from [<c0287a10>] (device_attach+0x64/0x88)
c0 [<c0287a10>] (device_attach+0x64/0x88) from [<c0286f44>] (bus_probe_device+0x28/0x98)
c0 [<c0286f44>] (bus_probe_device+0x28/0x98) from [<c0285580>] (device_add+0x3f4/0x5a8)
c0 [<c0285580>] (device_add+0x3f4/0x5a8) from [<c0289400>] (platform_device_add+0x168/0x200)
c0 [<c0289400>] (platform_device_add+0x168/0x200) from [<c028960c>] (platform_add_devices+0x20/0x5c)
c0 [<c028960c>] (platform_add_devices+0x20/0x5c) from [<c07904a0>] (init_machine_late+0x1c/0x28)
c0 [<c07904a0>] (init_machine_late+0x1c/0x28) from [<c0009470>] (do_one_initcall_debug+0x34/0xac)
c0 [<c0009470>] (do_one_initcall_debug+0x34/0xac) from [<c0009524>] (do_one_initcall+0x28/0xbc)
c0 [<c0009524>] (do_one_initcall+0x28/0xbc) from [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac)
c0 [<c078eaf0>] (kernel_init_freeable+0xe4/0x1ac) from [<c055cdb4>] (kernel_init+0x8/0xe4)
c0 [<c055cdb4>] (kernel_init+0x8/0xe4) from [<c000f4d8>] (ret_from_fork+0x14/0x3c)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值