i mx6xasoc音頻驅(qū)動說明與定制安卓源_第1頁
i mx6xasoc音頻驅(qū)動說明與定制安卓源_第2頁
i mx6xasoc音頻驅(qū)動說明與定制安卓源_第3頁
i mx6xasoc音頻驅(qū)動說明與定制安卓源_第4頁
i mx6xasoc音頻驅(qū)動說明與定制安卓源_第5頁
已閱讀5頁,還剩54頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

i.MX6XASOC音頻驅(qū)動說明與定制JohnLi(R64710)GSMFAEFreescaleSemiconductor,Inc.此文件用于幫助理解基于Freescale的i.MX6X的ASOC1ALSAandASOC基本概 ASoC的由i.MX6XASOC音頻驅(qū)動說明與定制JohnLi(R64710)GSMFAEFreescaleSemiconductor,Inc.此文件用于幫助理解基于Freescale的i.MX6X的ASOC1ALSAandASOC基本概 ASoC的由 硬件架 軟件架 數(shù)據(jù)結(jié) 2音頻驅(qū)動的流程,平臺數(shù)據(jù),內(nèi)核配置與測 音頻驅(qū)動的打開流 音頻驅(qū)動平臺數(shù) 音頻驅(qū)動內(nèi)核配 音頻驅(qū)動的測 3音頻驅(qū)動ASoC的機器 注冊Platform 注冊Platform 初始化入口soc_probe 4音頻驅(qū)動ASoC的Codec Codec簡 ASoC中對Codec的數(shù)據(jù)抽 Codec的注 Codec初始 regmap- 5音頻驅(qū)動ASoC的Codec Platform驅(qū)動在ASoC中的作 snd_soc_platform_driver的注 snd_soc_platform_driver中的ops字 音頻數(shù)據(jù)的dma操 cpu的snd_soc_daidriver驅(qū)動的注 snd_soc_dai_driver中的ops字 音頻驅(qū)動移植范例:SGTL5000(Sabe 6硬件設(shè) 軟件目 軟件說 7音頻驅(qū)動移植范例:WM8524(OTTSetBo 硬件設(shè) 軟件目 軟件說 Createthe ALSAandASOC基本 ALSAandASOC基本概ALSAAdvancedLinuxSoundArchitecturelinuxalsa-lib,alsa-API,圖動層的實現(xiàn)細節(jié),簡化了應(yīng)用程序的實現(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中的時鐘、DMA、I2S、PCM等等,只要指定了SoC,那么我們可以認為它會有一個對應(yīng)的Platform,它只與SoC相關(guān),與Machine無關(guān),這樣我們就Codec機、喇叭、聽筒,Line-out),Codec和Platform一樣,是可重用的部件,同一個架構(gòu)CodecCodecoCodecDAIPCMooCodecDAIPCMoCodecIO(I2C,SPIoCodecALSAoDAPMoDAPMoDACPlatform等等Machinei.MX6XSSIcodec以首先檢查這個文件夾有沒有相應(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取代了它,并且強化了snd_soc_pcm_runtime的作用,同時還增加了另外兩個數(shù)據(jù)結(jié)構(gòu)snd_soc_codec_driversnd_soc_platform_driver,用于明確代表Codec驅(qū)Platform驅(qū)動。后續(xù)的章節(jié)中將會逐一介紹MachinePlatformCodec驅(qū)動的工作細 音頻驅(qū)動 音頻驅(qū)動的流程,平臺數(shù)據(jù),內(nèi)核配置與測試2.1音頻驅(qū)動的打開流程ALSA提供硬件能力給ALSAruntime信息(包括硬件,DMA,軟件支持能力)配置讀寫DMA通道CPUDAICodecDAI接口配置Codec硬件音頻傳輸觸發(fā)后,接下來的DMA讀寫操作則由DMACallback2.2音頻驅(qū)動平臺數(shù)據(jù)臺數(shù)據(jù)結(jié)構(gòu),其中成員需要根據(jù)具體硬件設(shè)計配置,參考wm8962的設(shè)置:staticstructmxc_audio_platform_datawm8962_data=.ssi_num1,SSI通道數(shù)目,目前大部分音頻codec.src_port=2,表示連接到SSI上的Audmux接口號,參考i.MX6XRM一般Port1,2,7連一般Port1,2,7連接到內(nèi)SSI上,3,4,5,6連接到外部的pin上連接到外部saberSDP板上使用的是.hp_gpio=SABRESD_HEADPHONE_DET,//耳機檢查所用的.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的主時鐘是由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ū)動內(nèi)核配置 的音頻內(nèi)核menuconf 配置為Devicedrivers>Soundcardsupport>AdvancedLinuxSoundArchitecture>ALSAforSoCaudiosupport>SoCAudiofortheFreescalei.MXCPU,SoCAudiosupportforWM89622.4音頻驅(qū)動的測試音頻驅(qū)動支持放音,錄音,音量調(diào)節(jié)等,都可以通過ALSA應(yīng)用程序來測。aplay[-Dplughw:0,0]WM8962IN3RWM8962IN3Ramixersset'MIXINRIN3R'onamixersset'INPGARIN3R'arecord[-Dplughw:0,0]-r44100-fS16_LE-c2-d5aplay–harecord 音頻驅(qū)動ASoC的機器前面一節(jié)的內(nèi)容我們提到,ASoCMachine、PlatformCodec三大部分,其中的MachinePlatformCodec之間的耦合以及部分和設(shè)備或板子特定的代碼,再次引用上一節(jié)的內(nèi)容:Machine驅(qū)動負責(zé)處理機器特有的一些控件和音頻事件(例如,當(dāng)播放音頻時,需要先行打開一個放大器);單獨的Platform和Codec驅(qū)動是不能工作的,它必須由Machine驅(qū)動把它們結(jié)合在一起才能完成整個設(shè)備的音頻處理工作。ASoC的一切都從Machine驅(qū)動開始,包括聲卡的注冊,綁定PlatformCodec驅(qū)動等等,下面就讓我們從Machine驅(qū)動3.1注冊PlatformASoC把聲卡注冊為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}由此可見,模塊初始化時,注冊了一個名為soc-audio的Platform設(shè)備,同時把snd_soc_card_imxplatform_devicedev.drvdata字段中,這里引出了第一個數(shù)據(jù)結(jié)構(gòu)snd_soc_card的實例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ū)動將會利用這些名字去匹配已經(jīng)在系統(tǒng)中注冊的platform,codec,dai,這些注冊的部件都是在另外相應(yīng)的Platform驅(qū)動和Codec驅(qū)動的代碼文件中定義的,這樣看來,Machine驅(qū)動的設(shè)備初始化代碼無非就是選擇合適Platform和Codec以及dai,用他們填充以上幾個數(shù)據(jù)結(jié)構(gòu),然后注冊Platform設(shè)備即可。當(dāng)然還要實現(xiàn)連接PlatformCodecdai_link對應(yīng)的ops實現(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(實例snd_soc_ops(3.2注冊Platformplatform_driver。ASoCstaticintinit{return}/*ASoCplatformdriver3.2注冊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來判斷該卡是否已經(jīng)實例化,如果已經(jīng)實例化則直接返/*bindDAIsfor(i=0;i<card->num_links;soc_bind_dai_link(card,ASoC定義了三個全局的鏈表頭變量:codec_list、dai_list、platform_list,系統(tǒng)中所有的函數(shù)逐個掃描這三個鏈表,根據(jù)card->dai_link[]中的名稱進行匹配,匹配后把相應(yīng)的codec,dai和platform實例賦值到card->rtd[]中(snd_soc_pcm_runtime)。經(jīng)過這個過程后,/*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ū)動ASoC的Codec4.1Codec簡介代碼不經(jīng)修改即可用在不同的平臺上。以下的討論基于wolfsonCodec代碼不經(jīng)修改即可用在不同的平臺上。以下的討論基于wolfsonCodecWM8962,kernel的版本3.0.354.2ASoC中對Codec的數(shù)抽象描述Codec的最主要的幾個數(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ū)動中也會使用到,PlatformCodecDAIsnd_soc_dai_link段,詳細的定義請參照:/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,臺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的注因為Codec驅(qū)動的代碼要做到平臺無關(guān)性,要使得Machine驅(qū)動能夠使用該Codec,Codec驅(qū)動的首要任務(wù)就是確定和的實例,并把它們注冊到系統(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}從而注冊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=可見,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一樣,最后也會調(diào)用snd_soc_instantiate_cards4.44.4Codec初始Machine驅(qū)動的初始化,codec和dai的注冊,都會調(diào)用snd_soc_instantiate_cards進codec,dai,platformMachine文中所描述,就是通過3個全局鏈表,按名字進行匹配,把匹配的codec,daiplatform實例賦值給聲卡每對dai的snd_soc_pcm_runtime變量中。一旦綁定成功,將會使得codec和dai驅(qū)動的probe回調(diào)被調(diào)用,codec的初始化工作就在該回調(diào)中完成。對于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ū)動ASoC的Codec5.1Platform驅(qū)動ASoC中的作用CPU(DAI)把音頻數(shù)據(jù)傳送給Platform驅(qū)動分為兩個部分:snd_soc_platform_driver和snd_soc_dai_driver。其中,platform_driverdmacpudai5.2snd_soc_platform_driver的注冊通常,ASoCsnd_soc_platform_driver注冊為一個系統(tǒng)的platform_driver迷惑,前者只是針對ASoC子系統(tǒng)的,后者是來自Linux的設(shè)備驅(qū)動模型。我們要做的就是:snd_soc_platform_driver在platform_driver的probe回調(diào)中利用ASoC的API:snd_soc_register_platform()注冊上snd_soc_platform_driver在platform_driver的probe回調(diào)中利用ASoC的API:snd_soc_register_platform()注冊上面定義的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的管理等工作。下面介紹幾個重要設(shè)置snd_pcm_runtime結(jié)構(gòu)中的dmabuffer5.4音頻數(shù)dma操作因為dma的特殊性,dmabuffer是一塊特殊的內(nèi)存,比如有的平臺規(guī)定只有某段地址范方便dma控制器對內(nèi)存的訪問。在ASoC架構(gòu)中,dmabuffer的信息保存在snd_pcm_substream結(jié)構(gòu)的snd_dma_buffer*bufstructsnd_dma_bufferunsignedchar*area;dma_addr_taddr;size_tbytes;void/*devicetype因為dma的特殊性,dmabuffer是一塊特殊的內(nèi)存,比如有的平臺規(guī)定只有某段地址范方便dma控制器對內(nèi)存的訪問。在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ū)動的注冊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)的實例: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)準的snd_soc_ops抗pop,pop由soc-core以下這些api通常被machine驅(qū)動使用,machine驅(qū)動在他的snd_pcm_ops抗pop,pop由soc-core以下這些api通常被machine驅(qū)動使用,machine驅(qū)動在他的snd_pcm_opsASoCASoCPlatform 音 音頻驅(qū)動移植范例硬件SGTL5000,有些客戶也想在i.MX6X上使用,可以參考i.MX6XSaberLite的硬件原理圖和i.MX6XAUD4I2SSGTL5000,I2C1連接控制接口,然后通過GPIO0i.MX6XAUD4I2SSGTL5000,I2C1連接控制接口,然后通過GPIO0供給時鐘給SGTL5000,SGTL5000 做主,i.MX6X做從,類似于WM8962.6.2軟件目錄與 類似,移植到SGT 需要修改的文件如下\sound\soc\imx\imx- 機器層文件6.3軟件說明i.MX6X的所有芯片與開發(fā)板使用同一個uImage二級制內(nèi)核,所以其imx6_defconfig包括了目前Freescale的i.MX6X開發(fā)板所連接的所有外設(shè)驅(qū)動支持,所以可以確認:\arch\arm\configs\imx6_defconfig,也增加了支持,如下AUDMUX6.3軟件說明i.MX6X的所有芯片與開發(fā)板使用同一個uImage二級制內(nèi)核,所以其imx6_defconfig包括了目前Freescale的i.MX6X開發(fā)板所連接的所有外設(shè)驅(qū)動支持,所以可以確認:\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ū)動和 寄存器定否\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ū)動移植范例:WM8524(OTT硬件MX6XOTTSetBoxWolfsonWM8524codec,這個一個單純的DAC,只是單純的I2S信號進行數(shù)模轉(zhuǎn)換,沒有I2C控制通道,所以可以說其codec層功能幾乎沒有,很多類似codec都可以借用這個驅(qū)動,其硬件可以參考i.MX6XOTTSetBox的硬件原理圖。另外,這種codec一般做從,所以是由i.MX6X的audioPLL產(chǎn)生時鐘的,因為其內(nèi)部沒有PLL,所以需要提供精確的22.5762M的時鐘。7.2軟件目錄移植到 需要修改的文件如下Kconfig,Makefile85247.2軟件目錄移植到 需要修改的文件如下Kconfig,Makefile8524\sound\soc\imx\imx-pcm-dma-否PCM驅(qū)動和 寄存器定否\sound\soc\imx\imx-否\sound\soc\imx\imx-否Kconfig,Makefile7.3軟件說明\/*ConnectingWM85247.3軟件說明\/*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. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論