alsa驅(qū)動(dòng)分析(2.6.21內(nèi)核)之二
4.??????????????通常的使用流程的分析
通常使用alsalib來(lái)播放聲音包括以下幾個(gè)步驟:
1,?? open,這個(gè)和oss相同,對(duì)應(yīng)于alsa就是snd_pcm_open;
2,?? param設(shè)置,這個(gè)就是snd_pcm_hw_params;
3,?? 上層的alsa在設(shè)置param的成功以后或者出錯(cuò)的時(shí)候恢復(fù)都需要調(diào)用snd_pcm_prepare;
4,?? write函數(shù);
現(xiàn)在一個(gè)個(gè)的來(lái)看;
4.1.1?????????open過(guò)程介紹
如下圖所示:
???????? 就是我先前說(shuō)的分成三部分,先是cpu級(jí)別的,包括clock的enabe,中斷的申請(qǐng),空間的申請(qǐng);
???????? 然后就是平臺(tái)級(jí)別的包括DMA所需要的空間的分配等;
???????? 不過(guò)這里codec級(jí)別的沒(méi)有提供相關(guān)的函數(shù),由machine提供了一些函數(shù)主要是設(shè)置channel,格式,頻率范圍等等;
4.1.2?????????snd_pcm_hw_params流程分析
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
???????? 流程就是這樣,至于里面做的具體的事情,我覺(jué)得只需要對(duì)照spec看看就知道了,具體的寄存器設(shè)置下面有一點(diǎn)講解,主要是格式的設(shè)置(采樣率的設(shè)置會(huì)留到prepare的時(shí)候),至于中斷上來(lái)的時(shí)候那個(gè)更新hw_ptr函數(shù)很有用,這樣上層就可以知道數(shù)據(jù)到底寫(xiě)了多少或者說(shuō)還有多少空間可以寫(xiě);
?
4.1.3?????????prepare流程分析
?
當(dāng)alsa層調(diào)用snd_pcm_prepare的時(shí)候會(huì)觸發(fā)驅(qū)動(dòng)對(duì)應(yīng)的prepare的函數(shù)執(zhí)行,如下:
可以看出基本上還是分為了三段,一段是cpu級(jí)別的,主要是對(duì)于ssp port的設(shè)置,具體設(shè)置如下:
對(duì)于voice通道,littleton_micco_voice_prepare的設(shè)置:
the sscr0 0xc0163f,sscr10xf01dc0,sspsp 0x800085
其中對(duì)于pcm的ssp地址是:
#define SSCR0_P4???????__REG(0x41A00000)? /* SSP Port 4 Control Register 0*/
#define SSCR1_P4???????__REG(0x41A00004)? /* SSP Port 4 Control Register 1*/
#define SSPSP_P4???????__REG(0x41A0002C)?/* SSP Port 4 Programmable Serial Protocol */
所以結(jié)果就相當(dāng)于:
?SSCR0_P4 0x41A00000:0xc0163f——》0000,0000,1100,0000,0001,0110,0011,1111
對(duì)于這個(gè)地址高8位為0,
31 (MOD)-》0:普通模式;30(ACS)-》0:時(shí)鐘選擇是由NCS和ECS位絕決定,看后面;
29(FPCKE)-》0:FIFO packing mode disabled;28()-》0:reserved
27(52MM)-》0:13mbps模式;26:24(FRDC)-》0:每幀的時(shí)隙數(shù)
23(TIM)->1:表示禁止傳輸fifo underrun中斷;22(RIM)-》1:表示禁止接收f(shuō)ifo overrun中斷
21(NCS)->0:表示時(shí)鐘選擇由ECS決定;20(EDSS)-》0:表示前面填充DSS來(lái)達(dá)到8-16位
19:8(SCR)-》0x16:決定串口bit率,=sspx clock/(scr+1)???;7(SSE)-》0:表示disable port
6(ECS)-》0:表示片內(nèi)的時(shí)鐘用來(lái)計(jì)算serial clock rate;5:4(FRF)-》0b11:表示psp模式用來(lái)模擬I2S協(xié)議
3:0(DSS)-》0b1111:表示16bit數(shù)據(jù)(EDSS為0)
?
SSCR1_P4 0x41A00004:? 0xf01dc0——》0000,0000,1111,0000,0001,1101,1100,0000
對(duì)于這個(gè)地址高8位也為0,
31(TTELP)-》0:表示最后一個(gè)bit傳輸(LSB)傳完后有半個(gè)時(shí)鐘處于高阻(三態(tài))狀態(tài);
30(TTE)-》0:表示傳輸信號(hào)不是三態(tài)的;29(EBCEI)-》0:bit傳輸錯(cuò)誤不產(chǎn)生中斷
28(SCFR)-》0:表示SSPSCLK的時(shí)鐘信號(hào)需要連續(xù)的工作,主模式ignore;27(ECRA)-》0:表示禁止其它ssp向它發(fā)起始終請(qǐng)求
26(ECRB)-》0:表示同27;25(SCLKDIR)-》0:表示主模式,SSP端口,驅(qū)動(dòng)SSPSCLK;
24(SFRMDIR)-》0:表示主模式,SSP端口,驅(qū)動(dòng)SSPSFRM信號(hào);
23(RWOT)-》1:表示只接收不傳輸???;22(TRAIL)-》1:表示trailing bytes 由dma burst來(lái)處理;
21(TSRE)-》1:表示傳輸DMA sevice request 是enabled;20(RSRE)-》1:表示接收DMA service request允許
19(TINTE)-》0:表示接收超時(shí)中斷disable;18(PINTE)-》0:表示外設(shè)trail byte 中斷disable;
17:保留;16(IFS)->0:表示幀的極性由PSP的極性位決定;
15(STRF)-》0:表示傳輸FIFO(讀,寫(xiě))由SSDR_X來(lái)決定;14(EFWR)-》0:表示FIFO讀寫(xiě)特別函數(shù)disable
13:10(RFT)-》0b0111:表示到達(dá)什么級(jí)別rxfifo斷言中斷;9:6(TFT)-》0111:表示TXFIFO斷言中斷級(jí)別
5:保留;4(SPH)-》0:表示在每一個(gè)幀開(kāi)始之前要等一個(gè)時(shí)鐘,結(jié)束后要等0.5個(gè)時(shí)鐘;
3(SPO)-》0:表示SSPSCLK在inactive的時(shí)候是低電平;2(LBM)-》0:表示非循環(huán)模式
1(RIE)-》0:表示RXFIFO門(mén)檻到達(dá)的中斷disable;0(RIE)->0:表示接收FIFO門(mén)檻到達(dá)中斷disable
?
?
SSPSP_P4 0x41A0002C:?0x800085-》0000,0000,1000,0000,0000,0000,1000,0101
這個(gè)地址的高8位為0,
31:reverved;30:28(EDMYSTOP)-》0:extended dummy stop;
27:26(EDMYSTART)-》0:extended dummy start;25(FSRT)-》0:下一幀的開(kāi)始由前面的擴(kuò)展STOP決定;
24:23(DMYSTOP)-》0b01:表示最后一bit傳輸完畢后保持active的clock數(shù)1clock的延遲;22:保留
21:16(SFRMWDTH)-》0:表示最小位幀寬度;15:9(SFRMDLY)-》0:serial frame dealy
8:7(DMYSTRT)-》0b01:表示1clock的延遲在開(kāi)始的時(shí)候;6:4(STRTDLY)-》0:start delay
3(ETDS)-》0:表示結(jié)束時(shí)的傳輸狀態(tài)為low;2(SFRMP)-》1:serial frame的極性;
1:0(SCMODE)-》0b01:data driven 上升沿,數(shù)據(jù)采樣下降沿,idle狀態(tài),低;
?
對(duì)于littleton_micco_hifi_prepare的設(shè)置:
?The sscr0 e1c0003f,sscr1701dc0,sspsp 40200004,sstsa 3,ssrsa 3,ssacd 60,ssacdd 6590040
其中對(duì)于I2s的spp地址是:
#define SSCR0_P3? __REG(0x41900000)? /* SSP Port 3 Control Register 0*/
#define SSCR1_P3? __REG(0x41900004)? /* SSP Port 3 Control Register 1*/
#define SSPSP_P3? __REG(0x4190002C)?/* SSP Port 3 Programmable Serial Protocol */
#define SSTSA_P3? __REG(0x41900030)? /* SSP Port 3 Tx Timeslot Active*/
#define SSRSA_P3? __REG(0x41900034)? /* SSP Port 3 Rx Timeslot Active*/
#define SSACD_P3 __REG(0x4190003C)?/* SSP Port 3 Audio Clock Divider */
#define???? SSACDD_P3?? __REG(0x41900040)? /* SSP Port 3 Audio Clock DitherDivider Register */
?
SSCR0_P3==__REG(0x41900000):e1c0003f——》1110,0001,1100,0000,0000,0000,0011,1111
31 (MOD)-》1:網(wǎng)絡(luò)模式;30(ACS)-》1:時(shí)鐘選擇是audio clock和audio clock divider決定,由ssacd寄存器決定;
29(FPCKE)-》1:FIFO packing mode enabled;28()-》0:reserved
27(52MM)-》0:13mbps模式;26:24(FRDC)-》1:每幀的時(shí)隙數(shù)
23(TIM)->1:表示禁止傳輸fifo underrun中斷;22(RIM)-》1:表示禁止接收f(shuō)ifo overrun中斷
21(NCS)->0:這里ignore,由ACS決定了(為1);20(EDSS)-》0:表示前面填充DSS來(lái)達(dá)到8-16位
19:8(SCR)-》0:由ACS那里決定;7(SSE)-》0:表示disable port,工作時(shí)應(yīng)為1
6(ECS)-》0:表示片內(nèi)的時(shí)鐘用來(lái)計(jì)算serial clock rate;5:4(FRF)-》0b11:表示psp模式用來(lái)模擬I2S協(xié)議
3:0(DSS)-》0b1111:表示16bit數(shù)據(jù)(EDSS為0)
?
SSCR1_P3==__REG(0x41900004):701dc0——》0000,0000,0111,0000,0001,1101,1100,0000
31(TTELP)-》0:表示最后一個(gè)bit傳輸(LSB)傳完后有半個(gè)時(shí)鐘處于高阻(三態(tài))狀態(tài);
30(TTE)-》0:表示傳輸信號(hào)不是三態(tài)的;29(EBCEI)-》0:bit傳輸錯(cuò)誤不產(chǎn)生中斷
28(SCFR)-》0:表示SSPSCLK的時(shí)鐘信號(hào)需要連續(xù)的工作,主模式ignore;27(ECRA)-》0:表示禁止其它ssp向它發(fā)起始終請(qǐng)求
26(ECRB)-》0:表示同27;25(SCLKDIR)-》0:表示主模式,SSP端口,驅(qū)動(dòng)SSPSCLK;
24(SFRMDIR)-》0:表示主模式,SSP端口,驅(qū)動(dòng)SSPSFRM信號(hào);
23(RWOT)-》0:接收和傳輸都可以;22(TRAIL)-》1:表示trailing bytes 由dma burst來(lái)處理;
21(TSRE)-》1:表示傳輸DMA sevice request 是enabled;20(RSRE)-》1:表示接收DMA service request允許
19(TINTE)-》0:表示接收超時(shí)中斷disable;18(PINTE)-》0:表示外設(shè)trail byte 中斷disable;
17:保留;16(IFS)->0:表示幀的極性由PSP的極性位決定;
15(STRF)-》0:表示傳輸FIFO(讀,寫(xiě))由SSDR_X來(lái)決定;14(EFWR)-》0:表示FIFO讀寫(xiě)特別函數(shù)disable
13:10(RFT)-》0b0111:表示到達(dá)什么級(jí)別rxfifo斷言中斷;9:6(TFT)-》0111:表示TXFIFO斷言中斷級(jí)別
5:保留;4(SPH)-》0:表示在每一個(gè)幀開(kāi)始之前要等一個(gè)時(shí)鐘,結(jié)束后要等0.5個(gè)時(shí)鐘;
3(SPO)-》0:表示SSPSCLK在inactive的時(shí)候是低電平;2(LBM)-》0:表示非循環(huán)模式
1(RIE)-》0:表示RXFIFO門(mén)檻到達(dá)的中斷disable,0(RIE)->0:表示接收FIFO門(mén)檻到達(dá)中斷disable
?
SSPSP_P3==__REG(0x4190002C):40200004——》0100,0000,0010,0000,0000,0000,0000,0100
31:reverved;30:28(EDMYSTOP)-》4:extended dummy stop;
27:26(EDMYSTART)-》0:extended dummy start;25(FSRT)-》0:下一幀的開(kāi)始由前面的擴(kuò)展STOP決定;
24:23(DMYSTOP)-》0b00:表示最后一bit傳輸完畢后保持active的clock數(shù)的延遲;22:保留
21:16(SFRMWDTH)-》0b20:表示最小位幀寬度;15:9(SFRMDLY)-》0:serial frame dealy
8:7(DMYSTRT)-》0b00:表示0clock的延遲在開(kāi)始的時(shí)候;6:4(STRTDLY)-》0:start delay
3(ETDS)-》0:表示結(jié)束時(shí)的傳輸狀態(tài)為low;2(SFRMP)-》1:serial frame的極性;
1:0(SCMODE)-》0b00:data driven 下降沿,數(shù)據(jù)采樣上升沿,idle狀態(tài),低;
?
SSTSA_P3==__REG(0x41900030):3——》0011
31:8->0:reserved;7:0(TTSA)->0b0011:表示在那個(gè)time slot里面是傳輸數(shù)據(jù)的0,不傳輸,1傳輸;
SSRSA_P3==__REG(0x41900034):3——》0011
31:8 :reserved;7:0(RTSA)-》0:表示在那個(gè)slot里面接收數(shù)據(jù),0,不接受,1 接收;
SSACD_P3==__REG(0x4190003C):60——》0110,0000
31:8:reserved;7(SCDX8)-》0:sysclk/4產(chǎn)生內(nèi)部audio clock,1,sysclk/8產(chǎn)生audio clock;
6:4(ACPS)-》0b110:PLL輸出時(shí)鐘由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;除數(shù)(0x659)
15:12:reserved;11:0(DEN)-》64:被除數(shù)
比如我們的板子上是這樣計(jì)算這些值的:
比如,在我們的機(jī)子上的一個(gè)實(shí)例是這樣的,
那么第一步取得采樣率:48K,它也就是Sync clock;
第二步球的bit率:48X64=3.072M
第三步求的sysclk:這個(gè)根據(jù)scdx8決定是X4還是X8,在我們的例子中是4,所以:3.072X4=12.288
第四步求得我們要的dither divider y,公式為:
624*(y)/2=12.288,
算出y=0.039384615384615384615384615384615
所以查可能的分子和分母表,得出,分子是:
64,分母是1625
如下圖所示:
當(dāng)然更加詳細(xì)的請(qǐng)參閱spec;
?
第二段是平臺(tái)級(jí)別的,主要是對(duì)于DMA的初始化;
第三段是codec級(jí)別的,這里主要是對(duì)codec本身的設(shè)置,通過(guò)i2c接口對(duì)codec的寄存器操作,比如采樣率等等;
最后面還有一個(gè)poweron的函數(shù),這個(gè)函數(shù)前面有提到,但是沒(méi)有詳細(xì)分析,這里分析一下:
首先根據(jù)事件類(lèi)型,決定是關(guān)閉門(mén)序列,還是啟動(dòng)門(mén)序列,我只分析啟動(dòng)過(guò)程;
得到啟動(dòng)序列,就開(kāi)始遍歷整個(gè)序列,對(duì)于這個(gè)序列的每一個(gè)類(lèi)型,查找所有的門(mén)的序列,直到有一個(gè)門(mén)的類(lèi)型和當(dāng)前啟動(dòng)序列的類(lèi)型相同,然后再根據(jù)不同的類(lèi)型做不同的檢查和power:
1,如果是snd_soc_dapm_vmid則繼續(xù),不做任何處理;
2,
A)如果是snd_soc_dapm_adc,并且其active為1,這個(gè)active在上一步已經(jīng)分析過(guò)了,必須要包含這個(gè)流的名字的sname的門(mén)才會(huì)被激活,假設(shè)我們現(xiàn)在討論的是用pcm通道播放聲音,那么流的名字就是“Voice Playback”,所以,將置有dac3的active被設(shè)成1,這樣就避免了power on dac1,dac2,和adc了。如果這兩個(gè)條件都滿足,那么必然是“Voice Capture”了,因?yàn)橹挥羞@時(shí)候,我們才會(huì)用到adc,現(xiàn)在看看,如果用了adc將會(huì)啟動(dòng)什么,于是調(diào)用函數(shù)is_connected_input_ep,這是一個(gè)通用遞歸函數(shù),從名字上來(lái)說(shuō)就是看是否是已經(jīng)連接了輸入的門(mén),我們只考慮adc的情況,其余的情況待會(huì)再討論,對(duì)于adc,在is_connected_input_ep函數(shù)里面,是通過(guò)遍歷所有以這個(gè)門(mén)作為sink的source門(mén)(list_for_each_entry(path, &widget->sources,list_sink),可以看到,這里的最后一個(gè)參數(shù)是list_sink,而第二個(gè)參數(shù)卻是widget->sources,這個(gè)原因我在“門(mén)連接分析”頁(yè)里面已經(jīng)分析過(guò)了,總之sources就表示這個(gè)門(mén)的sources列表,而sinks就是這個(gè)門(mén)的sink列表),通過(guò)遞歸調(diào)用is_connected_input_ep來(lái)查看這些source門(mén)是否其中有一個(gè)是連通的,返回的是所有是否連通的和(聯(lián)通為1,否則為0),所以返回的結(jié)果可能是大于1的數(shù),表示不只一個(gè)源是聯(lián)通的。
B)如果這個(gè)函數(shù)返回為真則表示此adc是聯(lián)通的,于是調(diào)用dapm_update_bits來(lái)處理,這個(gè)函數(shù)過(guò)對(duì)mux(它的reg<0),input,output,mic,hp,line,spk,不做任何處理就返回了;過(guò)了這一關(guān),開(kāi)始查是否men的revert為真,如果為真,則把power取反,原來(lái)為真現(xiàn)在變假,于是調(diào)用snd_soc_read(micco_soc_read)開(kāi)始讀這個(gè)寄存器的值(注意,這里讀的值是可能和物理上的這個(gè)寄存器的值不一樣的,這里讀的值是cache里面的值),讀出來(lái)后強(qiáng)制把1<
3,
A)如果此類(lèi)型是snd_soc_dapm_dac并且active為1,則調(diào)用is_connected_output_ep來(lái)取得是否要power,下面來(lái)看看函數(shù)is_connected_output_ep,這也是一個(gè)通用的判斷是否有連接到輸出的遞歸函數(shù),我們只分析dac的情況,list_for_each_entry(path, &widget->sinks,list_source),上面已經(jīng)講過(guò),這里實(shí)際上查的是這個(gè)門(mén)的所有的sink列表,通過(guò)遞歸調(diào)用is_connected_output_ep來(lái)看是否它的sink是聯(lián)通的,只要有一條路是聯(lián)通的,則power為真。
B)返回后調(diào)用dapm_update_bits來(lái)處理,上面已經(jīng)分析過(guò)了,這個(gè)函數(shù)就是判斷是否需要設(shè)置此門(mén)的寄存器的1<<shift位。
4,如果此類(lèi)型是snd_soc_dapm_pga,則調(diào)用is_connected_input_ep來(lái)判斷是否聯(lián)通輸入,再調(diào)用is_connected_output_ep判斷是否聯(lián)通輸出,對(duì)于pgais_connected_input_ep函數(shù)的處理和adc是一樣的,對(duì)于is_connected_output_ep和dac的處理是一樣的,接著調(diào)用dapm_set_pga,根據(jù)power的值決定是mute pga還是啟用pga,但是就我打印的結(jié)果來(lái)看,基本上這個(gè)函數(shù)所起的作用為0,因?yàn)閷?duì)于pga的門(mén)似乎都沒(méi)有設(shè)置相應(yīng)的control,最后調(diào)用dapm_update_bits,設(shè)置power 位。
5,對(duì)于other widget,這里在我們的平臺(tái)上多半是指mux,首先調(diào)用is_connected_input_ep判斷是否連接輸入,再調(diào)用is_connected_output_ep判斷是否有輸出,調(diào)用dapm_update_bits位設(shè)置power 位,最后調(diào)用w->event(do_post_event)來(lái)進(jìn)行后期處理,這里主要就是對(duì)mux進(jìn)行寄存器設(shè)置,因?yàn)閙ux的寄存器的地址都是大于0x70+0x15的,所以它們的地址需要轉(zhuǎn)化,這個(gè)函數(shù)就是根據(jù)mux的類(lèi)型,訪問(wèn)不同的寄存器。
?
基本上prepare后,一切就都就緒了,只等一個(gè)trigger;而trigger的執(zhí)行會(huì)在上層的alsalib調(diào)用write的函數(shù)觸發(fā);
?
?
4.1.4?????????write的流程
?
用戶(hù)層的write到內(nèi)核里面都是通過(guò)ioctl來(lái)做的,這里面會(huì)觸發(fā)trigger函數(shù)的執(zhí)行,等trigger執(zhí)行完以后,才會(huì)真正調(diào)用函數(shù)把用戶(hù)層的東西copy到dma分配的空間;
這里面基本上只是畫(huà)了最簡(jiǎn)單的邏輯,其實(shí)里面非常的復(fù)雜特別是函數(shù)snd_pcm_lib_write1,這里面有同步的操作,也就是要等到有空余的空間的時(shí)候才允許寫(xiě),否則就要等待,喚醒是通過(guò)函數(shù)snd_pcm_update_hw_ptr_post來(lái)做的,這個(gè)函數(shù)會(huì)在DMA傳輸完一幀的中斷到來(lái)的時(shí)候被調(diào)用,用來(lái)更新緩沖區(qū)指針;
?
其中trigger的邏輯如下:
?
簡(jiǎn)單的說(shuō)就是啟動(dòng)DMA,enable ssp口;
?
?
?
?
?
?
4.1.5?????????使用流程的總結(jié)t
???????? 簡(jiǎn)單總結(jié)一下,用戶(hù)的使用流程;
???????? A,調(diào)用snd_pcm_open打開(kāi)設(shè)備節(jié)點(diǎn)對(duì)應(yīng)的pcm流的substream也就是錄音或者play;
B,調(diào)用snd_pcm_hw_params設(shè)置硬件參數(shù),包括格式,通道,采樣率,DMA空間的分配,中斷的申請(qǐng)等等,這里面會(huì)調(diào)用prepare函數(shù)使硬件準(zhǔn)備好硬件,包括codec的寄存器設(shè)置,各種路徑的建立,門(mén)的power on等;
C,調(diào)用write函數(shù)實(shí)現(xiàn)把數(shù)據(jù)寫(xiě)到設(shè)備里面去,這里會(huì)觸發(fā)trigger函數(shù)也就是DMA的啟動(dòng),SSP端口的啟動(dòng)等。
??????
?
5.??????????????Amixer調(diào)用的相關(guān)邏輯
我們的audio controller所調(diào)用的驅(qū)動(dòng)的接口都是amixer的cset,cget,所以有必要分析一下它的邏輯:
5.1.1?????????Amixer調(diào)用的上層邏輯
??? 也就是說(shuō)通過(guò)/dev下面的設(shè)備節(jié)點(diǎn)調(diào)用相應(yīng)的ioctl,然后進(jìn)入到內(nèi)核的范圍;
5.1.2?????????Amixer的內(nèi)核流程?????
這里只分析了控制函數(shù)為snd_soc_dapm_put_enum_double的處理邏輯,其它的都類(lèi)似,而具體的應(yīng)該是哪個(gè)處理函數(shù)來(lái)處理是在control的new的時(shí)候就已經(jīng)確立了的,對(duì)于我們的平臺(tái)其實(shí)在表micco_dapm_widgets建立的時(shí)候就已經(jīng)確立了;
為了方便后來(lái)者的調(diào)試,我這里把各個(gè)numid的對(duì)應(yīng)的控制函數(shù)都列出來(lái)了,如下:
numid=1到12:snd_soc_put_volsw;
numid=13到20:snd_soc_dapm_put_enum_double
?
?
.
6.??????????????總結(jié)
Alsa驅(qū)動(dòng)的架構(gòu)主要是分成對(duì)上為alsalib提供接口,對(duì)下實(shí)現(xiàn)硬件的管理,對(duì)上的內(nèi)容基本都是在sound/core目錄里面的文件來(lái)完成,而設(shè)計(jì)硬件的操作分成兩部分一部分相關(guān)與cpu這邊的是由sound/soc/pxa目錄里面的文件來(lái)完成的,另外一部分設(shè)計(jì)codec是由sound/soc/codec來(lái)完成的,這部分主要就是對(duì)codec這邊的寄存器的設(shè)置;簡(jiǎn)單示意如下:
?
它復(fù)雜的地方在于用戶(hù)態(tài)的alsa lib。
?
?
?
?
7.??????????????未討論
還有一些地方?jīng)]有討論到,比如timer,不過(guò)留到以后補(bǔ)充吧;
?
?
?
?
?
備注:
????????????? 內(nèi)核版本:2.6.21(+marvel patch)
?????? ? ? ? ?? 硬件平臺(tái):pxa310+9034codec;
?作者:wylhistory