ASoc音频驱动框架

news/2024/12/29 7:38:25/

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那一套。


http://www.ppmy.cn/news/245870.html

相关文章

AdminEAP框架-集成Shiro安全认证

1、概述 AdminEAP为本人基于AdminLTE改造的后台管理框架&#xff0c;包含了基本的系统管理功能和各种交互demo&#xff0c;项目已经开源到Github&#xff0c;并部署到阿里云。 Github : https://github.com/bill1012/AdminEAP AdminEAP DEMO: http://www.admineap.com 本文介…

1149 Dangerous Goods Packaging(23行代码+详细注释)

分数 25 全屏浏览题目 切换布局 作者 CHEN, Yue 单位 浙江大学 When shipping goods with containers, we have to be careful not to pack some incompatible goods into the same container, or we might get ourselves in serious trouble. For example, oxidizing age…

Aurora自动驾驶安全案例框架

/ 导读 / 自动驾驶公司Aurora于2021年8月推出了有史以来第一个适用于自动驾驶卡车和乘用车的安全案例框架&#xff08;Safety Case Framework)初始版本&#xff0c;解决了自动驾驶卡车和乘用车的安全问题。这使Aurora成为目前业内唯一一家公开分享其安全案例框架的自动驾驶公司…

Android Orm框架(GreenDao)

GreenDao与Ormlite对比 Ormlite&#xff1a;简单好用&#xff0c;比较符合JavaEE开发者使用习惯&#xff0c;注解很方便&#xff1b; GreenDao&#xff1a;为Android大大优化 &#xff0c;最小的内存使用 &#xff0c;非常高的性能优势。 官网地址&#xff1a;http://greend…

Bee,一个ORM框架

Bee&#xff0c;一个ORM框架。一个十分钟即可学会用的框架&#xff0c;一个少编码量的ORM框架&#xff0c; 编码复杂度为O(1)&#xff0c;即用了Bee&#xff0c;你可以不用另外写dao代码。 Bee已对外开源&#xff0c;开源地址&#xff1a; https://github.com/automvc/bee …

SSM 单体框架 - 前端开发:用户和权限模块

用户管理 分页 & 条件查询用户数据 查询条件 1. 用户手机号 2. 注册时间,包含开始日期和结束日期日期选择器组件 在查询条件中使用了 Element UI 中的日期选择器&#xff1a;https://element.eleme.cn/#/zh-CN/component/date-picker#mo-ren-xian-shi-ri-qi 在测试项目…

ORM: 如何管理品牌的在线声誉?

在线名誉管理&#xff08; OnlineReputationManagement&#xff09;又名在线声誉管理 &#xff0c;简称为ORM&#xff0c;是针对线上展示信息进行优化和管理的行为手段。小马识途营销顾问认为在线声誉管理&#xff08;ORM&#xff09;结合了营销、公关和客户服务三种方式&#…

ORM

1. 什么是元类 在Python中一切皆对象&#xff0c;类也是一个对象&#xff0c;实例对象由类创建出来的&#xff0c;类是由元类创建出来的。简而言之&#xff0c;用来创建类的类就叫元类&#xff08;metaclass&#xff09;。 函数type其实就是一个元类&#xff0c;type就是Pytho…