第一范文网 - 专业文章范例文档资料分享平台

alsa(audio)驱动分析

来源:用户分享 时间:2025/5/19 15:15:54 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

How to Mount Maemo File System——Guide System Analysis and Design Documents 31:8->0:reserved;7:0(TTSA)->0b0011:表示在那个time slot里面是传输数据的0,不传输,1传输; SSRSA_P3==__REG(0x41900034):3——》0011

31:8 :reserved;7:0(RTSA)-》0:表示在那个slot里面接收数据,0,不接受,1 接收; SSACD_P3==__REG(0x4190003C):60——》0110,0000

31:8:reserved;7(SCDX8)-》0:sysclk/4产生内部audio clock,1,sysclk/8产生audio clock; 6:4(ACPS)-》0b110:PLL输出时钟由Audio clock dither Divider register value决定; 3(SCDB)-》0:如果SCDX8为0则scdx8决定,为1,则sysclk不分频; 2:0(ACDS)-》0:表示clock divider select 为/1;

SSACDD_P3==__REG(0x41900040):6590040——》0000,0110,0101,1001,0000,0000,0100,0000 31:reserved;30:16(NUM)-》1625;除数(0x659) 15:12:reserved;11:0(DEN)-》64:被除数 比如我们的板子上是这样计算这些值的:

比如,在我们的机子上的一个实例是这样的,

那么第一步取得采样率:48K,它也就是Sync clock; 第二步球的bit率:48X64=3.072M

第三步求的sysclk:这个根据scdx8决定是X4还是X8,在我们的例子中是4,所以:3.072X4=12.288 第四步求得我们要的dither divider y,公式为: 624*(y)/2=12.288,

算出y=0.039384615384615384615384615384615 所以查可能的分子和分母表,得出,分子是: 64,分母是1625 如下图所示:

Issue: <0.5> Issue Date: <10/29/2007> 当然更加详细的请参阅spec;

?Tech, 2005

Page 13 of 22

How to Mount Maemo File System——Guide System Analysis and Design Documents

第二段是平台级别的,主要是对于DMA的初始化;

第三段是codec级别的,这里主要是对codec本身的设置,通过i2c接口对codec的寄存器操作,比如采样率等等; 最后面还有一个poweron的函数,这个函数前面有提到,但是没有详细分析,这里分析一下: 首先根据事件类型,决定是关闭门序列,还是启动门序列,我只分析启动过程;

得到启动序列,就开始遍历整个序列,对于这个序列的每一个类型,查找所有的门的序列,直到有一个门的类型和当前启动序列的类型相同,然后再根据不同的类型做不同的检查和power: 1,如果是snd_soc_dapm_vmid则继续,不做任何处理; 2, A)如果是snd_soc_dapm_adc,并且其active为1,这个active在上一步已经分析过了,必须要包含这个流的名字的sname的门才会被激活,假设我们现在讨论的是用pcm通道播放声音,那么流的名字就是“Voice Playback”,所以,将置有dac3的active被设成1,这样就避免了power on dac1,dac2,和adc了。如果这两个条件都满足,那么必然是“Voice Capture”了,因为只有这时候,我们才会用到adc,现在看看,如果用了adc将会启动什么,于是调用函数is_connected_input_ep,这是一个通用递归函数,从名字上来说就是看是否是已经连接了输入的门,我们只考虑adc的情况,其余的情况待会再讨论,对于adc,在

is_connected_input_ep函数里面,是通过遍历所有以这个门作为sink的source门(list_for_each_entry(path, &widget->sources, list_sink),可以看到,这里的最后一个参数是list_sink,而第二个参数却是

widget->sources,这个原因我在“门连接分析”页里面已经分析过了,总之sources就表示这个门的sources列表,而sinks就是这个门的sink列表),通过递归调用is_connected_input_ep来查看这些source门是否其中有一个是连通的,返回的是所有是否连通的和(联通为1,否则为0),所以返回的结果可能是大于1的数,表示不只一个源是联通的。

B)如果这个函数返回为真则表示此adc是联通的,于是调用dapm_update_bits来处理,这个函数过对mux(它的reg<0),input,output,mic,hp,line,spk,不做任何处理就返回了;过了这一关,开始查是否men的revert为真,如果为真,则把power取反,原来为真现在变假,于是调用snd_soc_read

(micco_soc_read)开始读这个寄存器的值(注意,这里读的值是可能和物理上的这个寄存器的值不一样的,这里读的值是cache里面的值),读出来后强制把1<reg, new)把值写到cache里面(实际负责写的是

micco_soc_write,而且,它对于0x70+0x15以下包含0x15的值是直接写到寄存器的地址的,否则只是些到数组cache里面去)好对于adc的情况我们就分析完了。 3,

A)如果此类型是snd_soc_dapm_dac并且active为1,则调用is_connected_output_ep来取得是否要power,下面来看看函数is_connected_output_ep,这也是一个通用的判断是否有连接到输出的递归函数,我们只分析dac的情况,list_for_each_entry(path, &widget->sinks, list_source),上面已经讲过,这里实际上查的是这个门的所有的sink列表,通过递归调用is_connected_output_ep来看是否它的sink是联通的,只要有一条路是联通的,则power为真。

B)返回后调用dapm_update_bits来处理,上面已经分析过了,这个函数就是判断是否需要设置此门的寄存器的1<

4,如果此类型是snd_soc_dapm_pga,则调用is_connected_input_ep来判断是否联通输入,再调用

is_connected_output_ep判断是否联通输出,对于pga is_connected_input_ep函数的处理和adc是一样的,对于is_connected_output_ep和dac的处理是一样的,接着调用dapm_set_pga,根据power的值决定是mute pga还是启用pga,但是就我打印的结果来看,基本上这个函数所起的作用为0,因为对于pga的门似乎都没有设置相应的control,最后调用dapm_update_bits,设置power 位。

5,对于other widget,这里在我们的平台上多半是指mux,首先调用is_connected_input_ep判断是否连接输入,再调用is_connected_output_ep判断是否有输出,调用dapm_update_bits位设置power 位,最后调用w->event(do_post_event)来进行后期处理,这里主要就是对mux进行寄存器设置,因为mux的寄存器的地址都是大于0x70+0x15的,所以它们的地址需要转化,这个函数就是根据mux的类型,访问不同的寄存器。

基本上prepare后,一切就都就绪了,只等一个trigger;而trigger的执行会在上层的alsalib调用write的函数触发;

?Tech, 2005

Page 14 of 22

Issue: <0.5> Issue Date: <10/29/2007> How to Mount Maemo File System——Guide System Analysis and Design Documents Issue: <0.5> Issue Date: <10/29/2007> ?Tech, 2005 Page 15 of 22

4.1.4

write的流程

How to Mount Maemo File System——Guide System Analysis and Design Documents snd_pcm_playback_ioctl Issue: <0.5> Issue Date: <10/29/2007> snd_pcm_playback_ioctl1case SNDRV_PCM_IOCTL_WRITEN_FRAMESsnd_pcm_lib_writevsnd_pcm_lib_write1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_writev_transfer)(runtime->status->state == SNDRV_PCM_STATE_PREPAREDtransfer(substream, appl_ofs, data, offset, frames)这个transfer就是snd_pcm_lib_writev_transfersnd_pcm_startsnd_pcm_lib_writev_transfersnd_pcm_action(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING)这里是在pxa3xx_pcm_preallocate_dma_buffer的时候分配的DMA空间copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)这里把用户层的数据copy到内核层,而这个地址就是用DMA分配的cpu地址,左边分配的地址被使用的地址snd_pcm_pre_startsnd_pcm_do_startsnd_pcm_post_startsubstream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);

?Tech, 2005

Page 16 of 22

搜索更多关于: alsa(audio)驱动分析 的文档
alsa(audio)驱动分析.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c19fli5ekjq5a66i6tkx2_4.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top