ASoc音频驱动框架

ASoc音频框架

嵌入式系统使用的音频框架是Asoc,在alsa的基础上又封装了一套代码,针对嵌入式系统。

Asoc产生

x86是通过PCI,如下图:
x86声卡架构
嵌入式式下面接口,产生了ASoc。

嵌入式声卡架构
1)分为三个部分,platform,codec和machine
platform:提供主控芯片驱动
codec :提供音频芯片驱动
machine类似于单板,它选择哪个platform,哪一个codec;并且决定了platform和codec怎么连接。
2)播放与录音
播放:soc通过i2s把数字信号给音频芯片,音频转换成模拟播放起来。
录音:音频芯片把模拟信号转换成数字信号通过i2s接口传递给soc端

codec侧驱动

codec侧有I2S和I2C分别对应着结构体snd_soc_dai_driver和snd_soc_codec_driver。

1.1 snd_soc_dai_driver结构

384 static struct snd_soc_dai_driver uda1341_dai = {                                                         
385         .name = "uda1341-iis",                                                                           
386         /* playback capabilities */                                                                      
387         .playback = {                                                                                    
388                 .stream_name = "Playback",                                                               
389                 .channels_min = 1,                                                                       
390                 .channels_max = 2,                                                                       
391                 .rates = UDA134X_RATES,                                                                  
392                 .formats = UDA134X_FORMATS,                                                              
393         },                                                                                               
394         /* capture capabilities */                                                                       
395         .capture = {                                                                                     
396                 .stream_name = "Capture",                                                                
397                 .channels_min = 1,                                                                       
398                 .channels_max = 2,                                                                       
399                 .rates = UDA134X_RATES,                                                                  
400                 .formats = UDA134X_FORMATS,                                                              
401         },                                                                                                                                       
402         /* pcm operations */                                                                             
403         .ops = &uda1341_dai_ops,                                                                         
404 };

说明:

  1. 名字
  2. 参数(速率,格式)
  3. 函数(设置参数的接口)

1.2snd_soc_codec_driver

334 static struct snd_soc_codec_driver soc_codec_dev_uda1341 = {                    
335     .probe = uda1341_soc_probe,                                                 
336                                                                                 
337     /* UDA1341的寄存器不支持读操作                                              
338      * 要知道某个寄存器的当前值,                                                
339      * 只能在写入时保存起来                                                     
340      */                                                                         
341         .reg_cache_size = sizeof(uda1341_reg),                                  
342         .reg_word_size = sizeof(u8),                                            
343         .reg_cache_default = uda1341_reg,                                       
344         .reg_cache_step = 1,                                                    
345         .read  = uda1341_read_reg_cache,                                        
346         .write = uda1341_write_reg,  /* 写寄存器 */                                                                                              
347 };

说明:
读写寄存器

platform端

snd_soc_dai_driver

142 static struct snd_soc_dai_driver s3c2440_i2s_dai = {                                                     
143         .playback = {                                                                                    
144                 .channels_min = 2,                                                                       
145                 .channels_max = 2,                                                                       
146                 .rates = S3C24XX_I2S_RATES,                                                              
147                 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},     
148         .capture = {                                                                                     
149                 .channels_min = 2,                                                                       
150                 .channels_max = 2,                                                                       
151                 .rates = S3C24XX_I2S_RATES,                                                              
152                 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},     
153         .ops = &s3c2440_i2s_dai_ops,                                                                     
154 };  

132 static const struct snd_soc_dai_ops s3c2440_i2s_dai_ops = {                     
133         .hw_params      = s3c2440_i2s_hw_params,                                
134         .trigger        = s3c2440_i2s_trigger,                                                                                                   
135 };  

说明:
1)name
2)参数
3)函数(设置参数函数,启动数据传输)

snd_soc_platform_driver

数据结构,负责数据传输。

283 static struct snd_soc_platform_driver s3c2440_dma_platform = {                                                                                   
284         .ops            = &s3c2440_dma_ops,                                                              
285         .pcm_new        = s3c2440_dma_new,                                                               
286         .pcm_free       = s3c2440_dma_free,                                                              
287 };                                                                                                       
288    


230 static struct snd_pcm_ops s3c2440_dma_ops = {                                                                                                    
231         .open           = s3c2440_dma_open,                                     
232         .close          = s3c2440_dma_close,                                    
233         .ioctl          = snd_pcm_lib_ioctl,                                    
234         .hw_params      = s3c2440_dma_hw_params,                                
235         .prepare    = s3c2440_dma_prepare,                                      
236         .trigger        = s3c2440_dma_trigger,                                  
237         .pointer        = s3c2440_dma_pointer,                                  
238 };  


内核相关链表

dai_list、codec_list和platform_list三个链表
1)dai_list
snd_soc_dai_driver
2)codec_list
snd_soc_codec_driver
3)platform_list
snd_soc_platform_driver

machine

 22 static struct snd_soc_dai_link s3c2440_uda1341_dai_link = {                     
 23         .name = "100ask_UDA1341",                                               
 24         .stream_name = "100ask_UDA1341",                                        
 25         .codec_name = "wm8976-codec",                                           
 26         .codec_dai_name = "wm8976-iis",                                         
 27         .cpu_dai_name = "s3c2440-iis",                                          
 28         .ops = &s3c2440_uda1341_ops,                                            
 29         .platform_name  = "s3c2440-dma",                                        
 30 };                                                                              
 31                                                                                 
 32                                                                                 
 33 static struct snd_soc_card myalsa_card = {                                                                                                       
 34         .name = "S3C2440_UDA1341",                                              
 35         .owner = THIS_MODULE,                                                   
 36         .dai_link = &s3c2440_uda1341_dai_link,                                  
 37         .num_links = 1,                                                         
 38 };

Asoc的流程

 33 static struct snd_soc_card myalsa_card = {                                      
 34         .name = "S3C2440_UDA1341",                                              
 35         .owner = THIS_MODULE,                                                   
 36         .dai_link = &s3c2440_uda1341_dai_link,                                  
 37         .num_links = 1,                                                         
 38 };

 44 static struct platform_device asoc_dev = {                                      
 45     .name         = "soc-audio",                                                
 46     .id       = -1,                                                             
 47     .dev = {                                                                    
 48         .release = asoc_release,                                                
 49         },                                                                      
 50 };                                                                              
 51                                                                                 
 52 static int s3c2440_uda1341_init(void)                                                                                                            
 53 {                                                                               
 54         platform_set_drvdata(&asoc_dev, &myalsa_card);                          
 55     platform_device_register(&asoc_dev);                                        
 

myalsa_card作为私有数据(主要dai_link结构体),放入到platform_device,
通过platform_device_register把设备soc-audio加入到虚拟platform框架中,会导致soc-audio同名的driver被调用。

soc

执行sound/soc/soc-core.c

2013 static int soc_probe(struct platform_device *pdev)                                                                                              
2014 {                                                                               
2015         struct snd_soc_card *card = platform_get_drvdata(pdev);                 
2016         int ret = 0;                                                            
2017                                                                                 
2018         /*                                                                      
2019          * no card, so machine driver should be registering card                
2020          * we should not be here in that case so ret error                      
2021          */                                                                     
2022         if (!card)                                                              
2023                 return -EINVAL;                                                 
2024                                                                                 
2025         /* Bodge while we unpick instantiation */                               
2026         card->dev = &pdev->dev;                                                 
2027                                                                                 
2028         ret = snd_soc_register_card(card);                                      
2029         if (ret != 0) {                                                         
2030                 dev_err(&pdev->dev, "Failed to register card\n");               
2031                 return ret;                                                     
2032         }                                                                       
2033                                                                                 
2034         return 0;                                                               
2035 }  

platform_get_drvdata提取传递过来的私有数据,重新构造card。

3387 int snd_soc_register_card(struct snd_soc_card *card)                            
3388 {                                                                               
3389         int i;                                                                  
3390                                                                                 
3391         if (!card->name || !card->dev)                                                                                                          
3392                 return -EINVAL;                                                 
3393                                                                                 
3394         dev_set_drvdata(card->dev, card);                                       
3395                                                                                 
3396         snd_soc_initialize_card_lists(card);                                    
3397                                                                                 
3398         soc_init_card_debugfs(card);                                            
3399                                                                                 
3400         card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *                
3401                             (card->num_links + card->num_aux_devs),             
3402                             GFP_KERNEL);                                        
3403         if (card->rtd == NULL)                                                  
3404                 return -ENOMEM;                                                 
3405         card->rtd_aux = &card->rtd[card->num_links];                            
3406                                                                                 
3407         for (i = 0; i < card->num_links; i++)                                   
3408                 card->rtd[i].dai_link = &card->dai_link[i];                     
3409                                                                                 
3410         INIT_LIST_HEAD(&card->list);                                            
3411         card->instantiated = 0;                                                 
3412         mutex_init(&card->mutex);                                               
3413                                                                                 
3414         mutex_lock(&client_mutex);       
3415         list_add(&card->list, &card_list);                                      
3416         snd_soc_instantiate_cards();                                            
3417         mutex_unlock(&client_mutex);                                            
3418                                                                                 
3419         dev_dbg(card->dev, "Registered card '%s'\n", card->name);               
3420                                                                                 
3421         return 0;                                                                                                                               
3422 }            

进入3416行

2005 static void snd_soc_instantiate_cards(void)                                     
2006 {                                                                               
2007         struct snd_soc_card *card;                                              
2008         list_for_each_entry(card, &card_list, list)                             
2009                 snd_soc_instantiate_card(card);                                                                                                 
2010 } 

进入2009那个函数

1821 static void snd_soc_instantiate_card(struct snd_soc_card *card)                 
1822 {                                                                               
1823         struct snd_soc_codec *codec;                                            
1824         struct snd_soc_codec_conf *codec_conf;                                  
1825         enum snd_soc_compress_type compress_type;                               
1826         int ret, i;                                                             
1827                                                                                 
1828         mutex_lock(&card->mutex);                                               
1829                                                                                 
1830         if (card->instantiated) {                                               
1831                 mutex_unlock(&card->mutex);                                     
1832                 return;                                                         
1833         }                                                                       
1834                                                                                 
1835         /* bind DAIs */                                                         
1836         for (i = 0; i < card->num_links; i++)                                   
1837                 soc_bind_dai_link(card, i);                                     
1838                                                                                 
1839         /* bind completed ? */                                                  
1840         if (card->num_rtd != card->num_links) {                                 
1841                 mutex_unlock(&card->mutex);                                     
1842                 return;                                                                                                                         
1843         }                                                                       
1844                                                                                 
1845         /* initialize the register cache for each available codec */            
1846         list_for_each_entry(codec, &codec_list, list) {                         
1847                 if (codec->cache_init)                                          
1848                         continue;                                               
1849                 /* by default we don't override the compress_type */            
1850                 compress_type = 0;                                              
1851                 /* check to see if we need to override the compress_type */     
1852                 for (i = 0; i < card->num_configs; ++i) {                       
1853                         codec_conf = &card->codec_conf[i];                      
1854                         if (!strcmp(codec->name, codec_conf->dev_name)) {       
1855                                 compress_type = codec_conf->compress_type;      
1856                                 if (compress_type && compress_type                                                                              
1857                                     != codec->compress_type)                    
1858                                         break;                                  
1859                         }                                                       
1860                 }                                                               
1861                 ret = snd_soc_init_codec_cache(codec, compress_type);           
1862                 if (ret < 0) {                                                  
1863                         mutex_unlock(&card->mutex);                             
1864                         return;                                                 
1865                 }                                                               
1866         }                                                                       
1867                                                                                 
1868         /* card bind complete so register a sound card */                       
1869         ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,           
1870                         card->owner, 0, &card->snd_card);                       
1871         if (ret < 0) {                                                          
1872                 printk(KERN_ERR "asoc: can't create sound card for card %s\n",  
1873                         card->name);                                            
1874                 mutex_unlock(&card->mutex);                                     
1875                 return;                                                         
1876         }                                                                       
1877         card->snd_card->dev = card->dev;                                        
1878                                                                                 
1879         card->dapm.bias_level = SND_SOC_BIAS_OFF;                               
1880         card->dapm.dev = card->dev;                                             
1881         card->dapm.card = card;                                                 
1882         list_add(&card->dapm.list, &card->dapm_list);                           
1883                                                                                 
1884 #ifdef CONFIG_DEBUG_FS                                                          
1885         snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root);        
1886 #endif                                                                          
1887                                                                                 
1888 #ifdef CONFIG_PM_SLEEP                                                          
1889         /* deferred resume work */                                              
1890         INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);            
1891 #endif                                                                          
1892                                                                                 
1893         if (card->dapm_widgets)                                                 
1894                 snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,                                                                      
1895                                           card->num_dapm_widgets);              
1896                                                                                 
1897         /* initialise the sound card only once */                               
1898         if (card->probe) {               
1899                 ret = card->probe(card);                                        
1900                 if (ret < 0)                                                    
1901                         goto card_probe_error;                                  
1902         }                                                                       
1903                                                                                 
1904         for (i = 0; i < card->num_links; i++) {                                 
1905                 ret = soc_probe_dai_link(card, i);                              
1906                 if (ret < 0) {                                                  
1907                         pr_err("asoc: failed to instantiate card %s: %d\n",     
1908                                card->name, ret);                                
1909                         goto probe_dai_err;                                     
1910                 }                                                               
1911         }                                                                       
1912                                                                                 
1913         for (i = 0; i < card->num_aux_devs; i++) {                              
1914                 ret = soc_probe_aux_dev(card, i);                               
1915                 if (ret < 0) {                                                  
1916                         pr_err("asoc: failed to add auxiliary devices %s: %d\n",
1917                                card->name, ret);                                
1918                         goto probe_aux_dev_err;                                 
1919                 }                                                                                                                               
1920         }                                                                       
1921                                                                                 
1922         /* We should have a non-codec control add function but we don't */      
1923         if (card->controls)                                                     
1924                 snd_soc_add_controls(list_first_entry(&card->codec_dev_list,    
 1925                                                       struct snd_soc_codec,     
1926                                                       card_list),               
1927                                      card->controls,                            
1928                                      card->num_controls);                       
1929                                                                                 
1930         if (card->dapm_routes)                                                  
1931                 snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,         
1932                                         card->num_dapm_routes);                 
1933                                                                                 
1934         snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),  
1935                  "%s", card->name);                                             
1936         snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),    
1937                  "%s", card->long_name ? card->long_name : card->name);         
1938         snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),        
1939                  "%s", card->driver_name ? card->driver_name : card->name);     
1940         for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {              
1941                 switch (card->snd_card->driver[i]) {                            
1942                 case '_':                                                       
1943                 case '-':                                                       
1944                 case '\0':                                                      
1945                         break;                                                  
1946                 default:                                                                                                                        
1947                         if (!isalnum(card->snd_card->driver[i]))                
1948                                 card->snd_card->driver[i] = '_';                
1949                         break;                                                  
1950                 }                                                               
1951         }      
  1953         if (card->late_probe) {                                                 
1954                 ret = card->late_probe(card);                                   
1955                 if (ret < 0) {                                                  
1956                         dev_err(card->dev, "%s late_probe() failed: %d\n",      
1957                                 card->name, ret);                               
1958                         goto probe_aux_dev_err;                                 
1959                 }                                                               
1960         }                                                                       
1961                                                                                 
1962         ret = snd_card_register(card->snd_card);                                
1963         if (ret < 0) {                                                          
1964                 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
1965                 goto probe_aux_dev_err;                                         
1966         }                                                                       
1967                                                                                 
1968 #ifdef CONFIG_SND_SOC_AC97_BUS                                                  
1969         /* register any AC97 codecs */                                          
1970         for (i = 0; i < card->num_rtd; i++) {                                   
1971                 ret = soc_register_ac97_dai_link(&card->rtd[i]);                
1972                 if (ret < 0) {                                                  
1973                         printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
1974                         while (--i >= 0)                                                                                                        
1975                                 soc_unregister_ac97_dai_link(card->rtd[i].codec);
1976                         goto probe_aux_dev_err;                                 
1977                 }                                                               
1978         }                                                                       
1979 #endif  
                                               

在1836行绑定指定dai,在1869行创建,在1962行注册。
概括:分配/设置/注册snd_card。进入alsa那一套。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值