How to Mount Maemo File System——Guide System Analysis and Design Documents
这里面基本上只是画了最简单的逻辑,其实里面非常的复杂特别是函数snd_pcm_lib_write1,这里面有同步的操作,也就是要等到有空余的空间的时候才允许写,否则就要等待,唤醒是通过函数
snd_pcm_update_hw_ptr_post来做的,这个函数会在DMA传输完一帧的中断到来的时候被调用,用来更新 Issue: <0.5> Issue Date: <10/29/2007> 缓冲区指针;
其中trigger的逻辑如下:
soc_pcm_triggerif (platform-if (cpu_dai->pcm_ops->trigger)>ops.trigger)pxa3xx_pcm_triggerpxa3xx_ssp_triggercase SNDRV_PCM_TRSNDRV_PCM_TRIGIGGER_STARTGER_START:意思就是开始启动DDADR(prtd->dma_ch) = prtd-SSCR1_P(port) |= >dma_desc_array_phys;SSCR1_TSRE;ssp_enable(&ssp[cpDCSR(prtd-对于播放u_dai->id]);>dma_ch) = DCSR_RUN;我想这里有个就是启动DMA传送了,而dma_desc_array_phys的地址是在pxa3xx_pcm_open通过dma_alloc_writecombine分配的这个地址是bus地址,在linux里面估计就是物理地址 简单的说就是启动DMA,enable ssp口; ?Tech, 2005
Page 17 of 22
How to Mount Maemo File System——Guide System Analysis and Design Documents
Issue: <0.5> Issue Date: <10/29/2007> 简单总结一下,用户的使用流程;
A,调用snd_pcm_open打开设备节点对应的pcm流的substream也就是录音或者play;
B,调用snd_pcm_hw_params设置硬件参数,包括格式,通道,采样率,DMA空间的分配,中断的申请
等等,这里面会调用prepare函数使硬件准备好硬件,包括codec的寄存器设置,各种路径的建立,门的power on等;
C,调用write函数实现把数据写到设备里面去,这里会触发trigger函数也就是DMA的启动,SSP端口的启
动等。
5. Amixer调用的相关逻辑
我们的audio controller所调用的驱动的接口都是amixer 的cset,cget,所以有必要分析一下它的逻辑:
?Tech, 2005 Page 18 of 22
How to Mount Maemo File System——Guide System Analysis and Design Documents Issue: <0.5> Issue Date: <10/29/2007>
这里是调用amixser cset numid=20 5的流程Amixercsetsnd_ctl_opensnd_ctl_open_noupdatesnd_ctl_elem_writectl->ops-_snd_ctl_hw_open>element_write(ctl, control);调用.element_write = 设置snd_ctl_hw_elem_snd_ctl_hw_openwrite,SNDRV_FILE_COsnd_ctl_new(&ctl, NTROL,只是打SND_CTL_TYPE_ioctl(hw->fd, 开的control文件的HW, name)SNDRV_CTL_IO名字,比如/dev/snd_open_devicectl->ops = CTL_ELEM_WRIsnd/controlC0&snd_ctl_hw_ops;TE, control) < 0) 也就是说通过/dev下面的设备节点调用相应的ioctl,然后进入到内核的范围; ?Tech, 2005
Page 19 of 22
How to Mount Maemo File System——Guide System Analysis and Design Documents
Issue: <0.5> Issue Date: <10/29/2007> 内核层不同的control有不同的处理函数,对于两个stereo numid 的mux 是snd_soc_dapm_put_enum_double这些值其实是在men建立的时候就已经设好的snd_soc_dapm_put_enum_doublesnd_ctl_ioctlcase SNDRV_CTL_IOCTL_ELEM_WRITEreturn snd_ctl_elem_write_user(ctl, argp);dapm_mux_update_powersnd_soc_update_bitsif (widget->event_flags & SND_SOC_DAPM_POST_REG)snd_ctl_elem_writedapm_power_widgetssnd_soc_write(codec, reg, new);widget->event(widget, SND_SOC_DAPM_POST_REG);kctl->put(kctl, control)w->event(w, SND_SOC_DAPM_PRE_PMU)codec->write(codec, reg, value)对于muxer这里有对各个mux的处理 micco_soc_write(w->codec, MICCO_MUX_STEREO_CH1, 1<<(v_val));这里真正开始写寄存器,因为,传的地址为3加上一般俄base为0x70,所以最后的合成地址就是0x73,这刚好就是我们需要的地址了。这里才是实际相这些mux 寄存器地址写值的地方,而且我发现只要是mux几乎都会有这样的转换,几个mux相应的偏移地址分别为:#defineMICCO_MUX_MONO0x0#defineMICCO_MUX_BEAR0x1#defineMICCO_MUX_LINE_OUT0x2#defineMICCO_MUX_STEREO_CH10x3#defineMICCO_MUX_STEREO_CH20x4do_post_eventmicco_soc_writeif(v_val <=6)if (reg <= MICCO_SOFT_START_RAMP)这里的界限就是0x15就是21,其它的值留到后面去做,也就是do_post_event里面去做micco_write(MICCO_AUDIO_REG_BASE + reg, val);这里的基地址就是0x70这里只分析了控制函数为snd_soc_dapm_put_enum_double的处理逻辑,其它的都类似,而具体的应该是哪个处理函数来处理是在control的new的时候就已经确立了的,对于我们的平台其实在表micco_dapm_widgets建立的时候就已经确立了;
为了方便后来者的调试,我这里把各个numid的对应的控制函数都列出来了,如下: numid=1到12:snd_soc_put_volsw;
?Tech, 2005 Page 20 of 22
相关推荐: