




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
i.MX6XASOC音頻驅(qū)動(dòng)說(shuō)明與定制JohnLi(R64710)GSMFAEFreescaleSemiconductor,Inc.此文件用于幫助理解基于Freescale的i.MX6X的ASOC1ALSAandASOC基本概 ASoC的由i.MX6XASOC音頻驅(qū)動(dòng)說(shuō)明與定制JohnLi(R64710)GSMFAEFreescaleSemiconductor,Inc.此文件用于幫助理解基于Freescale的i.MX6X的ASOC1ALSAandASOC基本概 ASoC的由 硬件架 軟件架 數(shù)據(jù)結(jié) 2音頻驅(qū)動(dòng)的流程,平臺(tái)數(shù)據(jù),內(nèi)核配置與測(cè) 音頻驅(qū)動(dòng)的打開(kāi)流 音頻驅(qū)動(dòng)平臺(tái)數(shù) 音頻驅(qū)動(dòng)內(nèi)核配 音頻驅(qū)動(dòng)的測(cè) 3音頻驅(qū)動(dòng)ASoC的機(jī)器 注冊(cè)Platform 注冊(cè)Platform 初始化入口soc_probe 4音頻驅(qū)動(dòng)ASoC的Codec Codec簡(jiǎn) ASoC中對(duì)Codec的數(shù)據(jù)抽 Codec的注 Codec初始 regmap- 5音頻驅(qū)動(dòng)ASoC的Codec Platform驅(qū)動(dòng)在ASoC中的作 snd_soc_platform_driver的注 snd_soc_platform_driver中的ops字 音頻數(shù)據(jù)的dma操 cpu的snd_soc_daidriver驅(qū)動(dòng)的注 snd_soc_dai_driver中的ops字 音頻驅(qū)動(dòng)移植范例:SGTL5000(Sabe 6硬件設(shè) 軟件目 軟件說(shuō) 7音頻驅(qū)動(dòng)移植范例:WM8524(OTTSetBo 硬件設(shè) 軟件目 軟件說(shuō) Createthe ALSAandASOC基本 ALSAandASOC基本概ALSAAdvancedLinuxSoundArchitecturelinuxalsa-lib,alsa-API,圖動(dòng)層的實(shí)現(xiàn)細(xì)節(jié),簡(jiǎn)化了應(yīng)用程序的實(shí)現(xiàn)難度。內(nèi)核空間中,alsa-socalsa-driverASoCsound/soc1.1ASoC的由ASoC--ALSASystemonChipALSADynamicAudioPowerManagement(DAPM能1.2硬件架構(gòu)ALSA圖Machine一樣,CPU不一樣,Codec不一樣,音頻的輸入、輸出設(shè)備也不一樣,Machine為Platform音頻圖Machine一樣,CPU不一樣,Codec不一樣,音頻的輸入、輸出設(shè)備也不一樣,Machine為Platform音頻相關(guān)的通常包含該SoC中的時(shí)鐘、DMA、I2S、PCM等等,只要指定了SoC,那么我們可以認(rèn)為它會(huì)有一個(gè)對(duì)應(yīng)的Platform,它只與SoC相關(guān),與Machine無(wú)關(guān),這樣我們就Codec機(jī)、喇叭、聽(tīng)筒,Line-out),Codec和Platform一樣,是可重用的部件,同一個(gè)架構(gòu)CodecCodecoCodecDAIPCMooCodecDAIPCMoCodecIO(I2C,SPIoCodecALSAoDAPMoDAPMoDACPlatform等等Machinei.MX6XSSIcodec以首先檢查這個(gè)文件夾有沒(méi)有相應(yīng)的codec層文件,目前它包括了wolfson,TI,Freescalecodec,imx-cs42888.cSaberAIDSPAudiocodecDACcodec1.4數(shù)據(jù)結(jié)構(gòu)1.4數(shù)據(jù)結(jié)構(gòu)由上圖我們可以看出,3.0中的數(shù)據(jù)結(jié)構(gòu)更為合理和清晰,取消了snd_soc_device結(jié)構(gòu),直接用snd_soc_card取代了它,并且強(qiáng)化了snd_soc_pcm_runtime的作用,同時(shí)還增加了另外兩個(gè)數(shù)據(jù)結(jié)構(gòu)snd_soc_codec_driversnd_soc_platform_driver,用于明確代表Codec驅(qū)Platform驅(qū)動(dòng)。后續(xù)的章節(jié)中將會(huì)逐一介紹MachinePlatformCodec驅(qū)動(dòng)的工作細(xì) 音頻驅(qū)動(dòng) 音頻驅(qū)動(dòng)的流程,平臺(tái)數(shù)據(jù),內(nèi)核配置與測(cè)試2.1音頻驅(qū)動(dòng)的打開(kāi)流程ALSA提供硬件能力給ALSAruntime信息(包括硬件,DMA,軟件支持能力)配置讀寫(xiě)DMA通道CPUDAICodecDAI接口配置Codec硬件音頻傳輸觸發(fā)后,接下來(lái)的DMA讀寫(xiě)操作則由DMACallback2.2音頻驅(qū)動(dòng)平臺(tái)數(shù)據(jù)臺(tái)數(shù)據(jù)結(jié)構(gòu),其中成員需要根據(jù)具體硬件設(shè)計(jì)配置,參考wm8962的設(shè)置:staticstructmxc_audio_platform_datawm8962_data=.ssi_num1,SSI通道數(shù)目,目前大部分音頻codec.src_port=2,表示連接到SSI上的Audmux接口號(hào),參考i.MX6XRM一般Port1,2,7連一般Port1,2,7連接到內(nèi)SSI上,3,4,5,6連接到外部的pin上連接到外部saberSDP板上使用的是.hp_gpio=SABRESD_HEADPHONE_DET,//耳機(jī)檢查所用的.hp_active_low=1,GPIO1.mic_gpio=SABRESD_MICROPHONE_DET,//麥克風(fēng)檢查所用的.mic_active_low=1,GPIO,//,//.clock_enablewm8962_clk_enable,//callback//.initmxc_wm8962_init函數(shù)如下,主要WM8962的主時(shí)鐘是由i.MX6XCLKO24MWM8962,然后做主,i.M做從的。原理圖如下:audiocodec是做從的,可以參考OTTsetboxWM8524staticint{intif(IS_ERR(clko)){returnPTR_ERR(clko);}/*bothaudiocodecandcomerauseCLKOwm8962_data.sysclk=return}//.clock_enable=wm8962_clk_enablestaticintwm8962_clk_enable(int{ifreturn}2.3音頻驅(qū)動(dòng)內(nèi)核配置 的音頻內(nèi)核menuconf 配置為Devicedrivers>Soundcardsupport>AdvancedLinuxSoundArchitecture>ALSAforSoCaudiosupport>SoCAudiofortheFreescalei.MXCPU,SoCAudiosupportforWM89622.4音頻驅(qū)動(dòng)的測(cè)試音頻驅(qū)動(dòng)支持放音,錄音,音量調(diào)節(jié)等,都可以通過(guò)ALSA應(yīng)用程序來(lái)測(cè)。aplay[-Dplughw:0,0]WM8962IN3RWM8962IN3Ramixersset'MIXINRIN3R'onamixersset'INPGARIN3R'arecord[-Dplughw:0,0]-r44100-fS16_LE-c2-d5aplay–harecord 音頻驅(qū)動(dòng)ASoC的機(jī)器前面一節(jié)的內(nèi)容我們提到,ASoCMachine、PlatformCodec三大部分,其中的MachinePlatformCodec之間的耦合以及部分和設(shè)備或板子特定的代碼,再次引用上一節(jié)的內(nèi)容:Machine驅(qū)動(dòng)負(fù)責(zé)處理機(jī)器特有的一些控件和音頻事件(例如,當(dāng)播放音頻時(shí),需要先行打開(kāi)一個(gè)放大器);單獨(dú)的Platform和Codec驅(qū)動(dòng)是不能工作的,它必須由Machine驅(qū)動(dòng)把它們結(jié)合在一起才能完成整個(gè)設(shè)備的音頻處理工作。ASoC的一切都從Machine驅(qū)動(dòng)開(kāi)始,包括聲卡的注冊(cè),綁定PlatformCodec驅(qū)動(dòng)等等,下面就讓我們從Machine驅(qū)動(dòng)3.1注冊(cè)PlatformASoC把聲卡注冊(cè)為PlatformDeviceWM8962staticintinit{intret=if(ret<gotoif(ret<gotoif(machine_is_mx6q_sabresd())if(!imx_snd_device)gotoplatform_set_drvdata(imx_snd_device,ret=if(0==gotoreturn}由此可見(jiàn),模塊初始化時(shí),注冊(cè)了一個(gè)名為soc-audio的Platform設(shè)備,同時(shí)把snd_soc_card_imxplatform_devicedev.drvdata字段中,這里引出了第一個(gè)數(shù)據(jù)結(jié)構(gòu)snd_soc_card的實(shí)例snd_soc_card_imx,他的定義如下:staticstructsnd_soc_opsimx_hifi_ops=.startup=.shutdown=.hw_params=.hw_free=.trigger=//snd_soc_dai_link中,指定了Platform、.hw_params=.hw_free=.trigger=//snd_soc_dai_link中,指定了Platform、Codec、codec_dai、cpu_dai的名字,稍后Machine驅(qū)動(dòng)將會(huì)利用這些名字去匹配已經(jīng)在系統(tǒng)中注冊(cè)的platform,codec,dai,這些注冊(cè)的部件都是在另外相應(yīng)的Platform驅(qū)動(dòng)和Codec驅(qū)動(dòng)的代碼文件中定義的,這樣看來(lái),Machine驅(qū)動(dòng)的設(shè)備初始化代碼無(wú)非就是選擇合適Platform和Codec以及dai,用他們填充以上幾個(gè)數(shù)據(jù)結(jié)構(gòu),然后注冊(cè)Platform設(shè)備即可。當(dāng)然還要實(shí)現(xiàn)連接PlatformCodecdai_link對(duì)應(yīng)的ops實(shí)現(xiàn),imx_hifi_ops。staticstructsnd_soc_dai_linkimx_dai[]={.name=.stream_name=wm8962",//codecdai.codec_name="wm8962.0-001a",//codecimx-ssi.1cpudaiimx-pcm-audio.1",//platform==staticstructsnd_soc_cardsnd_soc_card_imx===snd_soc_dai_link(實(shí)例snd_soc_ops(3.2注冊(cè)Platformplatform_driver。ASoCstaticintinit{return}/*ASoCplatformdriver3.2注冊(cè)Platformplatform_driver。ASoCstaticintinit{return}/*ASoCplatformdriverstaticstructsoc_driver=={="soc-====soc_probeASoC3.3初始化snd_soc_register_card3.3初始化snd_soc_register_cardsnd_soc_register_cardsnd_soc_pcm_runtimedai_linksnd_soc_pcm_runtimesnd_soc_carddai_link配置復(fù)制到相應(yīng)的snd_soc_pcm_runtime中,最后,大部分的工作都在該函數(shù)首先利用card->instantiated來(lái)判斷該卡是否已經(jīng)實(shí)例化,如果已經(jīng)實(shí)例化則直接返/*bindDAIsfor(i=0;i<card->num_links;soc_bind_dai_link(card,ASoC定義了三個(gè)全局的鏈表頭變量:codec_list、dai_list、platform_list,系統(tǒng)中所有的函數(shù)逐個(gè)掃描這三個(gè)鏈表,根據(jù)card->dai_link[]中的名稱(chēng)進(jìn)行匹配,匹配后把相應(yīng)的codec,dai和platform實(shí)例賦值到card->rtd[]中(snd_soc_pcm_runtime)。經(jīng)過(guò)這個(gè)過(guò)程后,/*cardbindcompletesoregisterasoundcardret=snd_card_create(SNDRV_DEFAULT_IDX1,card->owner,0,&card-card->snd_card->dev=card-card->dapm.bias_level=card->dapm.dev=card-card->dapm.card=list_add(&card->dapm.list,&card-initialisethesoundcardonlyonce(card->probe)ret=card-if(ret<goto}earlyDAIlinkprobe(orderinitialisethesoundcardonlyonce(card->probe)ret=card-if(ret<goto}earlyDAIlinkprobe(order=SND_SOC_COMP_ORDER_FIRST;order<=order++)for(i=0;i<card->num_links;i++)ret=soc_probe_dai_link(card,i,if(ret<0)pr_err("asoc:failedtocard%s:card->name,goto}}}(i=0;i<card->num_aux_devs;i++)ret=soc_probe_aux_dev(card,if(ret<0)pr_err("asoc:failedtoaddauxiliarydevices%s:card->name,goto}}soc_probe_dai_linkintsoc_probe_dai_link(structsnd_soc_card*card,int{/*setdefaultpowerofftimeoutrtd->pmdown_time=probethecpu_daicard->name,goto}}soc_probe_dai_linkintsoc_probe_dai_link(structsnd_soc_card*card,int{/*setdefaultpowerofftimeoutrtd->pmdown_time=probethecpu_dai(!cpu_dai->probedcpu_dai->driver->probe_order==order)if(cpu_dai->driver->probe)ret=cpu_dai->driver-}cpu_dai->probed=/*markcpu_daiasprobedandaddtocarddailist_add(&cpu_dai->card_list,&card-}probetheCODEC(!codec->probedcodec->driver->probe_order==order)ret=soc_probe_codec(card,}probetheplatform(!platform->probedplatform->driver->probe_order=={ret=soc_probe_platform(card,(!codec->probedcodec->driver->probe_order==order)ret=soc_probe_codec(card,}probetheplatform(!platform->probedplatform->driver->probe_order=={ret=soc_probe_platform(card,}probetheCODECDAI(!codec_dai->probed&&codec_dai->driver->probe_order=={if(codec_dai->driver->probe)ret=codec_dai->driver-}/*markcodec_daiasprobedandaddtocarddailistcodec_dai->probed=list_add(&codec_dai->card_list,&card-}completeDAIprobeduringlastprobe(order!=returnret=soc_post_component_init(card,codec,num,ifreturn/*createthepcmret=soc_new_pcm(rtd,return}/*createanewpcmsoc_new_pcm(structsnd_soc_pcm_runtime*rtd,ret=soc_post_component_init(card,codec,num,ifreturn/*createthepcmret=soc_new_pcm(rtd,return}/*createanewpcmsoc_new_pcm(structsnd_soc_pcm_runtime*rtd,{struct*soc_pcm_ops=&rtd-soc_pcm_ops-=soc_pcm_ops-=soc_pcm_ops-=soc_pcm_ops-=soc_pcm_ops-=soc_pcm_ops-=soc_pcm_ops-=ret=snd_pcm_new(rtd->card->snd_card,num,playback,capture,/*DAPMdailinkstreamworkINIT_DELAYED_WORK(&rtd->delayed_work,rtd->pcm=pcm->private_data=(platform->driver->ops)ret=snd_pcm_new(rtd->card->snd_card,num,playback,capture,/*DAPMdailinkstreamworkINIT_DELAYED_WORK(&rtd->delayed_work,rtd->pcm=pcm->private_data=(platform->driver->ops)soc_pcm_ops->mmap=platform->driver->ops-soc_pcm_ops->pointer=platform->driver->ops-soc_pcm_ops->ioctl=platform->driver->ops-soc_pcm_ops->copy=platform->driver->ops-soc_pcm_ops->silence=platform->driver->ops-soc_pcm_ops->ack=platform->driver->ops-soc_pcm_ops->page=platform->driver->ops-}snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_PLAYBACK,snd_pcm_set_ops(pcm,SNDRV_PCM_STREAM_CAPTURE,(platform->driver->pcm_new)ret=platform->driver-if(ret<0)pr_err("asoc:platformpcmconstructorreturn}}pcm->private_free=ret=platform->driver-if(ret<0)pr_err("asoc:platformpcmconstructorreturn}}pcm->private_free=platform->driver-return}open,close,hw_paramsalsapcmplatformsnd_pcm_opspcmsnd_pcm_ops字段,最后,調(diào)用daicard->late_probe(cardalsaif(card->late_probe)ret=card-if(ret<0)dev_err(card->dev,"%slate_probe()failed:card->name,goto}}snd_soc_dapm_new_widgets(&card-if(card-list_for_each_entry(codec,&card->codec_dev_list,retsnd_soc_dapm_new_widgets(&card-if(card-list_for_each_entry(codec,&card->codec_dev_list,ret=snd_card_register(card-if(ret<0)printk(KERN_ERR"asoc:failedtoregistersoundcardforcard-goto} 音頻驅(qū)動(dòng)ASoC的Codec4.1Codec簡(jiǎn)介代碼不經(jīng)修改即可用在不同的平臺(tái)上。以下的討論基于wolfsonCodec代碼不經(jīng)修改即可用在不同的平臺(tái)上。以下的討論基于wolfsonCodecWM8962,kernel的版本3.0.354.2ASoC中對(duì)Codec的數(shù)抽象描述Codec的最主要的幾個(gè)數(shù)據(jù)結(jié)構(gòu)分別是:snd_soc_codec,snd_soc_codec_driver,snd_soc_dai,snd_soc_dai_driversnd_soc_daisnd_soc_dai_driverASoCPlatform驅(qū)動(dòng)中也會(huì)使用到,PlatformCodecDAIsnd_soc_dai_link段,詳細(xì)的定義請(qǐng)參照:/include/sound/soc.h/*SoCAudioCodecdevicestructsnd_soc_codecconstchar/*Codecstructdevice*dev;/*Codecconststructsnd_soc_codec_driver*driver;/*codecstructsnd_soc_cardPCMvolatile/*runtime/*codecIOvoid*control_data;/*codecenumsnd_soc_control_typecontrol_type;/*SND_SOC_REGMAP/*Codec/*runtime/*codecIOvoid*control_data;/*codecenumsnd_soc_control_typecontrol_type;/*SND_SOC_REGMAP/*Codecunsignedint(*read)(structsnd_soc_codec*,unsigned*,unsignedint,int(*write)(struct/*dapmstructsnd_soc_dapm_context/*DAPM/*codecdriverstructsnd_soc_codec_driver/*driverops*);/*codecint(*probe)(structsnd_soc_instantiate_card(*remove)(structsnd_soc_codec(*suspend)(structsnd_soc_codec*);/*(*resume)(structsnd_soc_codec/*電源管理/*Defaultcontrolandsetup,addedafterprobe()isrunconststructsnd_kcontrol_new/*conststructsnd_soc_dapm_widget/*dapmconststructsnd_soc_dapm_route/*dapm/*codecwideint/*int/*codecIOunsignedint(*read)(...);/*codecconststructsnd_soc_dapm_widget/*dapmconststructsnd_soc_dapm_route/*dapm/*codecwideint/*int/*codecIOunsignedint(*read)(...);/*codec/*codec/*codecbiaslevelint*DigitalAudioInterfaceruntime**Holdsruntimedataforastructsnd_soc_daiconstchar/*daistructdevice/*/*driveropsstructsnd_soc_dai_driver/*DAIruntimeinfounsignedint/*streamisinuseunsignedintconstchar/*daistructdevice/*/*driveropsstructsnd_soc_dai_driver/*DAIruntimeinfounsignedint/*streamisinuseunsignedint/*streamis/*DAIDMAdatavoidplaybackdmavoid/*capturedma/*parentunionstructsnd_soc_platform/*cpudai,臺(tái)structsnd_soc_codecstructsnd_soc_card*card;/*Machinecrad*DigitalAudioInterface**DescribestheDigitalAudioInterfaceintermsofitsALSA,DAIand*operationsandcapabilities.Codecandplatformdriverswill*structureforeveryDAIthey**Thisstructurecoverstheclocking,formatingandALSAoperations*structsnd_soc_dai_driver/*DAIdescriptionconstchar/*dai/*DAIdrivercallbacksint**DescribestheDigitalAudioInterfaceintermsofitsALSA,DAIand*operationsandcapabilities.Codecandplatformdriverswill*structureforeveryDAIthey**Thisstructurecoverstheclocking,formatingandALSAoperations*structsnd_soc_dai_driver/*DAIdescriptionconstchar/*dai/*DAIdrivercallbacksint(*probe)(structsnd_soc_dai*dai);/*daiprobesnd_soc_instantiate_card(*remove)(structsnd_soc_dai(*suspend)(structsnd_soc_dai/*(*resume)(structsnd_soc_dai/*opsconststructsnd_soc_dai_ops/*dai/*capabilitiessnd_soc_pcm_stream/*capturesnd_soc_pcm_stream/*playbacksnd_soc_dai_ops*DAIclockingall*Calledbysoc_card*DAIformat*Calledbysoc_cardsnd_soc_dai_ops*DAIclockingall*Calledbysoc_card*DAIformat*Calledbysoc_card*DAIdigitalmute-*Calledbysoc-coretominimiseanyint*ALSAPCMaudiooperations-all*Calledbysoc-coreduringaudioPCMintvoid*ForhardwarebasedFIFOcauseddelay*snd_pcm_sframes_t4.3Codec的注intvoid*ForhardwarebasedFIFOcauseddelay*snd_pcm_sframes_t4.3Codec的注因?yàn)镃odec驅(qū)動(dòng)的代碼要做到平臺(tái)無(wú)關(guān)性,要使得Machine驅(qū)動(dòng)能夠使用該Codec,Codec驅(qū)動(dòng)的首要任務(wù)就是確定和的實(shí)例,并把它們注冊(cè)到系統(tǒng)中/sound/soc/codecs/wm8962.cplatformstaticintinit{int#ifdefined(CONFIG_I2C)||ret=if(ret!=0)printk(KERN_ERR"FailedtoregisterWM8962I2Cdriver:}return}staticstructi2c_driverwm8962_i2c_driver=.driver=.name=.owner=.probe}return}staticstructi2c_driverwm8962_i2c_driver=.driver=.name=.owner=.probe.remove.id_table=staticdevinitintwm8962_i2c_probe(structi2c_clientconststructi2c_device_id{structwm8962_privintwm8962=kzalloc(sizeof(structwm8962_priv),GFP_KERNEL);if(wm8962==NULL)i2c_set_clientdata(i2c,ret=snd_soc_register_codec(&i2c-&soc_codec_dev_wm8962,&wm8962_dai,ifret=snd_soc_register_codec(&i2c-&soc_codec_dev_wm8962,&wm8962_dai,if(ret<return}從而注冊(cè)soc_codec_dev_wm8962staticstructsnd_soc_codec_driversoc_codec_dev_wm8962=.probe.set_bias_level=.reg_cache_size=WM8962_MAX_REGISTER+.reg_cache_default=.volatile_register=.set_pll=staticstructsnd_soc_dai_driverwm8962_dai=.name=.playback=.stream_name=.channels_min=.channels_max=.rates=.formats=.capture=.stream_name=.channels_min=.channels_max=.rates=.capture=.stream_name=.channels_min=.channels_max=.rates=.formats=.ops=.symmetric_rates=可見(jiàn),Codecsnd_soc_codec_driversnd_soc_dai_drivercodec=kzalloc(sizeof(structsnd_soc_codec),/*createCODECcomponentnamecodec->name=fmt_single_name(dev,&codec-codec->write=codec_drv-codec->read=codec_drv-codec-=codec_drv-codec-=codec_drv-codec-=codec_drv-codec->dapm.bias_levelcodec->dapm.dev=codec->dapm.codec=codec->dapm.seq_notifier=codec_drv-codec->dapm.stream_event=codec_drv-codec->dev=codec->driver=codec->num_dai=codec->dapm.codec=codec->dapm.seq_notifier=codec_drv-codec->dapm.stream_event=codec_drv-codec->dev=codec->driver=codec->num_dai=registeranyDAIs(num_dai)ret=snd_soc_register_dais(dev,dai_drv,if(ret<goto}list_add(&codec->list,snd_soc_register_daissnd_soc_register_codec要初始化,最后把該daidai_listCodec一樣,最后也會(huì)調(diào)用snd_soc_instantiate_cards4.44.4Codec初始Machine驅(qū)動(dòng)的初始化,codec和dai的注冊(cè),都會(huì)調(diào)用snd_soc_instantiate_cards進(jìn)codec,dai,platformMachine文中所描述,就是通過(guò)3個(gè)全局鏈表,按名字進(jìn)行匹配,把匹配的codec,daiplatform實(shí)例賦值給聲卡每對(duì)dai的snd_soc_pcm_runtime變量中。一旦綁定成功,將會(huì)使得codec和dai驅(qū)動(dòng)的probe回調(diào)被調(diào)用,codec的初始化工作就在該回調(diào)中完成。對(duì)于WM8962,該回調(diào)就是4.5regmap-codecWM87537bits,9bits,WM89938bits,數(shù)據(jù)也是16bitsWM899416bits,數(shù)據(jù)也是16bits。在這些多樣的寄存器的控制。regmapconstoconstostruct*regmap_init_i2c(structi2c_clientconstostruct*regmap_init_spi(structspi_devicesnd_soc_update_bitsAPIcodec 音頻驅(qū)動(dòng)ASoC的Codec5.1Platform驅(qū)動(dòng)ASoC中的作用CPU(DAI)把音頻數(shù)據(jù)傳送給Platform驅(qū)動(dòng)分為兩個(gè)部分:snd_soc_platform_driver和snd_soc_dai_driver。其中,platform_driverdmacpudai5.2snd_soc_platform_driver的注冊(cè)通常,ASoCsnd_soc_platform_driver注冊(cè)為一個(gè)系統(tǒng)的platform_driver迷惑,前者只是針對(duì)ASoC子系統(tǒng)的,后者是來(lái)自Linux的設(shè)備驅(qū)動(dòng)模型。我們要做的就是:snd_soc_platform_driver在platform_driver的probe回調(diào)中利用ASoC的API:snd_soc_register_platform()注冊(cè)上snd_soc_platform_driver在platform_driver的probe回調(diào)中利用ASoC的API:snd_soc_register_platform()注冊(cè)上面定義的snd_soc_platform_driverkernel3.0.35中的/sound/soc/imximx-pcm-dma-mx2.cstaticintinit{return}staticstructplatform_driverimx_pcm_driver=.driver=.name="imx-pcm-.owner=.probe=.remove=staticintdevinitimx_soc_platform_probe(struct{structimx_ssi*ssi=if(ssi->dma_params_tx.burstsize==&&ssi->dma_params_rx.burstsize==0)ssi->dma_params_tx.burstsize=ssi->dma_params_rx.burstsize=}//snd_soc_register_platform()snd_soc_platformstructimx_ssi*ssi=if(ssi->dma_params_tx.burstsize==&&ssi->dma_params_rx.burstsize==0)ssi->dma_params_tx.burstsize=ssi->dma_params_rx.burstsize=}//snd_soc_register_platform()snd_soc_platform,觸發(fā)聲卡的returnsnd_soc_register_platform(&pdev->dev,}staticstructsnd_soc_platform_driverimx_soc_platform_mx2====5.3snd_soc_platform_driver中的ops字段5.3snd_soc_platform_driver中的ops字段的主要工作,他們基本都涉及dma操作以及dmabuffer的管理等工作。下面介紹幾個(gè)重要設(shè)置snd_pcm_runtime結(jié)構(gòu)中的dmabuffer5.4音頻數(shù)dma操作因?yàn)閐ma的特殊性,dmabuffer是一塊特殊的內(nèi)存,比如有的平臺(tái)規(guī)定只有某段地址范方便dma控制器對(duì)內(nèi)存的訪問(wèn)。在ASoC架構(gòu)中,dmabuffer的信息保存在snd_pcm_substream結(jié)構(gòu)的snd_dma_buffer*bufstructsnd_dma_bufferunsignedchar*area;dma_addr_taddr;size_tbytes;void/*devicetype因?yàn)閐ma的特殊性,dmabuffer是一塊特殊的內(nèi)存,比如有的平臺(tái)規(guī)定只有某段地址范方便dma控制器對(duì)內(nèi)存的訪問(wèn)。在ASoC架構(gòu)中,dmabuffer的信息保存在snd_pcm_substream結(jié)構(gòu)的snd_dma_buffer*bufstructsnd_dma_bufferunsignedchar*area;dma_addr_taddr;size_tbytes;void/*devicetypevirtualpointerphysicaladdressbufferprivateinbytesallocator;don'tstaticstructsnd_pcm_opsimx_pcm_ops==//snd_imx_pcm_hw_params5.5cpusnd_soc_daidriver驅(qū)動(dòng)的注冊(cè)platformdriver。參考代碼\linux-3.0.35\sound\soc\imx\imx-staticintinit{return}staticstructplatform_driverimx_ssi_driver=.probe=.remove=.driver=.name="imx-staticstructplatform_driverimx_ssi_driver=.probe=.remove=.driver=.name="imx-.owner=snd_soc_dai_driver結(jié)構(gòu)的實(shí)例:staticstructsnd_soc_dai_driversnd_soc_register_dai(&pdev->dev,snd_soc_dai_driverprobe、suspendstaticstructsnd_soc_dai_driverimx_ssi_dai=.probe=imx_ssi_dai_probe,.suspend=imx_ssi_dai_suspend,.resumeimx_ssi_dai_resume.playbacksnd_soc_pcm_streamdai.channels_min=.channels_max=.rates=.formats=.capturesnd_soc_pcm_streamdai.channels_min=.channels_max=.rates=.formats==.formats=.capturesnd_soc_pcm_streamdai.channels_min=.channels_max=.rates=.formats==staticstructsnd_soc_dai_opsimx_ssi_pcm_dai_ops{========5.6snd_soc_dai_driver中的ops字段通常由machine5.6snd_soc_dai_driver中的ops字段通常由machine set_channel_map標(biāo)準(zhǔn)的snd_soc_ops抗pop,pop由soc-core以下這些api通常被machine驅(qū)動(dòng)使用,machine驅(qū)動(dòng)在他的snd_pcm_ops抗pop,pop由soc-core以下這些api通常被machine驅(qū)動(dòng)使用,machine驅(qū)動(dòng)在他的snd_pcm_opsASoCASoCPlatform 音 音頻驅(qū)動(dòng)移植范例硬件SGTL5000,有些客戶也想在i.MX6X上使用,可以參考i.MX6XSaberLite的硬件原理圖和i.MX6XAUD4I2SSGTL5000,I2C1連接控制接口,然后通過(guò)GPIO0i.MX6XAUD4I2SSGTL5000,I2C1連接控制接口,然后通過(guò)GPIO0供給時(shí)鐘給SGTL5000,SGTL5000 做主,i.MX6X做從,類(lèi)似于WM8962.6.2軟件目錄與 類(lèi)似,移植到SGT 需要修改的文件如下\sound\soc\imx\imx- 機(jī)器層文件6.3軟件說(shuō)明i.MX6X的所有芯片與開(kāi)發(fā)板使用同一個(gè)uImage二級(jí)制內(nèi)核,所以其imx6_defconfig包括了目前Freescale的i.MX6X開(kāi)發(fā)板所連接的所有外設(shè)驅(qū)動(dòng)支持,所以可以確認(rèn):\arch\arm\configs\imx6_defconfig,也增加了支持,如下AUDMUX6.3軟件說(shuō)明i.MX6X的所有芯片與開(kāi)發(fā)板使用同一個(gè)uImage二級(jí)制內(nèi)核,所以其imx6_defconfig包括了目前Freescale的i.MX6X開(kāi)發(fā)板所連接的所有外設(shè)驅(qū)動(dòng)支持,所以可以確認(rèn):\arch\arm\configs\imx6_defconfig,也增加了支持,如下AUDMUXMX6Q_PAD_SD2_DAT0AUDMUX_AUD4_RXD,MX6Q_PAD_SD2_DAT3AUDMUX_AUD4_TXC,MX6Q_PAD_SD2_DAT2AUDMUX_AUD4_TXD,MX6Q_PAD_SD2_DAT1I2C1,SGTL5000/*GPIO3[21]/*GPIO3[28]MX6Q_PAD_EIM_D21MX6Q_PAD_EIM_D28/*SGTL500sys_mclkMX6Q_PAD_GPIO_0staticstructmxc_audio_platform_data\sound\soc\imx\imx-pcm-dma-否PCM驅(qū)動(dòng)和 寄存器定否\sound\soc\imx\imx-否\sound\soc\imx\imx-否 據(jù)SGTL5000支staticintstaticint{structclk*clko;structclk*new_parent;intrate;clko=clk_get(NULL,if(IS_ERR(clko))pr_err("can'tgetCLKOclock.\n");returnPTR_ERR(clko);}new_parent=clk_get(NULL,if(!IS_ERR(new_parent)){}rate=clk_round_rate(clko,16000000);if(rate<8000000||rate>27000000){pr_err("Error:SGTL5000mclkfreq%dreturn-}outofrange!\n",mx6_sabrelite_audio_data.sysclk=rate;clk_set_rate(clko,rate);return}staticstructimx_ssi_platform_datamx6_sabrelite_ssi_pdata=.flags=IMX_SSI_DMA|staticstructmxc_audio_platform_datastaticstructimx_ssi_platform_datamx6_sabrelite_ssi_pdata=.flags=IMX_SSI_DMA|staticstructmxc_audio_platform_data.ssi_num1,//SSI.src_port2,//AudmuxAudmuxPort.ext_port4,//AudmuxAudmuxPort={.init=.hp_gpio=-staticstructplatform_devicemx6_sabrelite_audio_device=.name="imx- 音頻驅(qū)動(dòng)移植范例:WM8524(OTT硬件MX6XOTTSetBoxWolfsonWM8524codec,這個(gè)一個(gè)單純的DAC,只是單純的I2S信號(hào)進(jìn)行數(shù)模轉(zhuǎn)換,沒(méi)有I2C控制通道,所以可以說(shuō)其codec層功能幾乎沒(méi)有,很多類(lèi)似codec都可以借用這個(gè)驅(qū)動(dòng),其硬件可以參考i.MX6XOTTSetBox的硬件原理圖。另外,這種codec一般做從,所以是由i.MX6X的audioPLL產(chǎn)生時(shí)鐘的,因?yàn)槠鋬?nèi)部沒(méi)有PLL,所以需要提供精確的22.5762M的時(shí)鐘。7.2軟件目錄移植到 需要修改的文件如下Kconfig,Makefile85247.2軟件目錄移植到 需要修改的文件如下Kconfig,Makefile8524\sound\soc\imx\imx-pcm-dma-否PCM驅(qū)動(dòng)和 寄存器定否\sound\soc\imx\imx-否\sound\soc\imx\imx-否Kconfig,Makefile7.3軟件說(shuō)明\/*ConnectingWM85247.3軟件說(shuō)明\/*ConnectingWM8524audio/*AP_AUD5_TXC(AudioOutTXCLK)*/MX6Q_PAD_DISP0_DAT16AUDMUX_AUD5_TXC,/*AP_AUD5_TXD(AudioOutTXD)*/MX6Q_PAD_DISP0_DAT17AUDMUX_AUD5_TXD,/*AP_AUD5_TXFS(AudioOutTXFS)*//*AUD_nMUTE(AudioOutMutecontrol)*/MX6Q_PAD_DISP0_DAT19GPIO_5_13,/*AUD_MCLK(AudioDACMCLK)*/MX6Q_PAD_GPIO_0CCM_CLKO,/*Addaudiostaticstructmxc_audio_platform_datastructplatform_devicemx6_ott_audio_wm8524_device=.name="imx-structplatform_devicemx6_ott_audio_wm8524_codec=.name="wm8524-WM8524支staticintmxc_wm8524_init(void){intstructclkclko=clk_get(NULL,"clko_clk");if(IS_ERR(clko)){pr_err("can'tgetCLKOclock.\n");returnPTR_ERR(clko);}rate=clk_round_rate(clko,22579200);clk_set_rate(clko,rate);wm8524_data.sysclk=return}structmxc_audio_platform_data====5,//外部連接structimx_ssi_platform_datamx6_ott_ssi_pdata=.flags=IMX_SSI_DMA|{void__initgpio_request(OTT_AUDIO_MUTE,"audio-mute");gpio_direction_output(OTT_AUDIO_MUTE,1);mxc_register_device(&mx6_ott_audio_wm8524_codec,NULL);imx6q_add_imx_ssi(1,&mx6_ott_ssi_pdata);}I2C#define(SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|\staticstructsnd_soc_dai_driverwm8524_dai=.name="wm8524-staticstructsnd_soc_dai_driverwm8524_dai=.name="wm8524-.playback=.stream_name=.channels_min=.channels_max=.rates=.formats=SNDRV_PCM_FMTBIT_S16_LE|staticstructsnd_soc_codec_driverstatic__devinitintwm8524_probe(structplatform_device{&soc_codec_dev_wm8524,&wm8524_dai,}staticint__devexitwm8524_remove(structplatform_device{return0;}staticstructplatform_driverwm8524_codec_driver=.driver=.name="wm8524-.owner=.probe=.remove=staticintinit{}staticvoidexit{}MODULE_DESCRIPTION("ASoCwm8524在文件\sound\soc\imx\imx-wm8524.c,WM8524工作在從模式staticintstaticintimx_hifi_hw_params(structsnd_pcm_substreamstructsnd_pcm_hw_params{dai_format=SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_IF從而在imx-ssi.c中,ssi的配置為從模式/*DAIclockmastermasksswitch(fmt&{casestrcr|=SSI_STCR_TFDIR|if((fmt&SND_SOC_DAIFMT_FORMAT_MASK)=={scr&=scr|=InformationinInformationinthisdocumentisprovidedsolelytoenablesystemandsoftwareimplementerstouseFreescaleSemiconductorproducts.Therearenoexpressorimpliedcopyrightlicensesgrantedhereundertodesignorfabricateanyintegratedcircuitsorintegratedcircuitsbasedontheinformationinthisdocument.FreescaleSemiconductorreservestherighttomakechangeswithoutfurthernoticetoanyproductsherein.FreescaleSemiconductormakesnowarranty,representationorguaranteeregardingthesuitabilityofitsproductsfor
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 北京市昌平區(qū)臨川育人學(xué)校2025屆高三第六次模擬考試化學(xué)試卷含解析
- 2024-2025學(xué)年下學(xué)期高三英語(yǔ)人教版同步經(jīng)典題精練之固定搭配和句型
- 怎做紋繡培訓(xùn)
- ESC感染性心內(nèi)膜炎指南
- 護(hù)膚管理軟件應(yīng)用
- 護(hù)理管理學(xué)組織
- 探索物聯(lián)網(wǎng)在醫(yī)療行業(yè)的應(yīng)用
- 山東省濰坊市奎文區(qū)瀚聲學(xué)校2024-2025學(xué)年六年級(jí)下學(xué)期3月月考語(yǔ)文試題(有答案)
- 用微課學(xué) 圖形圖像處理(Photoshop CS6)課件 項(xiàng)目一 基本操作
- 【大數(shù)據(jù)百家講壇】2025年DeepSeek、Manus與AI+Agent行業(yè)現(xiàn)狀報(bào)告
- 二零二五年度研學(xué)旅行基地運(yùn)營(yíng)管理合同協(xié)議
- 2025重慶市安全員B證考試題庫(kù)附答案
- 倉(cāng)儲(chǔ)場(chǎng)所消防安全培訓(xùn)
- 山東煙臺(tái)歷年中考語(yǔ)文文言文閱讀試題22篇(含答案與翻譯)(截至2023年)
- 大學(xué)課件-電路分析基礎(chǔ)
- 2025年中國(guó)流行成分和原料消費(fèi)深度洞察白皮書(shū)
- 2025年昆明長(zhǎng)水機(jī)場(chǎng)勤務(wù)員招聘筆試參考題庫(kù)含答案解析
- (八省聯(lián)考)陜西省2025年高考綜合改革適應(yīng)性演練 生物試卷(含答案詳解)
- 《光電對(duì)抗原理與應(yīng)用》課件第3章
- 二次供水水箱清洗操作流程
- AEO貿(mào)易安全培訓(xùn)
評(píng)論
0/150
提交評(píng)論