12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366 |
- --- a/sound/soc/Kconfig
- +++ b/sound/soc/Kconfig
- @@ -56,6 +56,7 @@ source "sound/soc/spear/Kconfig"
- source "sound/soc/tegra/Kconfig"
- source "sound/soc/txx9/Kconfig"
- source "sound/soc/ux500/Kconfig"
- +source "sound/soc/mtk/Kconfig"
-
- # Supported codecs
- source "sound/soc/codecs/Kconfig"
- --- a/sound/soc/Makefile
- +++ b/sound/soc/Makefile
- @@ -33,3 +33,4 @@ obj-$(CONFIG_SND_SOC) += spear/
- obj-$(CONFIG_SND_SOC) += tegra/
- obj-$(CONFIG_SND_SOC) += txx9/
- obj-$(CONFIG_SND_SOC) += ux500/
- +obj-$(CONFIG_SND_SOC) += mtk/
- --- a/sound/soc/codecs/Kconfig
- +++ b/sound/soc/codecs/Kconfig
- @@ -725,7 +725,7 @@ config SND_SOC_WM8955
- tristate
-
- config SND_SOC_WM8960
- - tristate
- + tristate "WM8960"
-
- config SND_SOC_WM8961
- tristate
- --- /dev/null
- +++ b/sound/soc/mtk/Kconfig
- @@ -0,0 +1,35 @@
- +config SND_MT76XX_SOC
- + tristate "SoC Audio for MT76XX APSoC Machine"
- + depends on SND_SOC && (SOC_MT7620 || SOC_MT7621)
- +
- + help
- + Say Y or M if you want to add support for codecs attached to
- + the MTK I2S interface.
- +
- +choice
- + prompt "Selected SoC type"
- + depends on SND_MT76XX_SOC
- + default SND_MT76XX_SOC_MT7620
- +
- +config SND_MT76XX_SOC_MT7620
- + bool "MT7620"
- + depends on SOC_MT7620
- +
- +config SND_MT76XX_SOC_MT7628
- + bool "MT7628"
- + depends on SOC_MT7620
- +
- +config SND_MT76XX_SOC_MT7621
- + bool "MT7621"
- + depends on SOC_MT7621
- +
- +endchoice
- +
- +config SND_MT76XX_PCM
- + tristate "MTK SoC Audio PCM Platform"
- + depends on SND_MT76XX_SOC
- +
- +config SND_MT76XX_I2S
- + tristate "MTK SoC I2S Support"
- + depends on SND_MT76XX_SOC
- +
- --- /dev/null
- +++ b/sound/soc/mtk/Makefile
- @@ -0,0 +1,40 @@
- +KBUILD_CFLAGS += -I$(srctree)
- +
- +ifeq ($(CONFIG_SND_MT76XX_SOC_MT7620),y)
- +KBUILD_CFLAGS += -DCONFIG_MT7620 -DCONFIG_RALINK_MT7620
- +endif
- +ifeq ($(CONFIG_SND_MT76XX_SOC_MT7628),y)
- +KBUILD_CFLAGS += -DCONFIG_MT7628 -DCONFIG_RALINK_MT7628
- +endif
- +ifeq ($(CONFIG_SOC_MT7620),y)
- +KBUILD_CFLAGS += -DRALINK_SYSCTL_BASE=0xB0000000
- +KBUILD_CFLAGS += -DRALINK_INTCL_BASE=0xB0000200
- +KBUILD_CFLAGS += -DRALINK_PIO_BASE=0xB0000600
- +KBUILD_CFLAGS += -DRALINK_I2S_BASE=0xB0000A00
- +KBUILD_CFLAGS += -DRALINK_GDMA_BASE=0xB0002800
- +KBUILD_CFLAGS += -DCONFIG_GDMA_EVERYBODY
- +KBUILD_CFLAGS += -DCONFIG_SND_MT76XX_SOC
- +KBUILD_CFLAGS += -DCONFIG_I2S_WM8960
- +#KBUILD_CFLAGS += -DCONFIG_I2S_MCLK_12P288MHZ
- +KBUILD_CFLAGS += -DCONFIG_I2S_MCLK_12MHZ
- +KBUILD_CFLAGS += -DCONFIG_GDMA_EVERYBODY
- +KBUILD_CFLAGS += -DSURFBOARDINT_DMA=15
- +KBUILD_CFLAGS += -DRALINK_INTCTL_DMA=128
- +KBUILD_CFLAGS += -DCONFIG_SND_SOC_WM8960
- +endif
- +
- +# MTK APSoC Platform Support
- +snd-soc-mt76xx-i2s-ctl-objs := i2s_ctrl.o i2s_debug.o #i2c_wm8960.o
- +snd-soc-mt76xx-pcm-objs := mt76xx_pcm.o
- +snd-soc-mt76xx-i2s-objs := mt76xx_i2s.o
- +
- +obj-$(CONFIG_SND_MT76XX_PCM) += snd-soc-mt76xx-pcm.o
- +obj-$(CONFIG_SND_MT76XX_I2S) += snd-soc-mt76xx-i2s-ctl.o snd-soc-mt76xx-i2s.o
- +
- +# MTK APSoC Machine Support
- +snd-soc-mt76xx-machine-objs := mt76xx_machine.o
- +
- +obj-$(CONFIG_SND_MT76XX_SOC) += i2c_wm8960.o ralink_gdma.o snd-soc-mt76xx-machine.o
- +
- +
- +
- --- /dev/null
- +++ b/sound/soc/mtk/i2c_wm8960.c
- @@ -0,0 +1,492 @@
- +#include <linux/kernel.h>
- +#include <linux/version.h>
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/slab.h>
- +#include <linux/i2c.h>
- +#include <linux/delay.h>
- +#include <linux/interrupt.h>
- +#include <linux/fs.h>
- +#include <linux/fcntl.h>
- +#include <linux/cdev.h>
- +#if defined(CONFIG_ARCH_MT7623)
- +#include <mt_i2c.h>
- +#include <mach/mt_gpio.h>
- +#endif
- +#include "i2c_wm8960.h"
- +#include "i2s_ctrl.h"
- +
- +
- +#define BUF_SIZE 20
- +
- +#undef MSG
- +#define MSG printk
- +
- +
- +#if defined(CONFIG_ARCH_MT7623)
- +/*FIXME*/
- +//static struct i2c_board_info __initdata i2c_devs1 = { I2C_BOARD_INFO("codec_wm8960", (0X34>>1))};
- +static struct i2c_board_info __initdata i2c_devs1 = { I2C_BOARD_INFO("codec_wm8960", (0X34))};
- +
- +#endif
- +unsigned long wm_reg_data[56];
- +struct wm8960_data *wmio;
- +
- +struct wm8960_data {
- + struct i2c_client *client;
- + struct device *dev;
- + const char *name;
- +};
- +
- +
- +void i2c_WM8960_write(u32 reg, u32 data)
- +{
- + int ret;
- + struct i2c_msg msg;
- + u8 buf[2]={0};
- +
- +#if defined(CONFIG_ARCH_MT7623)
- + unsigned int ext_flag = 0;
- +
- + ext_flag &= 0x7FFFFFFF;
- + ext_flag |= I2C_A_FILTER_MSG;
- + ext_flag |= I2C_POLLING_FLAG;
- +#endif
- +
- + wm_reg_data[reg] = data;
- +
- + buf[0]= (reg<<1)|(0x01&(data>>8));
- + buf[1]= (data&0xFF);
- +
- +#if defined(CONFIG_ARCH_MT7623)
- + /*FIXME*/
- + //msg.addr = wmio->client->addr;
- + msg.addr = wmio->client->addr>>1;
- +
- +#else
- + msg.addr = wmio->client->addr>>1;
- +#endif
- + msg.flags = 0;
- + msg.buf = (char *)buf;
- + msg.len = 2;
- +#if defined(CONFIG_ARCH_MT7623)
- + msg.timing = 80;
- + msg.ext_flag = ext_flag & 0x7FFFFFFF;
- +#endif
- +
- + ret = i2c_transfer(wmio->client->adapter, &msg, 1);
- + MSG("[WM8960(%02X)=0x%08X]\n",(unsigned int)reg,(unsigned int)data);
- +
- + if (ret <= 0)
- + printk("%s: i2c write error!\n", __func__);
- +}
- +
- +
- +
- +// Reset and power up the WM8960
- +void audiohw_preinit(void)
- +{
- + memset(wm_reg_data, 0 , sizeof(unsigned long)*55);
- +
- + i2c_WM8960_write(RESET, RESET_RESET); // Reset (0x0F)
- +
- + mdelay(50);
- + wm_reg_data[RESET] = 0xFFFF;
- + mdelay(50);
- +}
- +
- +void audiohw_set_apll(int srate)
- +{
- + unsigned long data;
- +
- + if((srate==8000) || (srate==12000) || (srate==16000) || (srate==24000) || (srate==32000) || (srate==48000))
- + {
- + // Provide 12.288MHz SYSCLK
- + data = wm_reg_data[PLL1];
- + i2c_WM8960_write(PLL1, data | PLL1_OPCLKDIV_1 | PLL1_SDM_FRACTIONAL | PLL1_PLLPRESCALE_1 | PLL1_PLLN(0x8)); // PLL1 (0x34)
- +
- + i2c_WM8960_write(PLL2, PLL2_PLLK_23_16(0x31)); // PLL2 (0x35)
- + i2c_WM8960_write(PLL3, PLL3_PLLK_15_8(0x26)); // PLL3 (0x36)
- + i2c_WM8960_write(PLL4, PLL4_PLLK_7_0(0xe9)); // PLL4 (0x37)
- + }
- + else if ((srate==11025) || (srate==22050) || (srate==44100))
- + {
- + //Provide 11.2896MHz SYSCLK
- + data = wm_reg_data[PLL1];
- + i2c_WM8960_write(PLL1, data | PLL1_OPCLKDIV_1 | PLL1_SDM_FRACTIONAL | PLL1_PLLPRESCALE_1 | PLL1_PLLN(0x7)); //PLL1 (0x34)
- +
- + i2c_WM8960_write(PLL2, PLL2_PLLK_23_16(0x86)); //PLL2 (0x35)
- + i2c_WM8960_write(PLL3, PLL3_PLLK_15_8(0xc2)); //PLL3 (0x36)
- + i2c_WM8960_write(PLL4, PLL4_PLLK_7_0(0x26)); //PLL4 (0x37)
- + }
- + else
- + {
- + printk("Not support this srate\n");
- + }
- + mdelay(3);
- +}
- +
- +
- +void audiohw_set_frequency(int fsel, int pll_en)
- +{
- + MSG("audiohw_set_frequency_=0x%08X\n",fsel);
- +
- + if (pll_en)
- + {
- + printk("PLL enable\n");
- + i2c_WM8960_write(CLOCKING1, (fsel<<3) | CLOCKING1_SYSCLKDIV_2 | CLOCKING1_CLKSEL_PLL); //CLOCKING (0x04)=>0x05
- +
- + }
- + else
- + {
- + printk("PLL disable\n");
- + i2c_WM8960_write(CLOCKING1, (fsel<<3));//| CLOCKING1_SYSCLKDIV_2); //CLOCKING (0x04)
- + }
- +
- +}
- +
- +//FIXME
- +int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r)
- +{
- + MSG("audiohw_set_lineout_vol_\n");
- + switch(Aout)
- + {
- + case 1:
- + //i2c_WM8960_write(LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(0x7f)); //LOUT1(0x02)
- + //i2c_WM8960_write(ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(0x7f)); //ROUT1(0x03)
- + i2c_WM8960_write(LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(vol_l)); //LOUT1(0x02)
- + i2c_WM8960_write(ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(vol_r)); //ROUT1(0x03)
- + break;
- + case 2:
- + i2c_WM8960_write(LSPK, LSPK_SPKLVU|LSPK_SPKLZC| LSPK_SPKLVOL(vol_l));
- + i2c_WM8960_write(RSPK, RSPK_SPKRVU|RSPK_SPKRZC| RSPK_SPKRVOL(vol_r));
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +//FIXME
- +int audiohw_set_linein_vol(int vol_l, int vol_r)
- +{
- + MSG("audiohw_set_linein_vol_\n");
- +
- + i2c_WM8960_write(LINV, LINV_IPVU|LINV_LINVOL(vol_l)); //LINV(0x00)=>0x12b
- + i2c_WM8960_write(RINV, RINV_IPVU|RINV_RINVOL(vol_r)); //LINV(0x01)=>0x12b
- +
- + return 0;
- +}
- +
- +//Set signal path
- +int audiohw_postinit(int bSlave, int AIn, int AOut, int pll_en, int wordLen24b)
- +{
- +
- + int i;
- + unsigned long data;
- +
- + if(wm_reg_data[RESET]!=0xFFFF)
- + return 0;
- +
- + if(bSlave)
- + {
- + MSG("WM8960 slave.....\n");
- + if(wordLen24b)
- + {
- + printk("24 bit word length\n");
- + i2c_WM8960_write(AINTFCE1, AINTFCE1_WL_24 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07)
- + }
- + else
- + {
- + printk("16 bit word length\n");
- + i2c_WM8960_write(AINTFCE1, AINTFCE1_WL_16 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07)
- + }
- + }
- + else
- + {
- + MSG("WM8960 master.....\n");
- + i2c_WM8960_write(CLOCKING2, 0x1c4);//CLOCKING2_BCLKDIV(0x1c4)); //CLOCKING2(0x08)
- +
- + if(wordLen24b)
- + {
- + printk("24 bit word length\n");
- + i2c_WM8960_write(AINTFCE1, AINTFCE1_MS | AINTFCE1_WL_24 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07)
- + }
- + else
- + {
- + printk("16 bit word length\n");
- + i2c_WM8960_write(AINTFCE1, AINTFCE1_MS | AINTFCE1_WL_16 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07)
- + }
- + mdelay(5);
- + }
- +
- +
- + //From app notes: allow Vref to stabilize to reduce clicks
- + for(i = 0; i < 1000*HZ; i++);
- +
- + if(AIn > 0)
- + {
- + data = wm_reg_data[PWRMGMT1];
- + i2c_WM8960_write(PWRMGMT1, data|PWRMGMT1_ADCL|PWRMGMT1_ADCR|PWRMGMT1_AINL |PWRMGMT1_AINR);//|PWRMGMT1_MICB);//PWRMGMT1(0x19)
- +
- + data = wm_reg_data[ADDITIONAL1];
- + i2c_WM8960_write(ADDITIONAL1, data|ADDITIONAL1_DATSEL(0x01)); //ADDITIONAL1(0x17)
- + i2c_WM8960_write(LADCVOL, LADCVOL_LAVU_EN|LADCVOL_LADCVOL(0xc3)); //LADCVOL(0x15)
- + i2c_WM8960_write(RADCVOL, RADCVOL_RAVU_EN|RADCVOL_RADCVOL(0xc3)); //RADCVOL(0x16)
- + i2c_WM8960_write(ADCLPATH, ADCLPATH_LMN1|ADCLPATH_LMIC2B);//|ADCLPATH_LMICBOOST_13DB); //ADCLPATH(0x20)=>(0x108)
- + i2c_WM8960_write(ADCRPATH, ADCRPATH_RMN1|ADCRPATH_RMIC2B);//|ADCRPATH_RMICBOOST_13DB); //ADCRPATH(0x21)=>(0x108)
- + i2c_WM8960_write(PWRMGMT3, PWRMGMT3_LMIC|PWRMGMT3_RMIC); //PWRMGMT3(0x2f)
- +
- + //i2c_WM8960_write(LINBMIX, 0x000); //LINBMIX(0x2B)
- +
- + if (AOut<=0)
- + {
- + i2c_WM8960_write(AINTFCE2, 0x40); //FIXME:(0x09)
- +
- + data = wm_reg_data[PWRMGMT2];
- + if(pll_en)
- + {
- + i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_PLL_EN|PWRMGMT2_DACL|PWRMGMT2_DACR); //PWRMGMT2(0x1a)
- + }
- + else
- + {
- + i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_DACL|PWRMGMT2_DACR); //PWRMGMT2(0x1a)
- +
- + }
- + }
- + }
- + if(AOut>0)
- + {
- + //Power management 2 setting
- + data = wm_reg_data[PWRMGMT2];
- +
- + if(pll_en)
- + {
- + i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_PLL_EN|PWRMGMT2_DACL|PWRMGMT2_DACR|PWRMGMT2_LOUT1|PWRMGMT2_ROUT1|PWRMGMT2_SPKL|PWRMGMT2_SPKR); //PWRMGMT2(0x1a)
- + }
- + else
- + {
- + i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_DACL|PWRMGMT2_DACR|PWRMGMT2_LOUT1|PWRMGMT2_ROUT1|PWRMGMT2_SPKL|PWRMGMT2_SPKR); //PWRMGMT2(0x1a)
- +
- + }
- +
- + mdelay(10);
- +
- + i2c_WM8960_write(AINTFCE2, 0x40); //FIXME:(0x09)
- +
- + i2c_WM8960_write(LEFTGAIN, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xff)); //LEFTGAIN(0x0a)
- + i2c_WM8960_write(RIGHTGAIN, RIGHTGAIN_RDVU|RIGHTGAIN_RDACVOL(0xff)); //RIGHTGAIN(0x0b)
- +
- + i2c_WM8960_write(LEFTMIX1, 0x100); //LEFTMIX1(0x22)
- + i2c_WM8960_write(RIGHTMIX2, 0x100); //RIGHTMIX2(0x25)
- +
- + data = wm_reg_data[PWRMGMT3]; //FIXME
- + i2c_WM8960_write(PWRMGMT3, data|PWRMGMT3_ROMIX|PWRMGMT3_LOMIX); //PWRMGMT3(0x2f)
- +
- + data = wm_reg_data[CLASSDCTRL1]; //CLASSDCTRL1(0x31) SPEAKER FIXME
- + i2c_WM8960_write(CLASSDCTRL1, 0xf7);//data|CLASSDCTRL1_OP_LRSPK);
- +
- + data = wm_reg_data[CLASSDCTRL3]; //CLASSDCTRL3(0x33)
- + i2c_WM8960_write(CLASSDCTRL3, 0xad);//data|(0x1b));
- + }
- +
- + i2c_WM8960_write(DACCTRL1, 0x000); //DACCTRL1(0x05)
- +
- + data = wm_reg_data[PWRMGMT1];
- + i2c_WM8960_write(PWRMGMT1, data|0x1c0); //FIXME:PWRMGMT1(0x19)
- +
- +
- + printk("WM8960 All initial ok!\n");
- +
- + return 0;
- +
- +}
- +
- +void audiohw_micboost(int boostgain)
- +{
- + unsigned long data;
- +
- + data = wm_reg_data[ADCLPATH];
- + i2c_WM8960_write(ADCLPATH, data|(boostgain << 4));
- +
- + data = wm_reg_data[ADCRPATH];
- + i2c_WM8960_write(ADCRPATH, data|(boostgain << 4));
- +}
- +
- +void audiohw_micin(int enableMic)
- +{
- + unsigned long data;
- +
- + if (enableMic==1)
- + {
- + data = wm_reg_data[PWRMGMT1];
- + i2c_WM8960_write(PWRMGMT1, data|PWRMGMT1_MICB);
- + }
- +#if 1
- + else
- + {
- + data = wm_reg_data[PWRMGMT1];
- + i2c_WM8960_write(PWRMGMT1, data & (~(PWRMGMT1_MICB)));
- + }
- +#endif
- +}
- +
- +void audiohw_mute( bool mute)
- +{
- + //Mute: Set DACMU = 1 to soft-mute the audio DACs.
- + //Unmute: Set DACMU = 0 to soft-un-mute the audio DACs.
- + i2c_WM8960_write(DACCTRL1, mute ? DACCTRL1_DACMU : 0);
- +}
- +
- +
- +//Nice shutdown of WM8960 codec
- +void audiohw_close(void)
- +{
- + i2c_WM8960_write(DACCTRL1,DACCTRL1_DACMU); //0x05->0x08
- + i2c_WM8960_write(PWRMGMT1, 0x000); //0x19->0x000
- + mdelay(400);
- + i2c_WM8960_write(PWRMGMT2, 0x000); //0x1a->0x000
- +
- +}
- +
- +void audiohw_loopback(int fsel)
- +{
- +}
- +
- +void audiohw_codec_exlbk(void)
- +{
- + memset(wm_reg_data, 0 , sizeof(unsigned long)*55);
- +
- + i2c_WM8960_write(LINV, 0x117); //0x00->0x117
- + i2c_WM8960_write(RINV, 0x117); //0x01->0x117
- + i2c_WM8960_write(LOUT1, 0x179); //0x02->0x179
- + i2c_WM8960_write(ROUT1, 0x179); //0x03->0x179
- + i2c_WM8960_write(CLOCKING1, 0x00); //0x04->0x00
- + //i2c_WM8960_write(CLOCKING1, 0x40); //0x04->0x00
- + i2c_WM8960_write(DACCTRL1, 0x00); //0x05->0x00
- + i2c_WM8960_write(AINTFCE2, 0x41); //0x09->0x41
- + i2c_WM8960_write(LADCVOL, 0x1c3); //0x15->0x1c3
- + i2c_WM8960_write(RADCVOL, 0x1c3); //0x16->0x1c3
- + i2c_WM8960_write(PWRMGMT1, 0xfc); //0x19->0xfc
- + i2c_WM8960_write(PWRMGMT2, 0x1e0); //0x1a->0x1e0
- + i2c_WM8960_write(ADCLPATH, 0x108); //0x20->0x108
- + i2c_WM8960_write(ADCRPATH, 0x108); //0x21->0x108
- + i2c_WM8960_write(LEFTMIX1, 0x150); //0x22->0x150
- + i2c_WM8960_write(RIGHTMIX2, 0x150); //0x25->0x150
- + i2c_WM8960_write(BYPASS1, 0x00); //0x2d->0x00
- + i2c_WM8960_write(BYPASS2, 0x00); //0x2e->0x00
- + i2c_WM8960_write(PWRMGMT3, 0x3c); //0x2f->0x3c
- +}
- +
- +void audiohw_bypass(void)
- +{
- + int i;
- +
- + memset(wm_reg_data, 0 , sizeof(unsigned long)*55);
- + i2c_WM8960_write(RESET, 0x000); //0x0f(R15)->0x000
- +
- + for(i = 0; i < 1000*HZ; i++);
- +
- + i2c_WM8960_write(PWRMGMT1, 0xf0); //0x19(R25)->0xf0
- + i2c_WM8960_write(PWRMGMT2, 0x60); //0x1a(R26)->0x60
- + i2c_WM8960_write(PWRMGMT3, 0x3c); //0x2f(R47)->0x3c
- + i2c_WM8960_write(LINV, 0x117); // 0x00(R0)->0x117
- + i2c_WM8960_write(RINV, 0x117); // 0x01(R1)->0x117
- + i2c_WM8960_write(ADCLPATH, 0x108); //0x20(R32)->0x108
- + i2c_WM8960_write(ADCRPATH, 0x108); //0x21(R33)->0x108
- + i2c_WM8960_write(BYPASS1, 0x80); //0x2d(R45)->0x80
- + i2c_WM8960_write(BYPASS2, 0x80); //0x2e(R46)->0x80
- + i2c_WM8960_write(LOUT1, 0x179); // 0x02(R2)->0x179
- + i2c_WM8960_write(ROUT1, 0x179); // 0x03(R3)->0x179
- +}
- +EXPORT_SYMBOL(audiohw_set_frequency);
- +EXPORT_SYMBOL(audiohw_close);
- +EXPORT_SYMBOL(audiohw_postinit);
- +EXPORT_SYMBOL(audiohw_preinit);
- +EXPORT_SYMBOL(audiohw_set_apll);
- +EXPORT_SYMBOL(audiohw_codec_exlbk);
- +EXPORT_SYMBOL(audiohw_bypass);
- +EXPORT_SYMBOL(audiohw_set_lineout_vol);
- +EXPORT_SYMBOL(audiohw_set_linein_vol);
- +EXPORT_SYMBOL(audiohw_micin);
- +EXPORT_SYMBOL(audiohw_mute);
- +EXPORT_SYMBOL(audiohw_loopback);
- +EXPORT_SYMBOL(audiohw_micboost);
- +
- +static int codec_wm8960_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- +{
- + struct wm8960_data *wm;
- +
- +printk("*******Enter %s********\n", __func__);
- +
- + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
- + return -EIO;
- +
- + wm = devm_kzalloc(&client->dev, sizeof(struct wm8960_data), GFP_KERNEL);
- + if (!wm)
- + return -ENOMEM;
- +
- +#if defined(CONFIG_ARCH_MT7623)
- + mt_set_gpio_mode(GPIO242, GPIO_MODE_04);
- + mt_set_gpio_mode(GPIO243, GPIO_MODE_04);
- +#endif
- + wm->client = client;
- + wm->dev = &client->dev;
- + wm->name = id->name;
- + i2c_set_clientdata(client, wm);
- + wmio = wm;
- +
- + memset(wm_reg_data, 0 , sizeof(unsigned long)*55);
- +
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
- +static int codec_wm8960_i2c_remove(struct i2c_client *client)
- +#else
- +static int __devexit codec_wm8960_i2c_remove(struct i2c_client *client)
- +#endif
- +{
- + struct wm8960_data *wm = i2c_get_clientdata(client);
- + kfree(wm);
- +
- + return 0;
- +}
- +
- +static const struct i2c_device_id wm8960_id[] = {
- + { "codec_wm8960", 0 },
- + {}
- +};
- +
- +static struct i2c_driver codec_wm8960_i2c_driver = {
- + .driver = {
- + .name = "codec_wm8960"
- + },
- + .probe = codec_wm8960_i2c_probe,
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
- + .remove = codec_wm8960_i2c_remove,
- +#else
- + .remove = __devexit_p(codec_wm8960_i2c_remove),
- +#endif
- + .id_table = wm8960_id,
- +};
- +static int __init wm8960_i2c_init(void)
- +{
- +#if defined(CONFIG_ARCH_MT7623)
- + i2c_register_board_info(1, &i2c_devs1, 1);
- +#endif
- + return i2c_add_driver(&codec_wm8960_i2c_driver);;
- +}
- +
- +static void __exit wm8960_i2c_exit(void)
- +{
- + i2c_del_driver(&codec_wm8960_i2c_driver);
- +}
- +
- +module_init(wm8960_i2c_init);
- +module_exit(wm8960_i2c_exit);
- +
- +MODULE_AUTHOR("Ryder Lee <ryder.lee@mediatek.com>");
- +MODULE_DESCRIPTION("WM8960 I2C client driver");
- +MODULE_LICENSE("GPL");
- +
- --- /dev/null
- +++ b/sound/soc/mtk/i2c_wm8960.h
- @@ -0,0 +1,288 @@
- +/* wm8960.h -- WM8960 Soc Audio driver */
- +#ifndef _WM8960_H
- +#define _WM8960_H
- +
- +#define bool unsigned char
- +#define false 0
- +#define true 1
- +
- +/* volume/balance/treble/bass interdependency */
- +#define VOLUME_MIN -730
- +#define VOLUME_MAX 60
- +
- +
- +/* Register addresses and bits */
- +#define OUTPUT_MUTED 0x2f
- +#define OUTPUT_0DB 0x79
- +
- +#define LINV 0x00
- +#define LINV_IPVU (1 << 8) /* FIXME */
- +#define LINV_LINMUTE (1 << 7)
- +#define LINV_LIZC (1 << 6)
- +#define LINV_LINVOL(x) ((x) & 0x3f)
- +
- +#define RINV 0x01
- +#define RINV_IPVU (1 << 8) /* FIXME */
- +#define RINV_RINMUTE (1 << 7)
- +#define RINV_RIZC (1 << 6)
- +#define RINV_RINVOL(x) ((x) & 0x3f)
- +
- +#define LOUT1 0x02
- +#define LOUT1_LO1VU (1 << 8)
- +#define LOUT1_LO1ZC (1 << 7)
- +#define LOUT1_LOUT1VOL(x) ((x) & 0x7f)
- +
- +#define ROUT1 0x03
- +#define ROUT1_RO1VU (1 << 8)
- +#define ROUT1_RO1ZC (1 << 7)
- +#define ROUT1_ROUT1VOL(x) ((x) & 0x7f)
- +
- +#define CLOCKING1 0x04 /* FIXME */
- +#define CLOCKING1_ADCDIV(x) (((x) & 0x7) << 6)
- +#define CLOCKING1_DACDIV(x) (((x) & 0x7) << 3)
- +#define CLOCKING1_SYSCLKDIV_1 (0 << 1)
- +#define CLOCKING1_SYSCLKDIV_2 (2 << 1)
- +#define CLOCKING1_CLKSEL_MCLK (0 << 0)
- +#define CLOCKING1_CLKSEL_PLL (1 << 0)
- +
- +#define DACCTRL1 0x05
- +#define DACCTRL1_DATTENUATE (1 << 7)
- +#define DACCTRL1_DACMU (1 << 3)
- +#define DACCTRL1_DEEMPH_48 (3 << 1)
- +#define DACCTRL1_DEEMPH_44 (2 << 1)
- +#define DACCTRL1_DEEMPH_32 (1 << 1)
- +#define DACCTRL1_DEEMPH_NONE (0 << 1)
- +#define DACCTRL1_DEEMPH(x) ((x) & (0x3 << 1))
- +
- +#define DACCTRL2 0x06
- +
- +#define AINTFCE1 0x07
- +#define AINTFCE1_BCLKINV (1 << 7)
- +#define AINTFCE1_MS (1 << 6)
- +#define AINTFCE1_LRSWAP (1 << 5)
- +#define AINTFCE1_LRP (1 << 4)
- +#define AINTFCE1_WL_32 (3 << 2)
- +#define AINTFCE1_WL_24 (2 << 2)
- +#define AINTFCE1_WL_20 (1 << 2)
- +#define AINTFCE1_WL_16 (0 << 2)
- +#define AINTFCE1_WL(x) (((x) & 0x3) << 2)
- +#define AINTFCE1_FORMAT_DSP (3 << 0)
- +#define AINTFCE1_FORMAT_I2S (2 << 0)
- +#define AINTFCE1_FORMAT_LJUST (1 << 0)
- +#define AINTFCE1_FORMAT_RJUST (0 << 0)
- +#define AINTFCE1_FORMAT(x) ((x) & 0x3)
- +
- +/* FIXME */
- +#define CLOCKING2 0x08
- +#define CLOCKING2_DCLKDIV(x) (((x) & 0x7) << 6)
- +#define CLOCKING2_BCLKDIV(x) (((x) & 0xf) << 0)
- +
- +#define AINTFCE2 0x09
- +#define AINTFCE2_ALRCGPIO_ALRC (0 << 6)
- +#define AINTFCE2_ALRCGPIO_GPIO (1 << 6)
- +#define AINTFCE2_LOOPBACK (1 << 0)
- +
- +#define LEFTGAIN 0x0a
- +#define LEFTGAIN_LDVU (1 << 8)
- +#define LEFTGAIN_LDACVOL(x) ((x) & 0xff)
- +
- +#define RIGHTGAIN 0x0b
- +#define RIGHTGAIN_RDVU (1 << 8)
- +#define RIGHTGAIN_RDACVOL(x) ((x) & 0xff)
- +
- +#define RESET 0x0f
- +#define RESET_RESET 0x000
- +
- +#define ALC1 0x11
- +#define ALC1_ALCOFF (0x0 << 7)
- +#define ALC1_ALCRONLY (0x1 << 7)
- +#define ALC1_ALCLONLY (0x2 << 7)
- +#define ALC1_ALCSTEREO (0x3 << 7)
- +#define ALC1_ALCSEL(x) (((x) & 0x3) << 7)
- +#define ALC1_SET_MAXGAIN(x) ((x & 0x7) << 4)
- +#define ALC1_GET_MAXGAIN(x) ((x) & (0x7 << 4))
- +#define ALC1_ALCL(x) ((x) & 0x0f)
- +
- +#define ALC2 0x12
- +#define ALC2_MINGAIN(x) ((x & 0x7) << 4)
- +#define ALC2_HLD(x) ((x) & 0x0f)
- +
- +#define ALC3 0x13
- +#define ALC3_SET_DCY(x) ((x & 0x0f) << 4)
- +#define ALC3_GET_DCY(x) ((x) & (0x0f << 4))
- +#define ALC3_ATK(x) ((x) & 0x0f)
- +
- +#define NOISEGATE 0x14
- +#define NOISEGATE_SET_NGTH(x) ((x & 0x1f) << 3)
- +#define NOISEGATE_GET_NGTH(x) ((x) & (0x1f << 3))
- +#define NOISEGATE_NGAT_ENABLE 1
- +
- +#define LADCVOL 0x15
- +#define LADCVOL_LAVU_EN (1 << 8)
- +#define LADCVOL_LADCVOL(x) ((x) & 0x0ff)
- +
- +#define RADCVOL 0x16
- +#define RADCVOL_RAVU_EN (1 << 8)
- +#define RADCVOL_RADCVOL(x) ((x) & 0x0ff)
- +
- +#define ADDITIONAL1 0x17
- +#define ADDITIONAL1_TSDEN (1 << 8)
- +#define ADDITIONAL1_VSEL_LOWEST (0 << 6)
- +#define ADDITIONAL1_VSEL_LOW (1 << 6)
- +#define ADDITIONAL1_VSEL_DEFAULT2 (2 << 6)
- +#define ADDITIONAL1_VSEL_DEFAULT (3 << 6)
- +#define ADDITIONAL1_VSEL(x) (((x) & 0x3) << 6)
- +#define ADDITIONAL1_DMONOMIX_STEREO (0 << 4)
- +#define ADDITIONAL1_DMONOMIX_MONO (1 << 4)
- +#define ADDITIONAL1_DATSEL(x) (((x) & 0x3) << 2)
- +#define ADDITIONAL1_TOCLKSEL (1 << 1)
- +#define ADDITIONAL1_TOEN (1 << 0)
- +
- +#define ADDITIONAL2 0x18
- +#define ADDITIONAL2_HPSWEN (1 << 6)
- +#define ADDITIONAL2_HPSWPOL (1 << 5)
- +#define ADDITIONAL2_TRIS (1 << 3)
- +#define ADDITIONAL2_LRCM_ON (1 << 2)
- +
- +#define PWRMGMT1 0x19
- +#define PWRMGMT1_VMIDSEL_DISABLED (0 << 7)
- +#define PWRMGMT1_VMIDSEL_50K (1 << 7)
- +#define PWRMGMT1_VMIDSEL_250K (2 << 7)
- +#define PWRMGMT1_VMIDSEL_5K (3 << 7)
- +#define PWRMGMT1_VREF (1 << 6)
- +#define PWRMGMT1_AINL (1 << 5)
- +#define PWRMGMT1_AINR (1 << 4)
- +#define PWRMGMT1_ADCL (1 << 3)
- +#define PWRMGMT1_ADCR (1 << 2)
- +#define PWRMGMT1_MICB (1 << 1)
- +#define PWRMGMT1_DIGENB (1 << 0)
- +
- +#define PWRMGMT2 0x1a
- +#define PWRMGMT2_DACL (1 << 8)
- +#define PWRMGMT2_DACR (1 << 7)
- +#define PWRMGMT2_LOUT1 (1 << 6)
- +#define PWRMGMT2_ROUT1 (1 << 5)
- +#define PWRMGMT2_SPKL (1 << 4)
- +#define PWRMGMT2_SPKR (1 << 3)
- +#define PWRMGMT2_OUT3 (1 << 1)
- +#define PWRMGMT2_PLL_EN (1 << 0)
- +
- +#define ADDITIONAL3 0x1b
- +#define ADDITIONAL3_VROI (1 << 6)
- +#define ADDITIONAL3_OUT3CAP (1 << 3)
- +#define ADDITIONAL3_ADC_ALC_SR(x) ((x) & 0x7)
- +
- +#define ANTIPOP1 0x1c
- +#define ANTIPOP2 0x1d
- +
- +#define ADCLPATH 0x20
- +#define ADCLPATH_LMN1 (1 << 8)
- +#define ADCLPATH_LMP3 (1 << 7)
- +#define ADCLPATH_LMP2 (1 << 6)
- +#define ADCLPATH_LMICBOOST_29DB (0x3 << 4)
- +#define ADCLPATH_LMICBOOST_20DB (0x2 << 4)
- +#define ADCLPATH_LMICBOOST_13DB (0x1 << 4)
- +#define ADCLPATH_SET_LMICBOOST(x) ((x & 0x3) << 4)
- +#define ADCLPATH_LMIC2B (1 << 3)
- +
- +
- +#define ADCRPATH 0x21
- +#define ADCRPATH_RMN1 (1 << 8)
- +#define ADCRPATH_RMP3 (1 << 7)
- +#define ADCRPATH_RMP2 (1 << 6)
- +#define ADCRPATH_RMICBOOST_29DB (0x3 << 4)
- +#define ADCRPATH_RMICBOOST_20DB (0x2 << 4)
- +#define ADCRPATH_RMICBOOST_13DB (0x1 << 4)
- +#define ADCRPATH_SET_RMICBOOST(x) ((x & 0x3) << 4)
- +#define ADCRPATH_RMIC2B (1 << 3)
- +
- +
- +#define LEFTMIX1 0x22
- +#define LEFTMIX1_LD2LO (1 << 8)
- +#define LEFTMIX1_LI2LO (1 << 7)
- +#define LEFTMIX1_LI2LO_DEFAULT (5 << 4)
- +#define LEFTMIX1_LI2LOVOL(x) (((x) & 0x7) << 4)
- +
- +#define RIGHTMIX2 0x25
- +#define RIGHTMIX2_RD2RO (1 << 8)
- +#define RIGHTMIX2_RI2RO (1 << 7)
- +#define RIGHTMIX2_RI2RO_DEFAULT (5 << 4)
- +#define RIGHTMIX2_RI2ROVOL(x) (((x) & 0x7) << 4)
- +
- +#define MONOMIX1 0x26
- +#define MONOMIX1_L2MO (1 << 7)
- +
- +#define MONOMIX2 0x27
- +#define MONOMIX2_R2MO (1 << 7)
- +
- +#define LSPK 0x28
- +#define LSPK_SPKLVU (1 << 8)
- +#define LSPK_SPKLZC (1 << 7)
- +#define LSPK_SPKLVOL(x) ((x) & 0x7f)
- +
- +#define RSPK 0x29
- +#define RSPK_SPKRVU (1 << 8)
- +#define RSPK_SPKRZC (1 << 7)
- +#define RSPK_SPKRVOL(x) ((x) & 0x7f)
- +
- +#define OUT3V 0x2a
- +#define LINBMIX 0x2b
- +#define RINBMIX 0x2c
- +#define BYPASS1 0x2d
- +#define BYPASS2 0x2e
- +
- +#define PWRMGMT3 0x2f
- +#define PWRMGMT3_LMIC (1<<5)
- +#define PWRMGMT3_RMIC (1<<4)
- +#define PWRMGMT3_LOMIX (1<<3)
- +#define PWRMGMT3_ROMIX (1<<2)
- +
- +#define ADDITIONAL4 0x30
- +
- +#define CLASSDCTRL1 0x31
- +#define CLASSDCTRL1_OP_OFF (0<<6)
- +#define CLASSDCTRL1_OP_LSPK (1<<6)
- +#define CLASSDCTRL1_OP_RSPK (2<<6)
- +#define CLASSDCTRL1_OP_LRSPK (3<<6)
- +
- +#define CLASSDCTRL3 0x33
- +
- +#define PLL1 0x34
- +#define PLL1_OPCLKDIV_1 (0<<6)
- +#define PLL1_OPCLKDIV_2 (1<<6)
- +#define PLL1_OPCLKDIV_3 (2<<6)
- +#define PLL1_OPCLKDIV_4 (3<<6)
- +#define PLL1_OPCLKDIV_5p5 (4<<6)
- +#define PLL1_OPCLKDIV_6 (5<<6)
- +#define PLL1_SDM_INTERGER (0<<5)
- +#define PLL1_SDM_FRACTIONAL (1<<5)
- +#define PLL1_PLLPRESCALE_1 (0<<4)
- +#define PLL1_PLLPRESCALE_2 (1<<4)
- +#define PLL1_PLLN(x) ((x) & 0xf)
- +
- +#define PLL2 0x35
- +#define PLL2_PLLK_23_16(x) ((x) & 0x1ff)
- +
- +#define PLL3 0x36
- +#define PLL3_PLLK_15_8(x) ((x) & 0x1ff)
- +
- +#define PLL4 0x37
- +#define PLL4_PLLK_7_0(x) ((x) & 0x1ff)
- +
- +/* codec API */
- +void audiohw_preinit(void);
- +int audiohw_postinit(int bSlave, int AIn, int AOut, int pll_en, int wordLen24b);
- +void audiohw_close(void);
- +void audiohw_set_frequency(int fsel, int pll_en);
- +void audiohw_mute(bool mute);
- +void audiohw_micboost(int boostgain);
- +void audiohw_micin(int enableMic);
- +void audiohw_set_apll(int srate);
- +int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r);
- +int audiohw_set_linein_vol(int vol_l, int vol_r);
- +void audiohw_mute( bool mute);
- +void audiohw_loopback(int fsel);
- +void audiohw_codec_exlbk(void);
- +void audiohw_bypass(void);
- +
- +#endif /* _WM875x_H */
- --- /dev/null
- +++ b/sound/soc/mtk/i2s_ctrl.c
- @@ -0,0 +1,3524 @@
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#include <linux/sched.h>
- +#endif
- +#include <linux/module.h>
- +#include <linux/kernel.h> /* _printk() */
- +#include <linux/slab.h> /* kmalloc() */
- +#include <linux/fs.h> /* everything... */
- +#include <linux/errno.h> /* error codes */
- +#include <linux/types.h> /* size_t */
- +#include <linux/proc_fs.h>
- +#include <linux/fcntl.h> /* O_ACCMODE */
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,14)
- +#include <asm/system.h> /* cli(), *_flags */
- +#endif
- +#include <asm/uaccess.h> /* copy_from/to_user */
- +#include <linux/interrupt.h>
- +#include <linux/mm.h>
- +#include <linux/mm_types.h>
- +#include <linux/pci.h>
- +#include <linux/delay.h>
- +#include "ralink_gdma.h"
- +#if defined(CONFIG_I2S_WITH_AEC)
- +#include "../aec/aec_api.h"
- +#endif
- +
- +#ifdef CONFIG_DEVFS_FS
- +#include <linux/devfs_fs_kernel.h>
- +static devfs_handle_t devfs_handle;
- +#endif
- +
- +#include "i2s_ctrl.h"
- +
- +#if defined(CONFIG_SND_MT76XX_SOC)
- +#include <sound/soc/mtk/mt76xx_machine.h>
- +#endif
- +
- +#if defined(CONFIG_I2S_WM8750)
- +#include "../codec/i2c_wm8750.h"
- +#endif
- +#if defined(CONFIG_I2S_WM8751)
- +#include "../codec/i2c_wm8751.h"
- +#endif
- +#if defined(CONFIG_I2S_WM8960)
- +#include "i2c_wm8960.h"
- +#endif
- +
- +static int i2sdrv_major = 191;
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#else
- +static struct class *i2smodule_class;
- +#endif
- +
- +static int _printk(char *fmt, ...)
- +{
- + return 0;
- +}
- +
- +/* external functions declarations */
- +#if defined(CONFIG_I2S_WM8960)
- +extern void audiohw_set_frequency(int fsel, int codec_pll_en);
- +void audiohw_set_apll(int srate);
- +#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- +extern void audiohw_set_frequency(int fsel);
- +#endif
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- +extern int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r);
- +extern int audiohw_set_master_vol(int vol_l, int vol_r);
- +extern int audiohw_set_linein_vol(int vol_l, int vol_r);
- +#endif
- +
- +extern void audiohw_micboost(int boostgain);
- +
- +extern int GdmaI2sTx(uint32_t Src, uint32_t Dst, uint8_t TxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +extern int GdmaI2sRx(uint32_t Src, uint32_t Dst, uint8_t RxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +extern int GdmaMaskChannel(uint32_t ChNum);
- +
- +extern int GdmaUnMaskChannel(uint32_t ChNum);
- +
- +/* internal functions declarations */
- +irqreturn_t i2s_irq_isr(int irq, void *irqaction);
- +int i2s_debug_cmd(unsigned int cmd, unsigned long arg);
- +
- +/* forward declarations for _fops */
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +static long i2s_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
- +#else
- +static int i2s_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
- +#endif
- +static int i2s_mmap(struct file *file, struct vm_area_struct *vma);
- +static int i2s_open(struct inode *inode, struct file *file);
- +static int i2s_release(struct inode *inode, struct file *file);
- +int i2s_mmap_alloc(unsigned long size);
- +int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size);
- +
- +/* global varable definitions */
- +i2s_config_type i2s_config;
- +i2s_status_type i2s_status;
- +i2s_config_type* pi2s_config = &i2s_config;;
- +i2s_status_type* pi2s_status = &i2s_status;;
- +
- +static inline long
- +ugly_hack_sleep_on_timeout(wait_queue_head_t *q, long timeout)
- +{
- + unsigned long flags;
- + wait_queue_t wait;
- +
- + init_waitqueue_entry(&wait, current);
- +
- + __set_current_state(TASK_INTERRUPTIBLE);
- + spin_lock_irqsave(&q->lock, flags);
- + __add_wait_queue(q, &wait);
- + spin_unlock(&q->lock);
- +
- + timeout = schedule_timeout(timeout);
- +
- + spin_lock_irq(&q->lock);
- + __remove_wait_queue(q, &wait);
- + spin_unlock_irqrestore(&q->lock, flags);
- +
- + return timeout;
- +}
- +
- +#define interruptible_sleep_on(x) \
- + ugly_hack_sleep_on_timeout(x, MAX_SCHEDULE_TIMEOUT);
- +
- +
- +#if defined(ARM_ARCH)
- +static dma_addr_t i2s_txdma_addr0, i2s_txdma_addr1;
- +static dma_addr_t i2s_rxdma_addr0, i2s_rxdma_addr1;
- +#define I2S_TX_FIFO_WREG_PHY (I2S_TX_FIFO_WREG & 0x1FFFFFFF)
- +#define I2S_RX_FIFO_RREG_PHY (I2S_RX_FIFO_RREG & 0x1FFFFFFF)
- +#else
- +static dma_addr_t i2s_txdma_addr, i2s_rxdma_addr;
- +#endif
- +static dma_addr_t i2s_mmap_addr[MAX_I2S_PAGE*2];
- + /* 8khz 11.025khz 12khz 16khz 22.05khz 24Khz 32khz 44.1khz 48khz 88.2khz 96khz*/
- +unsigned long i2s_inclk_15p625Mhz[11] = {60<<8, 43<<8, 40<<8, 30<<8, 21<<8, 19<<8, 14<<8, 10<<8, 9<<8, 7<<8, 4<<8};
- +unsigned long i2s_exclk_12p288Mhz[11] = {47<<8, 34<<8, 31<<8, 23<<8, 16<<8, 15<<8, 11<<8, 8<<8, 7<<8, 5<<8, 3<<8};
- +unsigned long i2s_exclk_12Mhz[11] = {46<<8, 33<<8, 30<<8, 22<<8, 16<<8, 15<<8, 11<<8, 8<<8, 7<<8, 5<<8, 3<<8};
- +#if defined(CONFIG_I2S_WM8750) || defined(CONFIG_SND_SOC_WM8750)
- + /* 8k 11.025k 12k 16k 22.05k 24k 32k 44.1k 48k 88.2k 96k*/
- +unsigned long i2s_codec_12p288Mhz[11] = {0x0C, 0x00, 0x10, 0x14, 0x38, 0x38, 0x18, 0x20, 0x00, 0x00, 0x1C};
- +unsigned long i2s_codec_12Mhz[11] = {0x0C, 0x32, 0x10, 0x14, 0x37, 0x38, 0x18, 0x22, 0x00, 0x3E, 0x1C};
- +unsigned long i2s_codec_24p576Mhz[11] = {0x4C, 0x00, 0x50, 0x54, 0x00, 0x78, 0x58, 0x00, 0x40, 0x00, 0x5C};
- +unsigned long i2s_codec_18p432Mhz[11] = {0x0e, 0x32, 0x12, 0x16, 0x36, 0x3a, 0x1a, 0x22, 0x02, 0x3e, 0x1e};
- +#endif
- +#if defined(CONFIG_I2S_WM8751) || defined(CONFIG_SND_SOC_WM8751)
- +unsigned long i2s_codec_12p288Mhz[11] = {0x04, 0x00, 0x10, 0x14, 0x38, 0x38, 0x18, 0x20, 0x00, 0x00, 0x1C};
- +unsigned long i2s_codec_12Mhz[11] = {0x04, 0x32, 0x10, 0x14, 0x37, 0x38, 0x18, 0x22, 0x00, 0x3E, 0x1C};
- +#endif
- +#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_SND_SOC_WM8960)
- +unsigned long i2s_codec_12p288Mhz[11] = {0x36, 0x24, 0x24, 0x1b, 0x12, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00};
- +unsigned long i2s_codec_12Mhz[11] = {0x36, 0x24, 0x24, 0x1b, 0x12, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00};
- +#endif
- +EXPORT_SYMBOL(i2s_codec_12p288Mhz);
- +EXPORT_SYMBOL(i2s_codec_12Mhz);
- +
- +#if defined(CONFIG_RALINK_RT6855A)
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k */
- +unsigned long i2s_inclk_int[11] = { 97, 70, 65, 48, 35, 32, 24, 17, 16, 12, 8};
- +unsigned long i2s_inclk_comp[11] = { 336, 441, 53, 424, 220, 282, 212, 366, 141, 185, 70};
- +#elif defined (CONFIG_RALINK_MT7621)
- +#ifdef MT7621_ASIC_BOARD
- +#if defined (CONFIG_I2S_MCLK_12P288MHZ)
- +unsigned long i2s_inclk_int[11] = { 576, 384, 0, 288, 192, 192, 144, 96, 96, 48, 48};
- +unsigned long i2s_inclk_comp[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- +#elif defined(CONFIG_I2S_MCLK_12MHZ)
- +unsigned long i2s_inclk_int[11] = {1171, 850, 0, 585, 425, 390, 292, 212, 195, 106, 97};
- +unsigned long i2s_inclk_comp[11] = { 448, 174, 0, 480, 87, 320, 496, 299, 160, 149, 336};
- +#endif
- +#else //MT7621_FPGA_BOARD
- +unsigned long i2s_inclk_int[11] = { 529, 384, 0, 264, 192, 176, 132, 96, 88, 48, 44};
- +unsigned long i2s_inclk_comp[11] = { 102, 0, 0, 307, 0, 204, 153, 0, 102, 0, 51};
- +#endif
- +#elif defined (CONFIG_RALINK_MT7628)
- +#ifdef MT7628_ASIC_BOARD
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */
- +unsigned long i2s_inclk_int_16bit[13] = {937, 680, 0, 468, 340, 312, 234, 170, 156, 85, 78, 42, 39};
- +unsigned long i2s_inclk_comp_16bit[13]= {256, 139, 0, 384, 69, 256, 192, 34, 128, 17, 64, 267, 32};
- +unsigned long i2s_inclk_int_24bit[13] = {625, 404, 0, 312, 226, 208, 156, 113, 104, 56, 52, 28, 26};
- +unsigned long i2s_inclk_comp_24bit[13]= { 0, 404, 0, 256, 387, 170, 128, 193, 85, 352, 42, 176, 21};
- +#else
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */
- +unsigned long i2s_inclk_int_16bit[13] = {468, 340, 0, 234, 170, 156, 117, 85, 78, 42, 39, 21, 19};
- +unsigned long i2s_inclk_comp_16bit[13]= {384, 69, 0, 192, 34, 128, 96, 17, 64, 264, 32, 133, 272};
- +unsigned long i2s_inclk_int_24bit[13] = {312, 202, 0, 156, 113, 104, 78, 56, 52, 28, 26, 14, 13};
- +unsigned long i2s_inclk_comp_24bit[13]= {256, 202, 0, 128, 193, 85, 64, 352, 42, 176, 21, 88, 10};
- +#endif
- +#elif defined (CONFIG_ARCH_MT7623)
- +#if defined MT7623_ASIC_BOARD
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */
- +unsigned long i2s_inclk_int_16bit[13] = {576, 384, 0, 288, 192, 192, 144, 96, 96, 48, 48, 24, 24};
- +unsigned long i2s_inclk_comp_16bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- +unsigned long i2s_inclk_int_24bit[13] = {384, 256, 0, 192, 128, 128, 96, 64, 64, 32, 32, 16, 16};
- +unsigned long i2s_inclk_comp_24bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- +#else
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */
- +unsigned long i2s_inclk_int_16bit[13] = {72, 48, 0, 36, 24, 24, 18, 12, 12, 6, 6, 3, 3};
- +unsigned long i2s_inclk_comp_16bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- +unsigned long i2s_inclk_int_24bit[13] = {48, 32, 0, 24, 16, 16, 12, 8, 8, 4, 4, 2, 2};
- +unsigned long i2s_inclk_comp_24bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- +#endif
- +#else
- + /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k */
- +unsigned long i2s_inclk_int[11] = { 78, 56, 52, 39, 28, 26, 19, 14, 13, 9, 6};
- +unsigned long i2s_inclk_comp[11] = { 64, 352, 42, 32, 176, 21, 272, 88, 10, 455, 261};
- +#endif
- +
- +#if defined(CONFIG_I2S_WITH_AEC)
- +aecFuncTbl_t *aecFuncP;
- +#endif
- +/* USB mode 22.05Khz register value in datasheet is 0x36 but will cause slow clock, 0x37 is correct value */
- +/* USB mode 44.1Khz register value in datasheet is 0x22 but will cause slow clock, 0x23 is correct value */
- +
- +struct tasklet_struct i2s_tx_tasklet;
- +struct tasklet_struct i2s_rx_tasklet;
- +EXPORT_SYMBOL(i2s_tx_tasklet);
- +EXPORT_SYMBOL(i2s_rx_tasklet);
- +
- +char test_buf[I2S_PAGE_SIZE];
- +char test_buf_1[I2S_PAGE_SIZE];
- +char test_buf_2[I2S_PAGE_SIZE];
- +
- +static const struct file_operations i2s_fops = {
- + owner : THIS_MODULE,
- + mmap : i2s_mmap,
- + open : i2s_open,
- + release : i2s_release,
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- + unlocked_ioctl: i2s_ioctl,
- +#else
- + ioctl : i2s_ioctl,
- +#endif
- +};
- +
- +int __init i2s_mod_init(void)
- +{
- + int result;
- +
- + _printk("******* i2s module init **********\n");
- + /* register device with kernel */
- +#ifdef CONFIG_DEVFS_FS
- + if(devfs_register_chrdev(i2sdrv_major, I2SDRV_DEVNAME , &i2s_fops)) {
- + _printk(KERN_WARNING " i2s: can't create device node - %s\n", I2SDRV_DEVNAME);
- + return -EIO;
- + }
- +
- + devfs_handle = devfs_register(NULL, I2SDRV_DEVNAME, DEVFS_FL_DEFAULT, i2sdrv_major, 0,
- + S_IFCHR | S_IRUGO | S_IWUGO, &i2s_fops, NULL);
- +#else
- + result = register_chrdev(i2sdrv_major, I2SDRV_DEVNAME, &i2s_fops);
- + if (result < 0) {
- + _printk(KERN_WARNING "i2s: can't get major %d\n",i2sdrv_major);
- + return result;
- + }
- +
- + if (i2sdrv_major == 0) {
- + i2sdrv_major = result; /* dynamic */
- + }
- +#endif
- +
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#else
- + i2smodule_class=class_create(THIS_MODULE, I2SDRV_DEVNAME);
- + if (IS_ERR(i2smodule_class))
- + return -EFAULT;
- + device_create(i2smodule_class, NULL, MKDEV(i2sdrv_major, 0), I2SDRV_DEVNAME);
- +#endif
- +
- +#if defined(CONFIG_I2S_WITH_AEC)
- + _printk("AEC FuncP init \n");
- + /*Add by mtk04880*/
- + aecFuncP = kmalloc(sizeof(aecFuncTbl_t), GFP_KERNEL);
- + /*If aecFuncP cannot request memory,it will be ignored in I2S module. Since AEC & I2S are independent
- + * when AEC module is inserted,It will return err message (but I2S will keep running without AEC support)
- + * */
- + if(aecFuncP){
- + memset(aecFuncP,0,sizeof(aecFuncTbl_t));
- + }
- +#endif
- +
- + return 0;
- +}
- +
- +void i2s_mod_exit(void)
- +{
- + _printk("************ i2s module exit *************\n");
- +#ifdef CONFIG_DEVFS_FS
- + devfs_unregister_chrdev(i2sdrv_major, I2SDRV_DEVNAME);
- + devfs_unregister(devfs_handle);
- +#else
- + unregister_chrdev(i2sdrv_major, I2SDRV_DEVNAME);
- +#endif
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#else
- + device_destroy(i2smodule_class,MKDEV(i2sdrv_major, 0));
- + class_destroy(i2smodule_class);
- +#endif
- + return ;
- +}
- +
- +
- +int i2s_open(struct inode *inode, struct file *filp)
- +{
- +#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN)
- + int Ret;
- +#endif
- + int minor = iminor(inode);
- +
- + if (minor >= I2S_MAX_DEV)
- + return -ENODEV;
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
- + MOD_INC_USE_COUNT;
- +#else
- + try_module_get(THIS_MODULE);
- +#endif
- +
- + if (filp->f_flags & O_NONBLOCK) {
- + MSG("filep->f_flags O_NONBLOCK set\n");
- + return -EAGAIN;
- + }
- +
- + /* set i2s_config */
- + filp->private_data = pi2s_config;
- + memset(pi2s_config, 0, sizeof(i2s_config_type));
- +#ifdef I2S_STATISTIC
- + memset(pi2s_status, 0, sizeof(i2s_status_type));
- +#endif
- + i2s_param_init(pi2s_config);
- +
- +#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN)
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- + Ret = request_irq(SURFBOARDINT_I2S, i2s_irq_isr, IRQF_DISABLED, "Ralink_I2S", NULL);
- +#else
- + Ret = request_irq(SURFBOARDINT_I2S, i2s_irq_isr, SA_INTERRUPT, "Ralink_I2S", NULL);
- +#endif
- +
- + if(Ret){
- + MSG("IRQ %d is not free.\n", SURFBOARDINT_I2S);
- + i2s_release(inode, filp);
- + return -1;
- + }
- +#endif
- +
- + init_waitqueue_head(&(pi2s_config->i2s_tx_qh));
- + init_waitqueue_head(&(pi2s_config->i2s_rx_qh));
- + spin_lock_init(&pi2s_config->lock);
- +
- + return 0;
- +}
- +
- +
- +static int i2s_release(struct inode *inode, struct file *filp)
- +{
- + i2s_config_type* ptri2s_config;
- +
- + /* decrement usage count */
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
- + MOD_DEC_USE_COUNT;
- +#else
- + module_put(THIS_MODULE);
- +#endif
- +
- +#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN)
- + free_irq(SURFBOARDINT_I2S, NULL);
- +#endif
- +
- + ptri2s_config = filp->private_data;
- + if(ptri2s_config==NULL)
- + goto EXIT;
- +#ifdef CONFIG_I2S_MMAP
- + i2s_mem_unmap(ptri2s_config);
- +#else
- + i2s_txbuf_free(ptri2s_config);
- + i2s_rxbuf_free(ptri2s_config);
- +#endif
- + /* free buffer */
- + i2s_txPagebuf_free(ptri2s_config);
- + i2s_rxPagebuf_free(ptri2s_config);
- +EXIT:
- + MSG("i2s_release succeeds\n");
- + return 0;
- +}
- +
- +int i2s_mmap_alloc(unsigned long size)
- +{
- + int i;
- + u32 page_size;
- + int first_index;
- +
- + page_size = I2S_PAGE_SIZE;
- +
- + if ((pi2s_config->mmap_index == 0) || (pi2s_config->mmap_index == MAX_I2S_PAGE))
- + {
- + MSG("mmap_index=%d\n", pi2s_config->mmap_index);
- +
- + first_index = pi2s_config->mmap_index;
- + pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] = kmalloc(size, GFP_DMA);
- + i2s_mmap_addr[pi2s_config->mmap_index] = (dma_addr_t)dma_map_single(NULL, pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], size, DMA_BIDIRECTIONAL);
- +
- + if( pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] == NULL )
- + {
- + MSG("i2s_mmap failed\n");
- + return -1;
- + }
- + }
- + else
- + {
- + _printk("illegal index:%d\n", pi2s_config->mmap_index);
- + return -1;
- + }
- +
- + _printk("MMAP[%d]=0x%08X, i2s_mmap_addr[%d]=0x%08x\n",
- + pi2s_config->mmap_index, (u32)pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index],
- + pi2s_config->mmap_index, i2s_mmap_addr[pi2s_config->mmap_index]);
- +
- + memset(pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], 0, size);
- + pi2s_config->mmap_index++;
- +
- + for (i=1; i<MAX_I2S_PAGE; i++)
- + {
- + i2s_mmap_addr[pi2s_config->mmap_index] = i2s_mmap_addr[first_index] + i*page_size;
- + pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] = pi2s_config->pMMAPBufPtr[first_index] + i*page_size;
- +
- + _printk("MMAP[%d]=0x%08X, i2s_mmap_addr[%d]=0x%08x\n",pi2s_config->mmap_index, (u32)pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], pi2s_config->mmap_index, i2s_mmap_addr[pi2s_config->mmap_index]);
- +
- + /* Notice: The last mmap_index's value should be MAX_I2S_PAGE or MAX_I2S_PAGE*2 */
- + pi2s_config->mmap_index++;
- + }
- +
- + return 0;
- +}
- +
- +int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size)
- +{
- + int nRet;
- +
- + if((pi2s_config->pMMAPBufPtr[0]!=NULL) && (pi2s_config->mmap_index == MAX_I2S_PAGE))
- + {
- + MSG("i2s_mmap_remap:0\n");
- + nRet = remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)pi2s_config->pMMAPBufPtr[0]) >> PAGE_SHIFT, size, vma->vm_page_prot);
- +
- + if( nRet != 0 )
- + {
- + _printk("i2s_mmap->remap_pfn_range failed\n");
- + return -EIO;
- + }
- + }
- +
- + if((pi2s_config->pMMAPBufPtr[MAX_I2S_PAGE]!=NULL) && (pi2s_config->mmap_index == MAX_I2S_PAGE*2))
- + {
- + MSG("i2s_mmap_remap:%d\n", MAX_I2S_PAGE);
- +
- + nRet = remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)pi2s_config->pMMAPBufPtr[MAX_I2S_PAGE]) >> PAGE_SHIFT, size, vma->vm_page_prot);
- +
- + if( nRet != 0 )
- + {
- + _printk("i2s_mmap->remap_pfn_range failed\n");
- + return -EIO;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int i2s_mmap(struct file *filp, struct vm_area_struct *vma)
- +{
- + unsigned long size = vma->vm_end-vma->vm_start;
- + _printk("page_size=%d, ksize=%lu\n", I2S_PAGE_SIZE, size);
- +
- + if((pi2s_config->pMMAPBufPtr[0]==NULL)&&(pi2s_config->mmap_index!=0))
- + pi2s_config->mmap_index = 0;
- +
- + _printk("%s: vm_start=%08X,vm_end=%08X\n", __func__, (u32)vma->vm_start, (u32)vma->vm_end);
- +
- + /* Do memory allocate and dma sync */
- + i2s_mmap_alloc(size);
- +
- + i2s_mmap_remap(vma, size);
- +
- +
- + return 0;
- +}
- +
- +int i2s_mem_unmap(i2s_config_type* ptri2s_config)
- +{
- + u32 page_size;
- +
- + page_size = I2S_PAGE_SIZE;
- +
- + if(ptri2s_config->pMMAPBufPtr[0])
- + {
- + _printk("ummap MMAP[0]=0x%08X\n", (u32)ptri2s_config->pMMAPBufPtr[0]);
- + dma_unmap_single(NULL, i2s_mmap_addr[0], MAX_I2S_PAGE*page_size, DMA_BIDIRECTIONAL);
- + kfree(ptri2s_config->pMMAPBufPtr[0]);
- + }
- +
- + if(ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE])
- + {
- + _printk("ummap MMAP[%d]=0x%08X\n", MAX_I2S_PAGE, (u32)ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]);
- + dma_unmap_single(NULL, i2s_mmap_addr[MAX_I2S_PAGE], MAX_I2S_PAGE*page_size, DMA_BIDIRECTIONAL);
- + kfree(ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]);
- + }
- +
- + ptri2s_config->mmap_index = 0;
- +
- + return 0;
- +}
- +
- +int i2s_param_init(i2s_config_type* ptri2s_config)
- +{
- + ptri2s_config->dmach = GDMA_I2S_TX0;
- + ptri2s_config->tx_ff_thres = CONFIG_I2S_TFF_THRES;
- + ptri2s_config->tx_ch_swap = CONFIG_I2S_CH_SWAP;
- + ptri2s_config->rx_ff_thres = CONFIG_I2S_TFF_THRES;
- + ptri2s_config->rx_ch_swap = CONFIG_I2S_CH_SWAP;
- + ptri2s_config->slave_en = CONFIG_I2S_SLAVE_EN;
- + ptri2s_config->codec_pll_en = CONFIG_I2S_CODEC_PLL_EN;
- +
- + ptri2s_config->bRxDMAEnable = 0;
- + ptri2s_config->bTxDMAEnable = 0;
- + //ptri2s_config->bALSAEnable = 0;
- + ptri2s_config->srate = 44100;
- + ptri2s_config->txvol = 0;
- + ptri2s_config->rxvol = 0;
- + ptri2s_config->lbk = 0;
- + ptri2s_config->extlbk = 0;
- + ptri2s_config->txrx_coexist = 0;
- + ptri2s_config->wordlen_24b = 0;
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + ptri2s_config->sys_endian = 0;
- + ptri2s_config->fmt = 0;
- +#endif
- + ptri2s_config->micboost = 0;
- + ptri2s_config->micin = 0;
- +
- + return 0;
- +}
- +
- +int i2s_txbuf_alloc(i2s_config_type* ptri2s_config)
- +{
- + int i;
- +
- + for( i = 0 ; i < MAX_I2S_PAGE ; i ++ )
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + ptri2s_config->pMMAPTxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i];
- +#else
- + if(ptri2s_config->pMMAPTxBufPtr[i]==NULL)
- + ptri2s_config->pMMAPTxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL);
- +#endif
- + memset(ptri2s_config->pMMAPTxBufPtr[i], 0, I2S_PAGE_SIZE);
- + }
- +
- + return 0;
- +}
- +
- +int i2s_rxbuf_alloc(i2s_config_type* ptri2s_config)
- +{
- + int i;
- +
- + for( i = 0 ; i < MAX_I2S_PAGE ; i ++ )
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + ptri2s_config->pMMAPRxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i+(ptri2s_config->mmap_index-MAX_I2S_PAGE)];
- +#else
- + if(ptri2s_config->pMMAPRxBufPtr[i]==NULL)
- + ptri2s_config->pMMAPRxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL);
- +#endif
- + memset(ptri2s_config->pMMAPRxBufPtr[i], 0, I2S_PAGE_SIZE);
- + }
- +
- + return 0;
- +}
- +
- +int i2s_txPagebuf_alloc(i2s_config_type* ptri2s_config)
- +{
- +#if defined(ARM_ARCH)
- + ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE , &i2s_txdma_addr0);
- + ptri2s_config->pPage1TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE , &i2s_txdma_addr1);
- + if(ptri2s_config->pPage0TxBuf8ptr==NULL)
- + {
- + MSG("Allocate Tx Page0 Buffer Failed\n");
- + return -1;
- + }
- + if(ptri2s_config->pPage1TxBuf8ptr==NULL)
- + {
- + MSG("Allocate Tx Page1 Buffer Failed\n");
- + return -1;
- + }
- +#else
- + ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_txdma_addr);
- + if(ptri2s_config->pPage0TxBuf8ptr==NULL)
- + {
- + MSG("Allocate Tx Page Buffer Failed\n");
- + return -1;
- + }
- + ptri2s_config->pPage1TxBuf8ptr = ptri2s_config->pPage0TxBuf8ptr + I2S_PAGE_SIZE;
- +#endif
- + return 0;
- +}
- +
- +int i2s_rxPagebuf_alloc(i2s_config_type* ptri2s_config)
- +{
- +#if defined(ARM_ARCH)
- + ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE, &i2s_rxdma_addr0);
- + ptri2s_config->pPage1RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE, &i2s_rxdma_addr1);
- + if(ptri2s_config->pPage0RxBuf8ptr==NULL)
- + {
- + MSG("Allocate Rx Page Buffer Failed\n");
- + return -1;
- + }
- + if(ptri2s_config->pPage1RxBuf8ptr==NULL)
- + {
- + MSG("Allocate Rx Page Buffer Failed\n");
- + return -1;
- + }
- +#else
- + ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_rxdma_addr);
- + if(ptri2s_config->pPage0RxBuf8ptr==NULL)
- + {
- + MSG("Allocate Rx Page Buffer Failed\n");
- + return -1;
- + }
- + ptri2s_config->pPage1RxBuf8ptr = ptri2s_config->pPage0RxBuf8ptr + I2S_PAGE_SIZE;
- +#endif
- + return 0;
- +}
- +
- +int i2s_txbuf_free(i2s_config_type* ptri2s_config)
- +{
- + int i;
- +
- + for(i = 0 ; i < MAX_I2S_PAGE ; i ++)
- + {
- + if(ptri2s_config->pMMAPTxBufPtr[i] != NULL)
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + ptri2s_config->pMMAPTxBufPtr[i] = NULL;
- +#else
- + kfree(ptri2s_config->pMMAPTxBufPtr[i]);
- + ptri2s_config->pMMAPTxBufPtr[i] = NULL;
- +#endif
- + }
- + }
- + return 0;
- +}
- +
- +int i2s_rxbuf_free(i2s_config_type* ptri2s_config)
- +{
- + int i;
- +
- + for(i = 0 ; i < MAX_I2S_PAGE ; i ++)
- + {
- + if(ptri2s_config->pMMAPRxBufPtr[i] != NULL)
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + ptri2s_config->pMMAPRxBufPtr[i] = NULL;
- +#else
- + kfree(ptri2s_config->pMMAPRxBufPtr[i]);
- + ptri2s_config->pMMAPRxBufPtr[i] = NULL;
- +#endif
- + }
- + }
- +
- + return 0;
- +}
- +
- +int i2s_txPagebuf_free(i2s_config_type* ptri2s_config)
- +{
- +#if defined(ARM_ARCH)
- + if (ptri2s_config->pPage0TxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr0);
- + ptri2s_config->pPage0TxBuf8ptr = NULL;
- + }
- +
- + if (ptri2s_config->pPage1TxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage1TxBuf8ptr, i2s_txdma_addr1);
- + ptri2s_config->pPage1TxBuf8ptr = NULL;
- + }
- + _printk("Free tx page buffer\n");
- +#else
- + if (ptri2s_config->pPage0TxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr);
- + ptri2s_config->pPage0TxBuf8ptr = NULL;
- + }
- +#endif
- + return 0;
- +
- +}
- +
- +int i2s_rxPagebuf_free(i2s_config_type* ptri2s_config)
- +{
- +#if defined(ARM_ARCH)
- + if (ptri2s_config->pPage0RxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr0);
- + ptri2s_config->pPage0RxBuf8ptr = NULL;
- + }
- + if (ptri2s_config->pPage1RxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage1RxBuf8ptr, i2s_rxdma_addr1);
- + ptri2s_config->pPage1RxBuf8ptr = NULL;
- + }
- + _printk("Free rx page buffer\n");
- +#else
- + if (ptri2s_config->pPage0RxBuf8ptr)
- + {
- + pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr);
- + ptri2s_config->pPage0RxBuf8ptr = NULL;
- + }
- +#endif
- + return 0;
- +}
- +
- +int i2s_reset_tx_param(i2s_config_type* ptri2s_config)
- +{
- + ptri2s_config->tx_isr_cnt = 0;
- + ptri2s_config->tx_w_idx = 0;
- + ptri2s_config->tx_r_idx = 0;
- + ptri2s_config->enLable = 0;
- + ptri2s_config->tx_pause_en = 0;
- + ptri2s_config->end_cnt = 0;
- + ptri2s_config->tx_stop_cnt = 0;
- +
- +#ifdef I2S_STATISTIC
- + pi2s_status->txbuffer_unrun = 0;
- + pi2s_status->txbuffer_ovrun = 0;
- + pi2s_status->txdmafault = 0;
- + pi2s_status->txovrun = 0;
- + pi2s_status->txunrun = 0;
- + pi2s_status->txthres = 0;
- + pi2s_status->txbuffer_len = 0;
- +#endif
- +
- + return 0;
- +}
- +
- +int i2s_reset_rx_param(i2s_config_type* ptri2s_config)
- +{
- + ptri2s_config->rx_isr_cnt = 0;
- + ptri2s_config->rx_w_idx = 0;
- + ptri2s_config->rx_r_idx = 0;
- + ptri2s_config->enLable = 0;
- + ptri2s_config->rx_pause_en = 0;
- + ptri2s_config->rx_stop_cnt = 0;
- +
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxbuffer_unrun = 0;
- + pi2s_status->rxbuffer_ovrun = 0;
- + pi2s_status->rxdmafault = 0;
- + pi2s_status->rxovrun = 0;
- + pi2s_status->rxunrun = 0;
- + pi2s_status->rxthres = 0;
- + pi2s_status->rxbuffer_len = 0;
- +#endif
- +
- + return 0;
- +}
- +#ifdef MT7621_ASIC_BOARD
- +int i2s_pll_config_mt7621(unsigned long index)
- +{
- + unsigned long data;
- + unsigned long regValue;
- + bool xtal_20M_en = 0;
- +// bool xtal_25M_en = 0;
- + bool xtal_40M_en = 0;
- +
- + regValue = i2s_inw(RALINK_SYSCTL_BASE + 0x10);
- + regValue = (regValue >> 6) & 0x7;
- + if (regValue < 3)
- + {
- + xtal_20M_en = 1;
- + MSG("Xtal is 20MHz. \n");
- + }
- + else if (regValue < 6)
- + {
- + xtal_40M_en = 1;
- + MSG("Xtal is 40M.\n");
- + }
- + else
- + {
- + //xtal_25M_en = 1;
- + MSG("Xtal is 25M.\n");
- + }
- +
- +#if defined (CONFIG_I2S_MCLK_12P288MHZ)
- + _printk("MT7621 provide 12.288M/11.298MHz REFCLK\n");
- + /* Firstly, reset all required register to default value */
- + i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008000);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, 0x01001d61);//0x01401d61);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, 0x80100004);//0x80120004);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
- +
- + /* toggle RG_XPTL_CHG */
- + i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008800);
- + i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008c00);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~(0x0000ffc0);
- + if ((xtal_40M_en) || (xtal_20M_en))
- + {
- + data |= REGBIT(0x1d, 8); /* for 40M or 20M */
- + }
- + else
- + {
- + data |= REGBIT(0x17, 8); /* for 25M */
- + }
- +
- + if (xtal_40M_en)
- + {
- + data |= REGBIT(0x1, 6); /* for 40M */
- + }
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018);
- + data &= ~(0xf0773f00);
- + data |= REGBIT(0x3, 28);
- + data |= REGBIT(0x2, 20);
- + if ((xtal_40M_en) || (xtal_20M_en))
- + {
- + data |= REGBIT(0x3, 16); /* for 40M or 20M */
- + }
- + else
- + {
- + data |= REGBIT(0x2, 16); /* for 25M */
- + }
- + data |= REGBIT(0x3, 12);
- + if ((xtal_40M_en) || (xtal_20M_en))
- + {
- + data |= REGBIT(0xd, 8); /* for 40M or 20M */
- + }
- + else
- + {
- + data |= REGBIT(0x7, 8); /* for 25M */
- + }
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data);
- +
- + if((index==1)|(index==4)|(index==7)|(index==9))// 270 MHz for 22.05K, 44.1K, 88.2K, 176.4K
- + {
- + if ((xtal_40M_en) || (xtal_20M_en))
- + {
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1a18548a); /* for 40M or 20M */
- + }
- + else
- + {
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x14ad106e); /* for 25M */
- + }
- + }
- + else if ((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10))// 294 MHZ for 24K, 48K, 96K, 192K
- + {
- + if ((xtal_40M_en) || (xtal_20M_en))
- + {
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48); /* for 40M or 20M */
- + }
- + else
- + {
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39); /* for 25M */
- + }
- + }
- + else if (index==2)
- + {
- + _printk("Not support 12KHz sampling rate!\n");
- + return -1;
- + }
- + else
- + {
- + _printk("Wrong sampling rate!\n");
- + return -1;
- + }
- +
- + //*Common setting - Set PLLGP_CTRL_4 *//
- + /* 1. Bit 31 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~(REGBIT(0x1, 31));
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + ndelay(10);
- +
- + /* 2. Bit 0 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 0);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + udelay(200);
- +
- + /* 3. Bit 3 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 3);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + udelay(1);
- +
- + /* 4. Bit 8 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 8);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + ndelay(40);
- +
- + /* 5. Bit 6 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 6);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + ndelay(40);
- +
- + /* 6. Bit 5 & Bit 7*/
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 5);
- + data |= REGBIT(0x1, 7);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + udelay(1);
- +
- + /* 7. Bit 17 */
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data |= REGBIT(0x1, 17);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- +
- +#elif defined(CONFIG_I2S_MCLK_12MHZ)
- + _printk("MT7621 provide 12MHz REFCLK\n");
- + /* Firstly, reset all required register to default value */
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);//0x01401d61);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);//0x80100004);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
- +
- + if (xtal_40M_en)
- + {
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 17);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x3, 4);
- + data |= REGBIT(0x1, 4);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 31);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + }
- + else if (xtal_20M_en)
- + {
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 17);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x3, 6);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x3, 4);
- + data |= REGBIT(0x1, 4);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 31);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- + }
- + else
- + {
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 17);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x7f, 8);
- + data |= REGBIT(0x17, 8);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x3, 6);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018);
- + data &= ~REGBIT(0x7, 16);
- + data |= REGBIT(0x2, 16);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018);
- + data &= ~REGBIT(0xf, 8);
- + data |= REGBIT(0x7, 8);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data);
- +
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014);
- + data &= ~REGBIT(0x3, 4);
- + data |= REGBIT(0x1, 4);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data);
- +
- + data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c);
- + data &= ~REGBIT(0x1, 31);
- + i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data);
- +
- + }
- +#endif
- + return 0;
- +}
- +#if defined(CONFIG_I2S_IN_MCLK)
- +int i2s_pll_refclk_set(void)
- +{
- + unsigned long data;
- +
- + /* Set APLL register for REFCLK */
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x90);
- + data &= ~(0x0000f000);
- + data |= REGBIT(0x1, 12);
- + i2s_outw(RALINK_SYSCTL_BASE+0x0090, data);
- +
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x0090);
- + data &= ~(0x00000300);
- + i2s_outw(RALINK_SYSCTL_BASE+0x0090, data);
- + MSG("Set 0x90 register\n");
- +
- + return 0;
- +}
- +#endif
- +#endif
- +
- +#ifdef MT7623_ASIC_BOARD
- +int i2s_pll_config_mt7623(unsigned long index)
- +{
- + unsigned long data;
- +
- + /* xPLL PWR ON */
- + data = i2s_inw(AUD2PLL_PWR_CON0);
- + data |= 0x1;
- + i2s_outw(AUD2PLL_PWR_CON0, data);
- + udelay(5);
- +
- + /* xPLL ISO Disable */
- + data = i2s_inw(AUD2PLL_PWR_CON0);
- + data &= ~(0x2);
- + i2s_outw(AUD2PLL_PWR_CON0, data);
- +
- + /* xPLL Frequency Set */
- + data = i2s_inw(AUD2PLL_CON0);
- + data |= 0x1;
- + i2s_outw(AUD2PLL_CON0, data);
- +
- + /* AUD1PLL Frequency Set(change from 98.304MHz to 294.912MHz) */
- + i2s_outw(AUD1PLL_CON0, 0x121);
- + i2s_outw(AUD1PLL_CON1, 0xad5efee6);
- + udelay(40);
- +
- + /* Audio clock setting */
- + if((index==1)|(index==4)|(index==7)|(index==9)|(index==11))// for 22.05K, 44.1K, 88.2K, 176.4K
- + {
- + _printk("\n*****%s:index=%d(270MHz)*****\n", __func__, (int)index);
- + data = i2s_inw(0xFB00002c);
- + //data &= ~REGBIT(0x8, 1);
- + data &= ~(0x80);
- + i2s_outw(0xFB00002C, data); /* AUD1PLL 270.9204MHz */
- + }
- + else if ((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10)|(index==12)) //for 24K, 48K, 96K, 192K
- + {
- + _printk("\n*****%s:index=%d(294MHz)*****\n", __func__, (int)index);
- + data = i2s_inw(0xFB00002c);
- + //data |= REGBIT(0x8, 1);
- + data |= (0x80);
- + i2s_outw(0xFB00002c, data); /* AUD1PLL 294.912MHz */
- + }
- + else if (index==2)
- + {
- + _printk("Not support 12KHz sampling rate!\n");
- + return -1;
- + }
- + else
- + {
- + _printk("Wrong sampling rate!\n");
- + return -1;
- + }
- + return 0;
- +}
- +#endif
- +
- +#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623)
- +int i2s_driving_strength_adjust(void)
- +{
- +#if defined(MT7628_ASIC_BOARD)
- + unsigned long data;
- +
- + MSG("Adjust MT7628 current's driving strngth\n");
- + /* Adjust REFCLK0's driving strength of current which can avoid
- + * the glitch of REFCKL0
- + * E4 = 0xb0001354[5]; E8 = 0xb0001364[5]
- + * (E4,E8)=(0,0)-> 4 mA;
- + * =(1,0)-> 8 mA;
- + * =(0,1)-> 12 mA;
- + * =(1,1)-> 16 mA*/
- +
- + /* Set to 12mA */
- + data = i2s_inw(0xb0001354);
- + data &= ~(0x1<<5);
- + i2s_outw(0xb0001354, data);
- +
- + data = i2s_inw(0xb0001364);
- + data |= (0x1<<5);
- + i2s_outw(0xb0001364, data);
- +#endif
- +#if defined(CONFIG_ARCH_MT7623)
- + MSG("Adjust MT7623 current's driving strngth\n");
- +
- + i2s_outw(0xF0005F80, 0x7777);
- +#endif
- +
- + return 0;
- +}
- +#endif
- +
- +#if defined(CONFIG_I2S_IN_MCLK)
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +int i2s_refclk_12m_enable(void)
- +{
- + unsigned long data;
- +
- + MSG("Enable SoC MCLK 12Mhz\n");
- +
- +#if defined(CONFIG_RALINK_RT6855A)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x860);
- + data |= (0x1<<17);
- + data &= ~(0x7<<18);
- + data |= (0x1<<18);
- + i2s_outw(RALINK_SYSCTL_BASE+0x860, data);
- +#elif defined(CONFIG_RALINK_RT3350)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data |= (0x1<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_RT3883)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x03<<13);
- + data |= (0x1<<13);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x0F<<8);
- + data |= (0x3<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_MT7620)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x07<<9);
- + data |= (1<<9);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_MT7621)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x1f<<18);
- + data |= REGBIT(0x19, 18);
- + data &= ~(0x1f<<12);
- + data |= REGBIT(0x1, 12);
- + data &= ~(0x7<<9);
- + data |= REGBIT(0x5, 9);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_MT7628)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + MSG("turn on REFCLK output for MCLK1\n");
- + data &= ~(0x7<<9);
- + data |= (0x1<<9); /* output for MCLK */
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#else
- + #error "This SoC does not provide 12MHz clock to audio codec\n");
- +#endif
- + i2s_refclk_gpio_out_config();
- +
- + return 0;
- +}
- +#endif
- +
- +#if defined(CONFIG_I2S_MCLK_12P288MHZ)
- +int i2s_refclk_12p288m_enable(void)
- +{
- + unsigned long data;
- + MSG("Enable SoC MCLK 12.288Mhz\n");
- +
- +#if defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x01F<<18);
- + data |= 31<<18;
- + data &= ~(0x01F<<12);
- + data |= 1<<12;
- + data |= (0xF<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_MT7621)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x1f<<18);
- + data |= REGBIT(0xc, 18);
- + data &= ~(0x1f<<12);
- + data |= REGBIT(0x1, 12);
- + data &= ~(0x7<<9);
- + data |= REGBIT(0x5, 9);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- + _printk("MT7621 provide REFCLK 12.288MHz/11.289MHz\n");
- +#elif defined(CONFIG_ARCH_MT7623)
- + /* MT7623 does not need to set divider for REFCLK */
- + /* GPIO126 - I2S0_MCLK */
- + data = i2s_inw(0xF00058F0);
- + data &= ~(0x7<<3);
- + data |= (0x6<<3);
- + i2s_outw(0xF00058F0, data);
- + /* GPIO_DIR8: OUT */
- + data = i2s_inw(0xF0005070);
- + data |= (0x1<<14);
- + i2s_outw(0xF0005070, data);
- +#else
- + #error "This SoC does not provide 12.288Mhz clock to audio codec\n");
- +#endif
- +
- + return 0;
- +}
- +#endif
- +
- +#if defined(CONFIG_I2S_MCLK_18P432MHZ)
- +int i2s_refclk_18p432m_enable(unsigned long index)
- +{
- + unsigned long data;
- + MSG("Enable SoC MCLK 18.432MHz/16.934MHz");
- +
- + if((index==1)|(index==4)|(index==7)|(index==9))// 16.934MHz for 22.05K, 44.1K, 88.2K, 176.4K
- + {
- + data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x2c);
- + data &= ~(0x1<<7);
- + i2s_outw(ETHDMASYS_SYSCTL_BASE+0x2c, data);
- + }
- + else if((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10))// 18.432MHZ for 24K, 48K, 96K, 192K
- + {
- + data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x2c);
- + data |= (0x1<<7);
- + i2s_outw(ETHDMASYS_SYSCTL_BASE+0x2c, data);
- + }
- +
- + data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x30);
- + data |= (0x1<<17);
- + i2s_outw(ETHDMASYS_SYSCTL_BASE+0x30, data);
- +
- + return 0;
- +}
- +#endif
- +#endif
- +
- +int i2s_refclk_disable(void)
- +{
- + unsigned long data;
- +
- +#if defined(CONFIG_RALINK_RT6855A)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x860);
- + data &= ~(1<<17);
- + i2s_outw(RALINK_SYSCTL_BASE+0x860, data);
- +#elif defined(CONFIG_RALINK_RT3350)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x1<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_RT3883)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x0F<<13);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350)||defined (CONFIG_RALINK_RT6855)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x0F<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined (CONFIG_RALINK_MT7620)||defined (CONFIG_RALINK_MT7621)||defined (CONFIG_RALINK_MT7628)
- + _printk("turn off REFCLK output from internal CLK\n");
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x07<<9);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- +#elif defined (CONFIG_ARCH_MT7623) /*FIXME:2*/
- +#ifdef MT7623_ASIC_BOARD
- + _printk("turn off REFCLK output from internal CLK\n");
- + /* GPIO126 - I2S0_MCLK */
- + data = i2s_inw(0xF00058F0);
- + data &= ~(0x7<<3);
- + //data |= (0x2<<3);
- + i2s_outw(0xF00058F0, data);
- + /* GPIO126 => GPIO_DIR8: IN */
- + data = i2s_inw(0xF0005070);
- + data &= ~(0x1<<14);
- + i2s_outw(0xF0005070, data);
- +#else
- + _printk("turn off REFCLK output from internal CLK\n");
- + data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x30);
- + data &= ~(0x1<<17);
- + i2s_outw(ETHDMASYS_SYSCTL_BASE+0x30, data);
- +#endif
- +#endif
- + return 0;
- +}
- +
- +int i2s_refclk_gpio_out_config(void)
- +{
- +#ifndef CONFIG_ARCH_MT7623
- + unsigned long data; /* FIXME */
- +#endif
- +
- + /* Set REFCLK GPIO pin as REFCLK mode*/
- +#if defined(CONFIG_RALINK_MT7620)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= ~(0x03<<21); /* WDT */
- + data |= (1<<21);
- + //data &= ~(0x03<<16); /* PERST */
- + //data |= (1<<16);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +#endif
- +#if defined(CONFIG_RALINK_MT7621)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + //data &= ~(0x3<<10); /* PERST */
- + //data |= (0x2<<10);
- + data &= ~(0x3<<8); /* WDT */
- + data |= (0x2<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- + MSG("Set 0x60 register\n");
- +#endif
- +#if defined(CONFIG_RALINK_MT7628)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= ~(0x1<<18);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +#endif
- +
- + return 0;
- +}
- +
- +int i2s_refclk_gpio_in_config(void)
- +{
- +#ifndef CONFIG_ARCH_MT7623
- + unsigned long data; /* FIXME */
- +#endif
- +
- +#if defined (CONFIG_RALINK_MT7620)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= ~(0x03<<21); /* WDT */
- + data |= (1<<21);
- + //data &= ~(0x03<<16); /* PERST */
- + //data |= (1<<16);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +
- + data = i2s_inw(RALINK_PIO_BASE);
- + data &= ~(0x1<<17); /* GPIO share ping 17 for WDT */
- + i2s_outw(RALINK_PIO_BASE, data);
- +
- + //data = i2s_inw(RALINK_PIO_BASE+0x04);
- + //data &= ~(0x1<<4); /* GPIO share ping 36 for PERST */
- + //i2s_outw(RALINK_PIO_BASE+0x04, data);
- +#endif
- +#if defined (CONFIG_RALINK_MT7621)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + //data &= ~(0x3<<10); /* PERST */
- + //data |= (0x1<<10);
- + data &= ~(0x3<<8); /* WDT */
- + data |= (0x1<<8);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +
- + data = i2s_inw(RALINK_PIO_BASE);
- + //data &= ~(0x1<<19); /* GPIO share ping 19 for RERST */
- + data &= ~(0x1<<18); /* GPIO share ping 18 for WDT */
- + i2s_outw(RALINK_PIO_BASE, data);
- +#endif
- +#if defined (CONFIG_RALINK_MT7628)
- + /* To use external OSC, set REFCLK_GPIO ping as GPIO mode and set it as input direction */
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data |= (0x1<<18);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +
- + data = i2s_inw(RALINK_PIO_BASE+0x04);
- + data &= ~(0x1<<5); /* GPIO share ping 37*/
- + i2s_outw(RALINK_PIO_BASE+0x04, data);
- +#endif
- +
- + return 0;
- +}
- +
- +int i2s_slave_clock_gpio_in_mt7623(void)
- +{
- + unsigned long data;
- +
- + /* GPIO74(I2S0_BCLK)=>GPIO_DIR5: IN */
- + data = i2s_inw(0xF0005040);
- + data &= ~(0x1<<10);
- + i2s_outw(0xF0005040, data);
- +
- + /* GPIO73(I2S0_LRCK)=>GPIO_DIR5: IN */
- + data = i2s_inw(0xF0005040);
- + data &= ~(0x1<<9);
- + i2s_outw(0xF0005040, data);
- +
- + _printk("i2s_slave_clock_gpio_in_mt7623\n");
- +
- + return 0;
- +}
- +
- +int i2s_master_clock_gpio_out_mt7623(void)
- +{
- + unsigned long data;
- +
- + /* GPIO74(I2S0_BCLK)=>GPIO_DIR5: OUT */
- + data = i2s_inw(0xF0005040);
- + data |= (0x1<<10);
- + i2s_outw(0xF0005040, data);
- +
- + /* GPIO73(I2S0_LRCK)=>GPIO_DIR5: OUT */
- + data = i2s_inw(0xF0005040);
- + data |= (0x1<<9);
- + i2s_outw(0xF0005040, data);
- +
- + _printk("i2s_master_clock_gpio_out_mt7623\n");
- +
- + return 0;
- +}
- +
- +int i2s_share_pin_mt7623(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- + _printk("\nConfig MT7623 I2S pinmux\n");
- + /* GPIO74 - I2S0_BCLK */
- + data = i2s_inw(0xF0005840);
- + data &= ~(0x7<<12);
- + data |= (0x6<<12);
- + i2s_outw(0xF0005840, data);
- +
- + /* GPIO73 - I2S0_LRCK */
- + data = i2s_inw(0xF0005840);
- + data &= ~(0x7<<9);
- + data |= (0x6<<9);
- + i2s_outw(0xF0005840, data);
- +
- + if(ptri2s_config->slave_en==0)
- + i2s_master_clock_gpio_out_mt7623();
- + else
- + i2s_slave_clock_gpio_in_mt7623();
- +
- + /* GPIO49 - I2S0_DATA */
- + data = i2s_inw(0xF00057F0);
- + data &= ~(0x7<<12);
- + data |= (0x6<<12);
- + i2s_outw(0xF00057F0, data);
- + /* GPIO_DIR4: OUT */
- + data = i2s_inw(0xF0005030);
- + data |= (0x1<<1);
- + i2s_outw(0xF0005030, data);
- +
- + /* GPIO72 - I2S0_DATA_IN */
- + data = i2s_inw(0xF0005840);
- + data &= ~(0x7<<6);
- + data |= (0x6<<6);
- + i2s_outw(0xF0005840, data);
- + /* GPIO_DIR5: IN */
- + data = i2s_inw(0xF0005040);
- + data &= ~(0x1<<8);
- + i2s_outw(0xF0005040, data);
- +
- + return 0;
- +}
- +
- +int i2s_share_pin_config(i2s_config_type* ptri2s_config)
- +{
- +#ifndef CONFIG_ARCH_MT7623
- + unsigned long data; /*FIXME*/
- +#endif
- +
- + /* set share pins to i2s/gpio mode and i2c mode */
- +#if defined(CONFIG_RALINK_RT6855A)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x860);
- + data |= 0x00008080;
- + i2s_outw(RALINK_SYSCTL_BASE+0x860, data);
- +#elif defined(CONFIG_RALINK_MT7621)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= 0xFFFFFFE3;
- + data |= 0x00000010;
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +#elif defined(CONFIG_RALINK_MT7628)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= ~(0x3<<6); /* I2S_MODE */
- + data &= ~(0x3<<20); /* I2C_MODE */
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +#elif defined(CONFIG_ARCH_MT7623)
- + i2s_share_pin_mt7623(ptri2s_config);
- +#else
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + data &= 0xFFFFFFE2;
- + data |= 0x00000018;
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +#endif
- + return 0;
- +}
- +
- +int i2s_ws_config(i2s_config_type* ptri2s_config, unsigned long index)
- +{
- + unsigned long data;
- + unsigned long* pTable;
- +
- +#if defined(CONFIG_I2S_IN_CLK)
- + /* REFCLK is 15.625Mhz or 40Mhz(fractional division) */
- +#if defined(CONFIG_I2S_FRAC_DIV)
- + MSG("Internal REFCLK with fractional division\n");
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + if (ptri2s_config->wordlen_24b == 1)
- + {
- + MSG("24 bit int table\n");
- + pTable = i2s_inclk_int_24bit;
- + }
- + else
- + {
- + MSG("16 bit int table\n");
- + pTable = i2s_inclk_int_16bit;
- + }
- +#else
- + pTable = i2s_inclk_int;
- +#endif /* CONFIG_RALINK_MT7628 */
- +
- + data = (unsigned long)(pTable[index]);
- + i2s_outw(I2S_DIVINT_CFG, data);
- +
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + if (ptri2s_config->wordlen_24b == 1)
- + {
- + MSG("24 bit comp table\n");
- + pTable = i2s_inclk_comp_24bit;
- + }
- + else
- + {
- + MSG("16 bit comp table\n");
- + pTable = i2s_inclk_comp_16bit;
- + }
- +#else
- + pTable = i2s_inclk_comp;
- +#endif /* CONFIG_RALINK_MT7628 */
- +
- + data = (unsigned long)(pTable[index]);
- + data |= REGBIT(1, I2S_CLKDIV_EN);
- + i2s_outw(I2S_DIVCOMP_CFG, data);
- +#else
- + MSG("Internal REFCLK 15.625Mhz \n");
- + pTable = i2s_inclk_15p625Mhz;
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x30);
- + data &= 0xFFFF00FF;
- + data |= (unsigned long)(pTable[index]);
- + data |= 0x00008000;
- + i2s_outw(RALINK_SYSCTL_BASE+0x30, data);
- +#endif /* CONFIG_I2S_FRAC_DIV */
- +#else
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- + /* REFCLK = MCLK = 12Mhz */
- + MSG("External REFCLK 12Mhz \n");
- + pTable = i2s_exclk_12Mhz;
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x30);
- + data &= 0xFFFF00FF;
- + data |= (unsigned long)(pTable[index]);
- + data |= 0x0000C000;
- + i2s_outw(RALINK_SYSCTL_BASE+0x30, data);
- +#else
- + /* REFCLK = MCLK = 12.288Mhz */
- + pTable = i2s_exclk_12p288Mhz;
- + MSG("External REFCLK 12.288Mhz \n");
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x30);
- + data &= 0xFFFF00FF;
- + data |= (unsigned long)(pTable[index]);
- + data |= 0x0000C000;
- + i2s_outw(RALINK_SYSCTL_BASE+0x30, data);
- +#endif /* CONFIG_I2S_MCLK_12MHZ */
- +#endif /* Not CONFIG_I2S_IN_CLK */
- +
- +#if defined(CONFIG_I2S_WS_EDGE)
- + data = i2s_inw(I2S_I2SCFG);
- + data |= REGBIT(0x1, I2S_WS_INV);
- + i2s_outw(I2S_I2SCFG, data);
- +#endif
- +
- + return 0;
- +}
- +
- +int i2s_mode_config(u32 slave_en)
- +{
- + unsigned long data;
- +
- + if(slave_en==0)
- + {
- + /* Master mode*/
- + _printk("This SoC is in Master mode\n");
- +#if defined(CONFIG_RALINK_RT3052)
- + data = i2s_inw(I2S_I2SCFG);
- + data &= ~REGBIT(0x1, I2S_SLAVE_EN);
- + data &= ~REGBIT(0x1, I2S_CLK_OUT_DIS);
- + i2s_outw(I2S_I2SCFG, data);
- +#elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||\
- + defined(CONFIG_RALINK_RT5350)||defined(CONFIG_RALINK_RT6855)||\
- + defined(CONFIG_RALINK_MT7620)||defined(CONFIG_RALINK_RT6855A)||\
- + defined(CONFIG_RALINK_MT7621)||defined(CONFIG_RALINK_MT7628)||\
- + defined(CONFIG_ARCH_MT7623)
- + data = i2s_inw(I2S_I2SCFG);
- + data &= ~REGBIT(0x1, I2S_SLAVE_MODE);
- + i2s_outw(I2S_I2SCFG, data);
- +#else
- + #error "a strange clock mode"
- +#endif
- + }
- + else
- + {
- + /* Slave mode */
- + _printk("This SoC is in Slave mode\n");
- +#if defined(CONFIG_RALINK_RT3052)
- + data = i2s_inw(I2S_I2SCFG);
- + data |= REGBIT(0x1, I2S_SLAVE_EN);
- + data |= REGBIT(0x1, I2S_CLK_OUT_DIS);
- + i2s_outw(I2S_I2SCFG, data);
- +#elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||\
- + defined(CONFIG_RALINK_RT5350)||defined(CONFIG_RALINK_RT6855)||\
- + defined(CONFIG_RALINK_MT7620)||defined(CONFIG_RALINK_RT6855A)||\
- + defined(CONFIG_RALINK_MT7621)||defined(CONFIG_RALINK_MT7628)||\
- + defined(CONFIG_ARCH_MT7623)
- + data = i2s_inw(I2S_I2SCFG);
- + data |= REGBIT(0x1, I2S_SLAVE_MODE);
- + i2s_outw(I2S_I2SCFG, data);
- +#else
- + #error "a strange clock mode "
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +int i2s_codec_frequency_config(i2s_config_type* ptri2s_config, unsigned long index)
- +{
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + unsigned long data;
- + unsigned long* pTable;
- +#endif
- +
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + pTable = i2s_codec_12Mhz;
- + data = pTable[index];
- +#endif
- +#if defined(CONFIG_I2S_WM8960)
- + audiohw_set_frequency(data, ptri2s_config->codec_pll_en);
- +#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + audiohw_set_frequency(data|0x01);
- +#endif
- +#else
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- +#if defined(MT7623_FPGA_BOARD) && defined(CONFIG_I2S_WM8750)
- + pTable = i2s_codec_18p432Mhz;
- +#else
- + pTable = i2s_codec_12p288Mhz;
- +#endif
- + data = pTable[index];
- +#endif
- +#if defined(CONFIG_I2S_WM8960)
- + audiohw_set_frequency(data, ptri2s_config->codec_pll_en);
- +#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + audiohw_set_frequency(data);
- +#endif
- +#endif
- + return 0;
- +}
- +
- +/*
- + * Ralink Audio System Clock Enable
- + *
- + * I2S_WS : signal direction opposite to/same as I2S_CLK
- + *
- + * I2S_CLK : Integer division or fractional division
- + * REFCLK from Internal or External (external REFCLK not support for fractional division)
- + * Suppose external REFCLK always be the same as external MCLK
- + *
- + * MCLK : External OSC or internal generation
- + *
- + */
- +int i2s_clock_enable(i2s_config_type* ptri2s_config)
- +{
- + unsigned long index;
- + /* audio sampling rate decision */
- + switch(ptri2s_config->srate)
- + {
- + case 8000:
- + index = 0;
- + break;
- + case 11025:
- + index = 1;
- + break;
- + case 12000:
- + index = 2;
- + break;
- + case 16000:
- + index = 3;
- + break;
- + case 22050:
- + index = 4;
- + break;
- + case 24000:
- + index = 5;
- + break;
- + case 32000:
- + index = 6;
- + break;
- + case 44100:
- + index = 7;
- + break;
- + case 48000:
- + index = 8;
- + break;
- + case 88200:
- + index = 9;
- + break;
- + case 96000:
- + index = 10;
- + break;
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + case 176000:
- + index = 11;
- + break;
- + case 192000:
- + index = 12;
- + break;
- +#endif
- + default:
- + index = 7;
- + }
- +#ifdef MT7621_ASIC_BOARD
- + /* Set pll config */
- + i2s_pll_config_mt7621(index);
- +#endif
- +#ifdef MT7623_ASIC_BOARD
- + /* Set pll config */
- + i2s_pll_config_mt7623(index);
- +#endif
- +
- + /* enable internal MCLK */
- +#if defined(CONFIG_I2S_IN_MCLK)
- +#if defined(CONFIG_RALINK_MT7621)
- + i2s_pll_refclk_set();
- +#endif
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623)
- + i2s_driving_strength_adjust();
- +#endif
- + i2s_refclk_12m_enable();
- +#endif /* MCLK_12MHZ */
- +#if defined(CONFIG_I2S_MCLK_12P288MHZ)
- + i2s_refclk_12p288m_enable();
- +#endif /* MCLK_12P288MHZ */
- +#if defined(CONFIG_I2S_MCLK_18P432MHZ)
- + i2s_refclk_18p432m_enable(index);
- +#endif
- + i2s_refclk_gpio_out_config();
- +
- +#else
- + MSG("Disable SoC MCLK, use external OSC\n");
- + i2s_refclk_disable();
- + i2s_refclk_gpio_in_config();
- +#endif /* CONFIG_I2S_IN_MCLK */
- +
- + i2s_share_pin_config(ptri2s_config);
- +
- + if(ptri2s_config->slave_en==0)
- + {
- + /* Setup I2S_WS and I2S_CLK */
- + i2s_ws_config(ptri2s_config, index);
- + }
- +
- + i2s_mode_config(ptri2s_config->slave_en);
- +
- + if(!ptri2s_config->bALSAEnable)
- + {
- +#if defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)|| defined(CONFIG_I2S_WM8960)
- + i2s_codec_enable(ptri2s_config);
- +#endif
- + i2s_codec_frequency_config(ptri2s_config,index);
- + }
- +
- + return 0;
- +}
- +
- +int i2s_clock_disable(i2s_config_type* ptri2s_config)
- +{
- + if(!ptri2s_config->bALSAEnable)
- + {
- +#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + i2s_codec_disable(ptri2s_config);
- +#endif
- + }
- +
- + /* disable internal MCLK */
- +#if defined(CONFIG_I2S_IN_MCLK)
- + i2s_refclk_disable();
- + i2s_refclk_gpio_in_config();
- +#endif
- + return 0;
- +}
- +
- +
- +int i2s_codec_enable(i2s_config_type* ptri2s_config)
- +{
- +
- + int AIn = 0, AOut = 0;
- +#if 1
- +#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + /* Codec initialization */
- + audiohw_preinit();
- +#endif
- +#endif
- +
- +#if defined(CONFIG_I2S_WM8960)
- + if(ptri2s_config->codec_pll_en)
- + {
- + MSG("Codec PLL EN = %d\n", pi2s_config->codec_pll_en);
- + audiohw_set_apll(ptri2s_config->srate);
- + }
- +#endif
- +
- +#if defined(CONFIG_I2S_TXRX)
- + if((ptri2s_config->bTxDMAEnable) || (ptri2s_config->txrx_coexist))
- + AOut = 1;
- + if((ptri2s_config->bRxDMAEnable) || (ptri2s_config->txrx_coexist))
- + AIn = 1;
- +#if defined(CONFIG_I2S_WM8960)
- + audiohw_postinit(!(ptri2s_config->slave_en), AIn, AOut, ptri2s_config->codec_pll_en, ptri2s_config->wordlen_24b);
- + audiohw_micboost(ptri2s_config->micboost);
- + audiohw_micin(ptri2s_config->micin);
- +#elif defined(CONFIG_I2S_WM8750)
- + audiohw_postinit(!(ptri2s_config->slave_en), AIn, AOut, ptri2s_config->wordlen_24b);
- +#endif
- + MSG("AOut=%d, AIn=%d\n", AOut, AIn);
- +#else
- +#if defined(CONFIG_I2S_WM8750)
- + audiohw_postinit(!(ptri2s_config->slave_en), 0, 1);
- +#elif defined(CONFIG_I2S_WM8960)
- + audiohw_postinit(!(ptri2s_config->slave_en), 1, 1, ptri2s_config->codec_pll_en);
- +#elif defined(CONFIG_I2S_WM8751)
- + if(ptri2s_config->slave_en==0)
- + audiohw_postinit(1,1);
- + else
- + audiohw_postinit(0,1);
- +#endif
- +#endif
- + return 0;
- +}
- +
- +int i2s_codec_disable(i2s_config_type* ptri2s_config)
- +{
- +#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_close();
- +#endif
- + return 0;
- +}
- +
- +int i2s_reset_config(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- + /* RESET bit: write 1 clear */
- +#if defined(CONFIG_RALINK_RT6855A)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x834);
- + data |= (1<<17);
- + i2s_outw(RALINK_SYSCTL_BASE+0x834, data);
- +
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x834);
- + data &= ~(1<<17);
- + i2s_outw(RALINK_SYSCTL_BASE+0x834, data);
- +#elif defined(CONFIG_ARCH_MT7623)
- + data = i2s_inw(0xFB000000+0x34);
- + data |= (1<<17);
- + i2s_outw(0xFB000000+0x34, data);
- +
- + data = i2s_inw(0xFB000000+0x34);
- + data &= ~(1<<17);
- + i2s_outw(0xFB000000+0x34, data);
- +#else
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x34);
- + data |= (1<<17);
- + i2s_outw(RALINK_SYSCTL_BASE+0x34, data);
- +
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x34);
- + data &= ~(1<<17);
- + i2s_outw(RALINK_SYSCTL_BASE+0x34, data);
- +
- +#if 0 /* Reset GDMA */
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x34);
- + data |= (1<<14);
- + i2s_outw(RALINK_SYSCTL_BASE+0x34, data);
- +
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x34);
- + data &= ~(1<<14);
- + i2s_outw(RALINK_SYSCTL_BASE+0x34, data);
- +#endif
- +#endif
- + _printk("I2S reset complete!!\n");
- + return 0;
- +}
- +
- +int i2s_tx_config(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- + /* set I2S_I2SCFG */
- + data = i2s_inw(I2S_I2SCFG);
- + data &= 0xFFFFFF81;
- + data |= REGBIT(ptri2s_config->tx_ff_thres, I2S_TX_FF_THRES);
- + data |= REGBIT(ptri2s_config->tx_ch_swap, I2S_TX_CH_SWAP);
- +#if defined(CONFIG_RALINK_RT6855A)
- + data |= REGBIT(1, I2S_BYTE_SWAP);
- +#endif
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + MSG("TX:wordLen=%d, sysEndian=%d\n", ptri2s_config->wordlen_24b, ptri2s_config->sys_endian);
- + data |= REGBIT(ptri2s_config->wordlen_24b, I2S_DATA_24BIT);
- + data |= REGBIT(ptri2s_config->sys_endian, I2S_SYS_ENDIAN);
- + data |= REGBIT(ptri2s_config->little_edn, I2S_LITTLE_ENDIAN);
- +#endif
- + data &= ~REGBIT(1, I2S_TX_CH0_OFF);
- + data &= ~REGBIT(1, I2S_TX_CH1_OFF);
- + i2s_outw(I2S_I2SCFG, data);
- +
- + /* set I2S_I2SCFG1 */
- + MSG("internal loopback: %d\n", ptri2s_config->lbk);
- + data = i2s_inw(I2S_I2SCFG1);
- + data |= REGBIT(ptri2s_config->lbk, I2S_LBK_EN);
- + data |= REGBIT(ptri2s_config->extlbk, I2S_EXT_LBK_EN);
- + data &= 0xFFFFFFFC;
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + data |= REGBIT(ptri2s_config->fmt, I2S_DATA_FMT);
- +#endif
- + i2s_outw(I2S_I2SCFG1, data);
- +
- + return 0;
- +}
- +
- +int i2s_rx_config(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- + /* set I2S_I2SCFG */
- + data = i2s_inw(I2S_I2SCFG);
- + data &= 0xFFFF81FF;
- + data |= REGBIT(ptri2s_config->rx_ff_thres, I2S_RX_FF_THRES);
- + data |= REGBIT(ptri2s_config->rx_ch_swap, I2S_RX_CH_SWAP);
- + data &= ~REGBIT(1, I2S_RX_CH0_OFF);
- + data &= ~REGBIT(1, I2S_RX_CH1_OFF);
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + MSG("RX:wordLen=%d, sysEndian=%d\n", ptri2s_config->wordlen_24b, ptri2s_config->sys_endian);
- + data |= REGBIT(ptri2s_config->wordlen_24b, I2S_DATA_24BIT);
- + data |= REGBIT(ptri2s_config->sys_endian, I2S_SYS_ENDIAN);
- + data |= REGBIT(ptri2s_config->little_edn, I2S_LITTLE_ENDIAN);
- +#endif
- + i2s_outw(I2S_I2SCFG, data);
- +
- + /* set I2S_I2SCFG1 */
- + data = i2s_inw(I2S_I2SCFG1);
- + data |= REGBIT(ptri2s_config->lbk, I2S_LBK_EN);
- + data |= REGBIT(ptri2s_config->extlbk, I2S_EXT_LBK_EN);
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + data &= 0xFFFFFFFC;
- + data |= REGBIT(ptri2s_config->fmt, I2S_DATA_FMT);
- +#endif
- + i2s_outw(I2S_I2SCFG1, data);
- +
- + return 0;
- +}
- +
- +/* Turn On Tx DMA and INT */
- +int i2s_tx_enable(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- +#if defined(I2S_HW_INTERRUPT_EN)
- + data = i2s_inw(I2S_INT_EN);
- + data |= REGBIT(0x1, I2S_TX_INT3_EN); /* FIFO DMA fault */
- + data |= REGBIT(0x1, I2S_TX_INT2_EN); /* FIFO overrun */
- + data |= REGBIT(0x1, I2S_TX_INT1_EN); /* FIFO underrun */
- + data |= REGBIT(0x1, I2S_TX_INT0_EN); /* FIFO below threshold */
- + i2s_outw(I2S_INT_EN, data);
- +#endif
- +
- + data = i2s_inw(I2S_I2SCFG);
- +#if defined(CONFIG_I2S_TXRX)
- + data |= REGBIT(0x1, I2S_TX_EN);
- +#endif
- + data |= REGBIT(0x1, I2S_DMA_EN);
- + i2s_outw(I2S_I2SCFG, data);
- +
- + data = i2s_inw(I2S_I2SCFG);
- + data |= REGBIT(0x1, I2S_EN);
- + i2s_outw(I2S_I2SCFG, data);
- +
- + MSG("i2s_tx_enable done\n");
- + return I2S_OK;
- +}
- +
- +/* Turn On Rx DMA and INT */
- +int i2s_rx_enable(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- +#if defined(I2S_HW_INTERRUPT_EN)
- + data = i2s_inw(I2S_INT_EN);
- + data |= REGBIT(0x1, I2S_RX_INT3_EN); /* FIFO DMA fault */
- + data |= REGBIT(0x1, I2S_RX_INT2_EN); /* FIFO overrun */
- + data |= REGBIT(0x1, I2S_RX_INT1_EN); /* FIFO underrun */
- + data |= REGBIT(0x1, I2S_RX_INT0_EN); /* FIFO below threshold */
- + i2s_outw(I2S_INT_EN, data);
- +#endif
- +
- + data = i2s_inw(I2S_I2SCFG);
- +#if defined(CONFIG_I2S_TXRX)
- + data |= REGBIT(0x1, I2S_RX_EN);
- +#endif
- + data |= REGBIT(0x1, I2S_DMA_EN);
- + i2s_outw(I2S_I2SCFG, data);
- +
- + data = i2s_inw(I2S_I2SCFG);
- + data |= REGBIT(0x1, I2S_EN);
- + i2s_outw(I2S_I2SCFG, data);
- +
- + MSG("i2s_rx_enable done\n");
- + return I2S_OK;
- +}
- +/* Turn Off Tx DMA and INT */
- +int i2s_tx_disable(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- +#if defined(I2S_HW_INTERRUPT_EN)
- + data = i2s_inw(I2S_INT_EN);
- + data &= ~REGBIT(0x1, I2S_TX_INT3_EN);
- + data &= ~REGBIT(0x1, I2S_TX_INT2_EN);
- + data &= ~REGBIT(0x1, I2S_TX_INT1_EN);
- + data &= ~REGBIT(0x1, I2S_TX_INT0_EN);
- + i2s_outw(I2S_INT_EN, data);
- +#endif
- +
- + data = i2s_inw(I2S_I2SCFG);
- +#if defined(CONFIG_I2S_TXRX)
- + data &= ~REGBIT(0x1, I2S_TX_EN);
- +#endif
- + if(ptri2s_config->bRxDMAEnable==0)
- + {
- + ptri2s_config->bTxDMAEnable = 0;
- + data &= ~REGBIT(0x1, I2S_DMA_EN);
- + data &= ~REGBIT(0x1, I2S_EN);
- + }
- + i2s_outw(I2S_I2SCFG, data);
- + return I2S_OK;
- +}
- +/* Turn Off Rx DMA and INT */
- +int i2s_rx_disable(i2s_config_type* ptri2s_config)
- +{
- + unsigned long data;
- +
- +#if defined(I2S_HW_INTERRUPT_EN)
- + data = i2s_inw(I2S_INT_EN);
- + data &= ~REGBIT(0x1, I2S_RX_INT3_EN);
- + data &= ~REGBIT(0x1, I2S_RX_INT2_EN);
- + data &= ~REGBIT(0x1, I2S_RX_INT1_EN);
- + data &= ~REGBIT(0x1, I2S_RX_INT0_EN);
- + i2s_outw(I2S_INT_EN, data);
- +#endif
- +
- + data = i2s_inw(I2S_I2SCFG);
- +#if defined(CONFIG_I2S_TXRX)
- + data &= ~REGBIT(0x1, I2S_RX_EN);
- +#endif
- + if(ptri2s_config->bTxDMAEnable==0)
- + {
- + ptri2s_config->bRxDMAEnable = 0;
- + data &= ~REGBIT(0x1, I2S_DMA_EN);
- + data &= ~REGBIT(0x1, I2S_EN);
- + }
- + i2s_outw(I2S_I2SCFG, data);
- + return I2S_OK;
- +}
- +
- +int i2s_dma_tx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + int tx_r_idx;
- +
- + if ((pi2s_config->bALSAEnable==1) && (pi2s_config->bALSAMMAPEnable==1))
- + tx_r_idx = (pi2s_config->tx_r_idx + ALSA_MMAP_IDX_SHIFT)%MAX_I2S_PAGE;
- + else
- + tx_r_idx = pi2s_config->tx_r_idx;
- +
- + if(dma_ch==GDMA_I2S_TX0)
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + dma_sync_single_for_device(NULL, i2s_mmap_addr[tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_mmap_addr[tx_r_idx], I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[tx_r_idx]), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- +#else
- + memcpy(pi2s_config->pPage0TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[tx_r_idx], I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)(pi2s_config->pPage0TxBuf8ptr), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- +#endif
- + pi2s_config->dmach = GDMA_I2S_TX0;
- + pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE;
- + }
- + else
- + {
- +#if defined(CONFIG_I2S_MMAP)
- + dma_sync_single_for_device(NULL, i2s_mmap_addr[tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_mmap_addr[tx_r_idx], I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[tx_r_idx]), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- +#else
- + memcpy(pi2s_config->pPage1TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[tx_r_idx], I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)(pi2s_config->pPage1TxBuf8ptr), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- +#endif
- + pi2s_config->dmach = GDMA_I2S_TX1;
- + pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE;
- + }
- +#if defined(CONFIG_I2S_WITH_AEC)
- + if(aecFuncP->AECFeEnq){
- + aecFuncP->AECFeEnq(0,pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx],I2S_PAGE_SIZE);
- + }
- +#endif
- + return 0;
- +}
- +
- +int i2s_dma_tx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + if(dma_ch==GDMA_I2S_TX0)
- + {
- + memset(pi2s_config->pPage0TxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- + }
- + else
- + {
- + memset(pi2s_config->pPage1TxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- + }
- + return 0;
- +}
- +
- +int i2s_dma_rx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + int rx_w_idx;
- +
- + pi2s_config->rx_w_idx = (pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE;
- +
- + if ((pi2s_config->bALSAEnable==1) && (pi2s_config->bALSAMMAPEnable==1))
- + rx_w_idx = (pi2s_config->rx_w_idx+ALSA_MMAP_IDX_SHIFT)%MAX_I2S_PAGE;
- + else
- + rx_w_idx = (pi2s_config->rx_w_idx)%MAX_I2S_PAGE;
- +
- + if(dma_ch==GDMA_I2S_RX0)
- + {
- +
- +#ifdef CONFIG_I2S_MMAP
- + dma_sync_single_for_device(NULL, i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], I2S_PAGE_SIZE, DMA_FROM_DEVICE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, (u32)i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pMMAPRxBufPtr[rx_w_idx]), 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- +#else
- + memcpy(pi2s_config->pMMAPRxBufPtr[rx_w_idx], pi2s_config->pPage0RxBuf8ptr, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage0RxBuf8ptr), 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- +#endif
- + pi2s_config->dmach = GDMA_I2S_RX0;
- + }
- + else
- + {
- +
- +#ifdef CONFIG_I2S_MMAP
- + dma_sync_single_for_device(NULL, i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], I2S_PAGE_SIZE, DMA_FROM_DEVICE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, (u32)i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pMMAPRxBufPtr[rx_w_idx]), 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- +#else
- + memcpy(pi2s_config->pMMAPRxBufPtr[rx_w_idx], pi2s_config->pPage1RxBuf8ptr, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage1RxBuf8ptr), 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- +#endif
- + pi2s_config->dmach = GDMA_I2S_RX1;
- +
- + }
- +#if defined(CONFIG_I2S_WITH_AEC)
- + if(aecFuncP->AECNeEnq){
- + aecFuncP->AECNeEnq(0,pi2s_config->pMMAPRxBufPtr[rx_w_idx],I2S_PAGE_SIZE);
- + }
- +#endif
- + return 0;
- +}
- +
- +int i2s_dma_rx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + if(dma_ch==GDMA_I2S_RX0)
- + {
- + memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- + }
- + else
- + {
- + memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- + }
- + return 0;
- +}
- +
- +void i2s_dma_tx_handler(u32 dma_ch)
- +{
- + pi2s_config->enLable = 1; /* TX:enLabel=1; RX:enLabel=2 */
- +
- + if(pi2s_config->bTxDMAEnable==0)
- + {
- + if(pi2s_config->end_cnt != 0)
- + {
- + i2s_dma_tx_transf_data(pi2s_config, dma_ch);
- + pi2s_config->end_cnt --;
- + MSG("end_cnt = %d, r_idx = %d\n", pi2s_config->end_cnt, pi2s_config->tx_r_idx);
- + }
- + else
- + {
- + pi2s_config->tx_stop_cnt++;
- + i2s_dma_tx_soft_stop(pi2s_config, dma_ch);
- + MSG("tx_stop=%d, ch=%d\n", pi2s_config->tx_stop_cnt, dma_ch);
- + if (pi2s_config->tx_stop_cnt == 3)
- + {
- + wake_up_interruptible(&(pi2s_config->i2s_tx_qh));
- + _printk("T:wake up!!\n");
- + }
- + }
- + return;
- + }
- +
- + pi2s_config->tx_isr_cnt++;
- +
- +#ifdef I2S_STATISTIC
- + i2s_int_status(dma_ch);
- +#endif
- + /* FIXME */
- + if(pi2s_config->bALSAEnable)
- + {
- + if(pi2s_config->dmaStat[STREAM_PLAYBACK])
- + {
- + if(!pi2s_config->bTrigger[STREAM_PLAYBACK]){
- + //_printk("trigger stop: rIdx:%d widx:%d\n", pi2s_config->tx_r_idx,pi2s_config->tx_w_idx);
- + i2s_dma_tx_transf_zero(pi2s_config, dma_ch);
- + if(pi2s_config->bPreTrigger[STREAM_PLAYBACK]){
- + /* mtk04880 commented:
- + * for corner case, there are cases which ALSA Trigger stop before disabling DMA.
- + * For which case, it needs to keep call snd_pcm_elapased to keep ALSA hw ptr updating.
- + * It is so called post stop handlment.
- + */
- + //_printk("post-stop\n");
- + goto EXIT;
- + }
- + else{
- + //_printk("pre-stop\n");
- + wake_up_interruptible(&(pi2s_config->i2s_tx_qh));
- + return;
- + }
- + }
- + else{
- + if(!pi2s_config->bPreTrigger[STREAM_PLAYBACK])
- + pi2s_config->bPreTrigger[STREAM_PLAYBACK] = 1;
- +
- + }
- + }
- + }
- + else
- + {
- + if(pi2s_config->tx_r_idx==pi2s_config->tx_w_idx)
- + {
- + /* Buffer Empty */
- + MSG("TXBE r=%d w=%d[i=%u,c=%u]\n",pi2s_config->tx_r_idx,pi2s_config->tx_w_idx,pi2s_config->tx_isr_cnt,dma_ch);
- +#ifdef I2S_STATISTIC
- + pi2s_status->txbuffer_unrun++;
- +#endif
- + i2s_dma_tx_transf_zero(pi2s_config, dma_ch);
- + goto EXIT;
- + }
- + }
- +
- + if(pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx]==NULL)
- + {
- + MSG("mmap buf NULL [%d]\n",pi2s_config->tx_r_idx);
- + i2s_dma_tx_transf_zero(pi2s_config, dma_ch);
- +
- + goto EXIT;
- + }
- +
- + if(pi2s_config->tx_pause_en == 1)
- + {
- + /* Enable PAUSE */
- + MSG("TX pause now\n");
- + i2s_dma_tx_transf_zero(pi2s_config, dma_ch);
- +
- + goto EXIT;
- + }
- +
- +#ifdef I2S_STATISTIC
- + pi2s_status->txbuffer_len--;
- +#endif
- + i2s_dma_tx_transf_data(pi2s_config, dma_ch);
- +
- +EXIT:
- +#if defined(CONFIG_SND_MT76XX_SOC)
- + if(pi2s_config->bALSAEnable == 1){
- + if(pi2s_config->pss[STREAM_PLAYBACK])
- + snd_pcm_period_elapsed(pi2s_config->pss[STREAM_PLAYBACK]);
- + }
- +#endif
- + wake_up_interruptible(&(pi2s_config->i2s_tx_qh));
- + return;
- +}
- +
- +void i2s_dma_rx_handler(u32 dma_ch)
- +{
- + pi2s_config->enLable = 2; /* TX:enLabel=1; RX:enLabel=2 */
- +#if defined(CONFIG_I2S_TXRX)
- + if(pi2s_config->rx_isr_cnt==0)
- + {
- + pi2s_config->next_p0_idx = 0;
- + pi2s_config->next_p1_idx = 1;
- + }
- + pi2s_config->rx_isr_cnt++;
- +
- +#ifdef I2S_STATISTIC
- + i2s_int_status(dma_ch);
- +#endif
- +
- + if (pi2s_config->bRxDMAEnable==0)
- + {
- + pi2s_config->rx_stop_cnt++;
- + i2s_dma_rx_soft_stop(pi2s_config, dma_ch);
- + MSG("rx_stop=%d\n", pi2s_config->rx_stop_cnt);
- +
- + if(pi2s_config->rx_stop_cnt == 2)
- + {
- + wake_up_interruptible(&(pi2s_config->i2s_rx_qh));
- + _printk("R:wake up!!\n");
- + }
- + return;
- + }
- +
- + if(pi2s_config->bALSAEnable)
- + {
- + if(pi2s_config->dmaStat[STREAM_CAPTURE]){
- + if(!pi2s_config->bTrigger[STREAM_CAPTURE]){
- + MSG("trigger stop: rIdx:%d widx:%d\n", pi2s_config->rx_r_idx,pi2s_config->rx_w_idx);
- + i2s_dma_rx_transf_zero(pi2s_config, dma_ch);
- + wake_up_interruptible(&(pi2s_config->i2s_rx_qh));
- + return;
- + }
- + }
- + }
- + else
- + {
- + if(((pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE)==pi2s_config->rx_r_idx){
- + /* Buffer Full */
- + MSG("RXBF r=%d w=%d[i=%u,c=%u]\n",pi2s_config->rx_r_idx,pi2s_config->rx_w_idx,pi2s_config->rx_isr_cnt,dma_ch);
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxbuffer_unrun++;
- +#endif
- + i2s_dma_rx_transf_zero(pi2s_config, dma_ch);
- + goto EXIT;
- + }
- + }
- +
- + if(pi2s_config->rx_pause_en == 1)
- + {
- + /* Enable PAUSE */
- + i2s_dma_rx_transf_zero(pi2s_config, dma_ch);
- +
- + goto EXIT;
- + }
- +
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxbuffer_len++;
- +#endif
- + i2s_dma_rx_transf_data(pi2s_config, dma_ch);
- +
- +EXIT:
- +#if defined(CONFIG_SND_MT76XX_SOC)
- + if(pi2s_config->bALSAEnable == 1){
- + if(pi2s_config->pss[STREAM_CAPTURE])
- + snd_pcm_period_elapsed(pi2s_config->pss[STREAM_CAPTURE]);
- + }
- +#endif
- + wake_up_interruptible(&(pi2s_config->i2s_rx_qh));
- +#endif
- + return;
- +}
- +
- +#ifdef I2S_STATISTIC
- +void i2s_int_status(u32 dma_ch)
- +{
- + u32 i2s_status;
- +
- + if((pi2s_config->tx_isr_cnt>0)||(pi2s_config->rx_isr_cnt>0))
- + {
- + i2s_status = i2s_inw(I2S_INT_STATUS);
- +
- + if(i2s_status®BIT(1, I2S_TX_DMA_FAULT))
- + {
- + pi2s_status->txdmafault++;
- + }
- + if(i2s_status®BIT(1, I2S_TX_OVRUN))
- + {
- + pi2s_status->txovrun++;
- + }
- + if(i2s_status®BIT(1, I2S_TX_UNRUN))
- + {
- + pi2s_status->txunrun++;
- + }
- + if(i2s_status®BIT(1, I2S_TX_THRES))
- + {
- + pi2s_status->txthres++;
- + }
- + if(i2s_status®BIT(1, I2S_RX_DMA_FAULT))
- + {
- + pi2s_status->rxdmafault++;
- + }
- + if(i2s_status®BIT(1, I2S_RX_OVRUN))
- + {
- + pi2s_status->rxovrun++;
- + }
- + if(i2s_status®BIT(1, I2S_RX_UNRUN))
- + {
- + pi2s_status->rxunrun++;
- + }
- + if(i2s_status®BIT(1, I2S_RX_THRES))
- + {
- + pi2s_status->rxthres++;
- + }
- + }
- +#if 0
- + if(pi2s_config->enLable == 1)
- + {
- + if((pi2s_config->tx_isr_cnt>0) && (pi2s_config->tx_isr_cnt%40==0))
- + {
- + MSG("tisr i=%u,ch=%u,o=%u,u=%d,s=%X [r=%d,w=%d]\n",\
- + pi2s_config->tx_isr_cnt,dma_ch,pi2s_status->txovrun,pi2s_status->txunrun,\
- + i2s_inw(I2S_INT_STATUS),pi2s_config->tx_r_idx,pi2s_config->tx_w_idx);
- + }
- + }
- +
- + if(pi2s_config->enLable == 2)
- + {
- + if((pi2s_config->rx_isr_cnt>0) && (pi2s_config->rx_isr_cnt%40==0))
- + {
- + MSG("risr i=%u,ch=%u,o=%u,u=%d,s=%X [r=%d,w=%d]\n",\
- + pi2s_config->rx_isr_cnt,dma_ch,pi2s_status->rxovrun,pi2s_status->rxunrun,\
- + i2s_inw(I2S_INT_STATUS),pi2s_config->rx_r_idx,pi2s_config->rx_w_idx);
- + }
- + }
- +#endif
- +
- + *(unsigned long*)(I2S_INT_STATUS) = 0xFFFFFFFF;
- +}
- +#endif
- +
- +#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN)
- +irqreturn_t i2s_irq_isr(int irq, void *irqaction)
- +{
- + u32 i2s_status;
- +
- + //MSG("i2s_irq_isr [0x%08X]\n",i2s_inw(I2S_INT_STATUS));
- + if((pi2s_config->tx_isr_cnt>0)||(pi2s_config->rx_isr_cnt>0))
- + {
- + i2s_status = i2s_inw(I2S_INT_STATUS);
- + MSG("i2s_irq_isr [0x%08X]\n",i2s_status);
- + }
- + else
- + return IRQ_HANDLED;
- +
- + if(i2s_status®BIT(1, I2S_TX_DMA_FAULT))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->txdmafault++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_TX_OVRUN))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->txovrun++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_TX_UNRUN))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->txunrun++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_TX_THRES))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->txthres++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_RX_DMA_FAULT))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxdmafault++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_RX_OVRUN))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxovrun++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_RX_UNRUN))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxunrun++;
- +#endif
- + }
- + if(i2s_status®BIT(1, I2S_RX_THRES))
- + {
- +#ifdef I2S_STATISTIC
- + pi2s_status->rxthres++;
- +#endif
- + }
- + i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF);
- + return IRQ_HANDLED;
- +}
- +#endif
- +
- +void i2s_tx_task(unsigned long pData)
- +{
- + unsigned long flags;
- + spin_lock_irqsave(&pi2s_config->lock, flags);
- + //if (pi2s_config->bTxDMAEnable!=0)
- + {
- + if (pi2s_config->tx_unmask_ch!=0)
- + {
- + u32 dmach = pi2s_config->tx_unmask_ch;
- + u32 ch;
- + for (ch = 0; ch < 16; ch++)
- + {
- + if (dmach& (1<<ch))
- + {
- + MSG("do unmask ch%d tisr=%d in tx_isr\n",ch,pi2s_config->tx_isr_cnt);
- + GdmaUnMaskChannel(ch);
- + }
- + }
- + pi2s_config->tx_unmask_ch = 0;
- + }
- + }
- + spin_unlock_irqrestore(&pi2s_config->lock, flags);
- +}
- +
- +void i2s_rx_task(unsigned long pData)
- +{
- + unsigned long flags;
- + spin_lock_irqsave(&pi2s_config->lock, flags);
- + //if (pi2s_config->bRxDMAEnable!=0)
- + {
- + if (pi2s_config->rx_unmask_ch!=0)
- + {
- + u32 dmach = pi2s_config->rx_unmask_ch;
- + u32 ch;
- + for (ch = 0; ch < 16; ch++)
- + {
- + if (dmach& (1<<ch))
- + {
- + MSG("do unmask ch%d risr=%d in rx_isr\n",ch,pi2s_config->rx_isr_cnt);
- + GdmaUnMaskChannel(ch);
- + }
- + }
- + pi2s_config->rx_unmask_ch = 0;
- +
- + }
- + }
- + spin_unlock_irqrestore(&pi2s_config->lock, flags);
- +}
- +
- +
- +void i2s_dma_unmask_handler(u32 dma_ch)
- +{
- + MSG("i2s_dma_unmask_handler ch=%d\n",dma_ch);
- +
- + GdmaUnMaskChannel(dma_ch);
- +
- + return;
- +}
- +
- +void i2s_dma_tx_unmask_handler(u32 dma_ch)
- +{
- + MSG("i2s_dma_tx_unmask_handler ch=%d\n",dma_ch);
- + pi2s_config->tx_unmask_ch |= (1<<dma_ch);
- + tasklet_hi_schedule(&i2s_tx_tasklet);
- + return;
- +}
- +
- +void i2s_dma_rx_unmask_handler(u32 dma_ch)
- +{
- + MSG("i2s_dma_rx_unmask_handler ch=%d\n",dma_ch);
- + pi2s_config->rx_unmask_ch |= (1<<dma_ch);
- + tasklet_hi_schedule(&i2s_rx_tasklet);
- + return;
- +}
- +
- +void i2s_dma_mask_handler(u32 dma_ch)
- +{
- + MSG("i2s_dma_mask_handler ch=%d\n", dma_ch);
- + GdmaMaskChannel(dma_ch);
- + return;
- +}
- +
- +void i2s_dma_tx_init(i2s_config_type* ptri2s_config)
- +{
- + memset(pi2s_config->pPage0TxBuf8ptr, 0, I2S_PAGE_SIZE);
- + memset(pi2s_config->pPage1TxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- + GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)ptri2s_config->pPage0TxBuf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- + GdmaI2sTx((u32)ptri2s_config->pPage1TxBuf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- +
- + return;
- +}
- +
- +void i2s_dma_rx_init(i2s_config_type* ptri2s_config)
- +{
- + memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE);
- + memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE);
- +
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- +
- + return;
- +}
- +
- +void i2s_dma_tx_end_handle(i2s_config_type* ptri2s_config)
- +{
- + if (ptri2s_config->tx_w_idx < ptri2s_config->tx_r_idx)
- + {
- + ptri2s_config->end_cnt = (ptri2s_config->tx_w_idx + MAX_I2S_PAGE)-ptri2s_config->tx_r_idx;
- + _printk("case1: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt);
- + }
- + else if (ptri2s_config->tx_w_idx > ptri2s_config->tx_r_idx)
- + {
- + ptri2s_config->end_cnt = ptri2s_config->tx_w_idx-ptri2s_config->tx_r_idx;
- + _printk("case2: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt);
- + }
- + else
- + {
- + _printk("case3: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt);
- +
- + }
- +
- + if (ptri2s_config->end_cnt > 0)
- + {
- + interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh));
- + }
- +
- + return;
- +}
- +
- +void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config)
- +{
- + while(ptri2s_config->tx_stop_cnt<3)
- + interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh));
- +
- + return;
- +}
- +
- +void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config)
- +{
- + while(ptri2s_config->rx_stop_cnt<2)
- + interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh));
- + return;
- +}
- +
- +int i2s_dma_tx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + if(dma_ch==GDMA_I2S_TX0)
- + {
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- + }
- + else
- + {
- +#if defined(ARM_ARCH)
- + GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#else
- + GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler);
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +int i2s_dma_rx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch)
- +{
- + if(dma_ch==GDMA_I2S_RX0)
- + {
- + memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- + }
- + else
- + {
- + memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE);
- +#if defined(ARM_ARCH)
- + GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#else
- + GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler);
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +void i2s_gen_test_pattern(void)
- +{
- + int i;
- + for (i=0; i<I2S_PAGE_SIZE; i++)
- + {
- + test_buf[i] = 0x5A;
- + test_buf_1[i] = 0x11;
- + test_buf_2[i] = 0x22;
- +
- + }
- +}
- +
- +int i2s_put_audio(i2s_config_type* ptri2s_config, unsigned long arg)
- +{
- + unsigned long flags;
- + int tx_w_idx;
- +
- + do{
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +
- + if(((ptri2s_config->tx_w_idx+4)%MAX_I2S_PAGE)!=ptri2s_config->tx_r_idx)
- + {
- + ptri2s_config->tx_w_idx = (ptri2s_config->tx_w_idx+1)%MAX_I2S_PAGE;
- + tx_w_idx = ptri2s_config->tx_w_idx;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + //_printk("put TB[%d] for user write\n",ptri2s_config->tx_w_idx);
- +#if defined(CONFIG_I2S_MMAP)
- + put_user(tx_w_idx, (int*)arg);
- +#else
- + copy_from_user(ptri2s_config->pMMAPTxBufPtr[tx_w_idx], (char*)arg, I2S_PAGE_SIZE);
- +#endif
- + pi2s_status->txbuffer_len++;
- + //spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + }
- + else
- + {
- + /* Buffer Full */
- + //_printk("TBF tr=%d, tw=%d\n", ptri2s_config->tx_r_idx, ptri2s_config->tx_w_idx);
- + pi2s_status->txbuffer_ovrun++;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh));
- + if (ptri2s_config->bTxDMAEnable==0 && ptri2s_config->end_cnt==0)
- + {
- + _printk("wake up for exit i2s driver\n");
- + put_user(-1, (int*)arg);
- + break;
- + }
- + }
- + }while(1);
- +
- + return 0;
- +}
- +
- +int i2s_get_audio(i2s_config_type* ptri2s_config, unsigned long arg)
- +{
- + unsigned long flags;
- + int rx_r_idx;
- +
- + do{
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + //_printk("GA rr=%d, rw=%d,i=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx,ptri2s_config->rx_isr_cnt);
- + if(((ptri2s_config->rx_r_idx+2)%MAX_I2S_PAGE)!=ptri2s_config->rx_w_idx)
- + {
- + rx_r_idx = ptri2s_config->rx_r_idx;
- + ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +#if defined(CONFIG_I2S_MMAP)
- + put_user(rx_r_idx, (int*)arg);
- +#else
- + copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[rx_r_idx], I2S_PAGE_SIZE);
- +#endif
- + //_printk("rx_r_idx=%d\n", ptri2s_config->rx_r_idx);
- + //ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE;
- + pi2s_status->rxbuffer_len--;
- + //spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + }
- + else
- + {
- + /* Buffer Full */
- + //_printk("RBF rr=%d, rw=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx);
- + pi2s_status->rxbuffer_ovrun++;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh));
- + }
- +#if defined(CONFIG_I2S_WITH_AEC)
- + if(aecFuncP->AECECDeq){
- + aecFuncP->AECECDeq(0,pi2s_config->pMMAPRxBufPtr[ptri2s_config->rx_r_idx],I2S_PAGE_SIZE);
- + }
- +#endif
- + }while(1);
- +
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +long i2s_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
- +#else
- +int i2s_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
- +#endif
- +{
- + int i ;
- + i2s_config_type* ptri2s_config;
- + unsigned long flags;
- +
- + ptri2s_config = filp->private_data;
- + switch (cmd) {
- + case I2S_RESET:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_reset_config(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_SRATE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +#if defined(CONFIG_I2S_WM8960)
- + if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ))
- + {
- + MSG("Audio sampling rate %u should be %d ~ %d Hz. Set SRate to 48000Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ);
- + ptri2s_config->srate = 48000;
- + spin_unlock(&ptri2s_config->lock);
- + break;
- + }
- +#elif defined(CONFIG_I2S_WM8750)
- + if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ))
- + {
- + MSG("Audio sampling rate %u should be %d ~ %d Hz. Set SRate to 96000Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ);
- + ptri2s_config->srate = 96000;
- + spin_unlock(&ptri2s_config->lock);
- + break;
- + }
- +#endif
- + ptri2s_config->srate = arg;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + MSG("set audio sampling rate to %d Hz\n", ptri2s_config->srate);
- + break;
- + case I2S_TX_VOL:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +
- + if((int)arg > 127)
- + ptri2s_config->txvol = 127;
- + else if((int)arg < 48)
- + ptri2s_config->txvol = 48;
- + else
- + ptri2s_config->txvol = arg;
- +
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +#if (defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751))
- + audiohw_set_master_vol(arg,arg);
- +#elif defined(CONFIG_I2S_WM8960)
- + audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol);
- +#endif
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_VOL:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +
- + if((int)arg > 63)
- + ptri2s_config->rxvol = 63;
- + else if((int)arg < 0)
- + ptri2s_config->rxvol = 0;
- + else
- + ptri2s_config->rxvol = arg;
- +
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- +#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + case I2S_WORD_LEN:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 16)
- + {
- + ptri2s_config->wordlen_24b = 0;
- + MSG("Enable 16 bit word length.\n");
- + }
- + else if ((int)arg == 24)
- + {
- + ptri2s_config->wordlen_24b = 1;
- + MSG("Enable 24 bit word length.\n");
- + }
- + else
- + {
- + MSG("MT7628 only support 16bit/24bit word length.\n");
- + spin_unlock(&ptri2s_config->lock);
- + break;
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_ENDIAN_FMT:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + {
- + ptri2s_config->little_edn = 1;
- + MSG("Little endian format.\n");
- + }
- + else
- + {
- + ptri2s_config->little_edn = 0;
- + MSG("Big endian format.\n");
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- +#endif
- + case I2S_INTERNAL_LBK:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + {
- + ptri2s_config->lbk = 1;
- + MSG("Enable internal loopback.\n");
- + }
- + else
- + {
- + ptri2s_config->lbk = 0;
- + MSG("Disable internal loopback.\n");
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_EXTERNAL_LBK:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + {
- + ptri2s_config->extlbk = 1;
- + MSG("Enable external loopback.\n");
- + }
- + else
- + {
- + ptri2s_config->extlbk = 0;
- + MSG("Disable external loopback.\n");
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_TXRX_COEXIST:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + {
- + ptri2s_config->txrx_coexist = 1;
- + MSG("TX/RX coexist.\n");
- + }
- + else
- + {
- + ptri2s_config->txrx_coexist = 0;
- + MSG("TX/RX coexist.\n");
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- +
- + case I2S_TX_ENABLE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("I2S_TXENABLE\n");
- +
- + pi2s_config->tx_unmask_ch = 0;
- + tasklet_init(&i2s_tx_tasklet, i2s_tx_task, (u32)pi2s_config);
- +
- + pi2s_config->dis_match = 0;
- + pi2s_config->start_cnt = 0;
- + i2s_gen_test_pattern();
- +
- + /* allocate tx buffer */
- + i2s_txPagebuf_alloc(ptri2s_config);
- + i2s_txbuf_alloc(ptri2s_config);
- +
- + /* Init two dma channels */
- + i2s_dma_tx_init(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + /* Init & config all tx param */
- + i2s_reset_tx_param(ptri2s_config);
- + ptri2s_config->bTxDMAEnable = 1;
- + /* Clear all ALSA related config */
- + ptri2s_config->bALSAEnable = 0;
- + ptri2s_config->bALSAMMAPEnable = 0;
- +
- + i2s_tx_config(ptri2s_config);
- +
- + if(ptri2s_config->bRxDMAEnable==0)
- + i2s_clock_enable(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol);
- +#endif
- + GdmaUnMaskChannel(GDMA_I2S_TX0);
- +
- + i2s_tx_enable(ptri2s_config);
- +
- + /* Kick off dma channel */
- + //GdmaUnMaskChannel(GDMA_I2S_TX0);
- +
- + MSG("I2S_TXENABLE done\n");
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_TX_DISABLE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("I2S_TXDISABLE\n");
- +
- + //tasklet_kill(&i2s_tx_tasklet);
- +
- + /* Handle tx end data */
- + ptri2s_config->bTxDMAEnable = 0;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + i2s_tx_end_sleep_on(ptri2s_config);
- +
- + tasklet_kill(&i2s_tx_tasklet);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_reset_tx_param(ptri2s_config);
- + i2s_tx_disable(ptri2s_config);
- + if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0))
- + i2s_clock_disable(ptri2s_config);
- +
- + i2s_txbuf_free(ptri2s_config);
- + if(ptri2s_config->mmap_index <= MAX_I2S_PAGE)
- + ptri2s_config->mmap_index = 0;
- +
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_ENABLE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("I2S_RXENABLE\n");
- + pi2s_config->rx_unmask_ch = 0;
- + tasklet_init(&i2s_rx_tasklet, i2s_rx_task, (u32)pi2s_config);
- +
- + /* allocate rx buffer */
- + i2s_rxPagebuf_alloc(ptri2s_config);
- + i2s_rxbuf_alloc(ptri2s_config);
- +
- + /* Init two dma channels */
- + i2s_dma_rx_init(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + /* Init & config all rx param */
- + i2s_reset_rx_param(ptri2s_config);
- + ptri2s_config->bRxDMAEnable = 1;
- + ptri2s_config->bALSAEnable = 0;
- + ptri2s_config->bALSAMMAPEnable = 0;
- +
- + i2s_rx_config(ptri2s_config);
- +
- + if(ptri2s_config->bTxDMAEnable==0)
- + i2s_clock_enable(ptri2s_config);
- +
- +#if defined(CONFIG_I2S_TXRX)
- +#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751)
- + audiohw_set_linein_vol(ptri2s_config->rxvol, ptri2s_config->rxvol);
- +#endif
- +#endif
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + /* Kick off dma channel */
- + GdmaUnMaskChannel(GDMA_I2S_RX0);
- +
- + i2s_rx_enable(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_DISABLE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("I2S_RXDISABLE\n");
- + //tasklet_kill(&i2s_rx_tasklet);
- +
- + ptri2s_config->bRxDMAEnable = 0;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + i2s_rx_end_sleep_on(ptri2s_config);
- + tasklet_kill(&i2s_rx_tasklet);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_reset_rx_param(ptri2s_config);
- + i2s_rx_disable(ptri2s_config);
- + if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0))
- + i2s_clock_disable(ptri2s_config);
- +
- + i2s_rxbuf_free(ptri2s_config);
- + if(ptri2s_config->mmap_index <= MAX_I2S_PAGE)
- + ptri2s_config->mmap_index = 0;
- + //i2s_rxPagebuf_free(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_PUT_AUDIO:
- + i2s_put_audio(ptri2s_config, arg);
- + break;
- + case I2S_GET_AUDIO:
- + i2s_get_audio(ptri2s_config, arg);
- + break;
- + case I2S_TX_STOP:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("TxGDMA STOP\n");
- + ptri2s_config->bTxDMAEnable = 0;
- + ptri2s_config->end_cnt = 0;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + while(ptri2s_config->tx_stop_cnt<3)
- + interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh));
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_reset_tx_param(ptri2s_config);
- + i2s_tx_disable(ptri2s_config);
- + if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0))
- + i2s_clock_disable(ptri2s_config);
- +
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_txbuf_free(ptri2s_config);
- + if(ptri2s_config->mmap_index <= MAX_I2S_PAGE)
- + ptri2s_config->mmap_index = 0;
- + //i2s_txPagebuf_free(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_TX_PAUSE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + ptri2s_config->tx_pause_en = 1;
- + MSG("* tx_pause_en = 1 *\n");
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_TX_RESUME:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + ptri2s_config->tx_pause_en = 0;
- + MSG("# tx_pause_en = 0 #\n");
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_STOP:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + MSG("I2S_RX_STOP\n");
- + ptri2s_config->bRxDMAEnable = 0;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + while(ptri2s_config->rx_stop_cnt<2)
- + interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh));
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_reset_rx_param(ptri2s_config);
- + i2s_rx_disable(ptri2s_config);
- + if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0))
- + i2s_clock_disable(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- +
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_rxbuf_free(ptri2s_config);
- + if(ptri2s_config->mmap_index <= MAX_I2S_PAGE)
- + ptri2s_config->mmap_index = 0;
- + //i2s_rxPagebuf_free(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_PAUSE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + ptri2s_config->rx_pause_en = 1;
- + MSG("* rx_pause_en = 1 *\n");
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_RX_RESUME:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + ptri2s_config->rx_pause_en = 0;
- + MSG("# rx_pause_en = 0 #\n");
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_CODEC_MIC_BOOST:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg > 3)
- + ptri2s_config->micboost = 3;
- + else if((int)arg < 0)
- + ptri2s_config->micboost = 0;
- + else
- + ptri2s_config->micboost = arg;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_CODEC_MIC_IN:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + ptri2s_config->micin = 1;
- + else
- + ptri2s_config->micin = 0;
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_CLOCK_ENABLE:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + i2s_clock_disable(ptri2s_config);
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + ptri2s_config->wordlen_24b = 1;
- +#endif
- + i2s_tx_config(ptri2s_config);
- + i2s_clock_enable(ptri2s_config);
- + i2s_tx_enable(ptri2s_config);
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- + case I2S_DEBUG_CODEC:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + for (i=0; i<10; i++)
- + {
- + _printk("### i=%d ###\n", i);
- + i2s_clock_enable(ptri2s_config);
- + i2s_clock_disable(ptri2s_config);
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- +#if defined(CONFIG_I2S_MS_CTRL)
- + case I2S_MS_MODE_CTRL:
- + spin_lock_irqsave(&ptri2s_config->lock, flags);
- + if((int)arg == 1)
- + {
- + ptri2s_config->slave_en = 1;
- + _printk("I2S in slave mode.\n");
- + }
- + else
- + {
- + ptri2s_config->slave_en = 0;
- + _printk("I2S in master mode.\n");
- + }
- + spin_unlock_irqrestore(&ptri2s_config->lock, flags);
- + break;
- +#endif
- + case I2S_DEBUG_CLKGEN:
- + case I2S_DEBUG_INLBK:
- + case I2S_DEBUG_EXLBK:
- + case I2S_DEBUG_CODECBYPASS:
- + case I2S_DEBUG_FMT:
- +#if defined(CONFIG_I2S_WM8960)
- + case I2S_DEBUG_CODEC_EXLBK:
- +#endif
- + case I2S_DEBUG_RESET:
- + i2s_debug_cmd(cmd, arg);
- + break;
- + default :
- + MSG("i2s_ioctl: command format error\n");
- + }
- +
- + return 0;
- +}
- +
- +/************************
- + * API for ALSA *
- + * *
- + ************************/
- +char* i2s_memPool_Alloc(i2s_config_type* ptri2s_config,int dir)
- +{
- + //_printk("%s\n",__func__);
- + if(!ptri2s_config)
- + return NULL;
- + if(dir == STREAM_PLAYBACK){
- +#if defined(CONFIG_I2S_MMAP)
- + i2s_mmap_alloc(I2S_TOTAL_PAGE_SIZE);
- +#endif
- + i2s_txbuf_alloc(ptri2s_config);
- + return ptri2s_config->pMMAPTxBufPtr[0];
- + }else{
- +#if defined(CONFIG_I2S_MMAP)
- + i2s_mmap_alloc(I2S_TOTAL_PAGE_SIZE);
- +#endif
- + i2s_rxbuf_alloc(ptri2s_config);
- + return ptri2s_config->pMMAPRxBufPtr[0];
- + }
- + return NULL;
- +}
- +
- +void i2s_memPool_free(i2s_config_type* ptri2s_config,int dir)
- +{
- + if(!ptri2s_config)
- + return;
- + if(dir == STREAM_PLAYBACK){
- +#if defined(CONFIG_I2S_MMAP)
- + i2s_mem_unmap(ptri2s_config);
- +#endif
- + i2s_txbuf_free(ptri2s_config);
- + }else{
- +#if defined(CONFIG_I2S_MMAP)
- + i2s_mem_unmap(ptri2s_config);
- +#endif
- + i2s_rxbuf_free(ptri2s_config);
- + }
- +
- + return;
- +}
- +
- +int i2s_page_prepare(i2s_config_type* ptri2s_config,int dir)
- +{
- + if(dir == STREAM_PLAYBACK){
- + /* allocate tx buffer */
- + i2s_txPagebuf_alloc(ptri2s_config);
- + i2s_dma_tx_init(ptri2s_config);
- + }else{
- + /* allocate rx buffer */
- + i2s_rxPagebuf_alloc(ptri2s_config);
- + i2s_dma_rx_init(ptri2s_config);
- + }
- + return 0;
- +}
- +
- +int i2s_page_release(i2s_config_type* ptri2s_config,int dir)
- +{
- + if(!ptri2s_config)
- + return (-1);
- + if(dir == STREAM_PLAYBACK)
- + i2s_txPagebuf_free(ptri2s_config);
- + else
- + i2s_rxPagebuf_free(ptri2s_config);
- +
- + return 0;
- +}
- +
- +int i2s_startup(void)
- +{
- + memset(pi2s_config, 0, sizeof(i2s_config_type));
- +
- +#ifdef I2S_STATISTIC
- + memset(pi2s_status, 0, sizeof(i2s_status_type));
- +#endif
- +
- + i2s_param_init(pi2s_config);
- + pi2s_config->bALSAEnable = 1;
- +#if defined(CONFIG_I2S_MMAP)
- + pi2s_config->bALSAMMAPEnable = 1;
- +#endif
- +
- +#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + pi2s_config->little_edn = 1;
- +#endif
- +
- + init_waitqueue_head(&(pi2s_config->i2s_tx_qh));
- + init_waitqueue_head(&(pi2s_config->i2s_rx_qh));
- + spin_lock_init(&pi2s_config->lock);
- +
- + return 0;
- +}
- +
- +int gdma_En_Switch(i2s_config_type* ptri2s_config,int dir,int enabled){
- + if(!ptri2s_config)
- + return (-1);
- + if(dir == STREAM_PLAYBACK){
- + ptri2s_config->bTxDMAEnable = enabled;
- + //MSG("%s:%d\n",__func__,ptri2s_config->bTxDMAEnable);
- + }else{
- + ptri2s_config->bRxDMAEnable = enabled;
- + }
- + return 0;
- +}
- +
- +int i2s_audio_exchange(i2s_config_type* ptri2s_config,int dir,unsigned long arg)
- +{
- + //MSG("I2S_PUT_AUDIO\n");
- + if(!ptri2s_config)
- + return (-1);
- + if(dir == STREAM_PLAYBACK){
- + i2s_put_audio(ptri2s_config, arg);
- + }else{
- + i2s_get_audio(ptri2s_config, arg);
- + }
- + return 0;
- +}
- +
- +void gdma_mask_handler(u32 dma_ch)
- +{
- + i2s_dma_mask_handler(dma_ch);
- + return;
- +}
- +
- +void gdma_unmask_handler(u32 dma_ch)
- +{
- + i2s_dma_unmask_handler(dma_ch);
- + return;
- +}
- +
- +u32 i2s_mmap_phys_addr(i2s_config_type* ptri2s_config)
- +{
- + if((ptri2s_config->pMMAPBufPtr[0]!=NULL) && (ptri2s_config->mmap_index == MAX_I2S_PAGE))
- + return (dma_addr_t)i2s_mmap_addr[0];
- + else if((ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]!=NULL) && (ptri2s_config->mmap_index == MAX_I2S_PAGE*2))
- + return (dma_addr_t)i2s_mmap_addr[MAX_I2S_PAGE];
- + else
- + return -1;
- +}
- +
- +EXPORT_SYMBOL(i2s_startup);
- +EXPORT_SYMBOL(i2s_mem_unmap);
- +EXPORT_SYMBOL(i2s_mmap_alloc);
- +EXPORT_SYMBOL(i2s_mmap_remap);
- +EXPORT_SYMBOL(i2s_param_init);
- +EXPORT_SYMBOL(i2s_txbuf_alloc);
- +EXPORT_SYMBOL(i2s_rxbuf_alloc);
- +EXPORT_SYMBOL(i2s_txPagebuf_alloc);
- +EXPORT_SYMBOL(i2s_rxPagebuf_alloc);
- +EXPORT_SYMBOL(i2s_txbuf_free);
- +EXPORT_SYMBOL(i2s_rxbuf_free);
- +EXPORT_SYMBOL(i2s_txPagebuf_free);
- +EXPORT_SYMBOL(i2s_rxPagebuf_free);
- +EXPORT_SYMBOL(i2s_rx_disable);
- +EXPORT_SYMBOL(i2s_tx_disable);
- +EXPORT_SYMBOL(i2s_rx_enable);
- +EXPORT_SYMBOL(i2s_tx_enable);
- +EXPORT_SYMBOL(i2s_rx_config);
- +EXPORT_SYMBOL(i2s_tx_config);
- +EXPORT_SYMBOL(i2s_reset_config);
- +EXPORT_SYMBOL(i2s_clock_disable);
- +EXPORT_SYMBOL(i2s_clock_enable);
- +EXPORT_SYMBOL(i2s_reset_rx_param);
- +EXPORT_SYMBOL(i2s_reset_tx_param);
- +EXPORT_SYMBOL(i2s_dma_rx_handler);
- +EXPORT_SYMBOL(i2s_dma_tx_handler);
- +EXPORT_SYMBOL(i2s_dma_unmask_handler);
- +EXPORT_SYMBOL(i2s_dma_tx_unmask_handler);
- +EXPORT_SYMBOL(i2s_dma_rx_unmask_handler);
- +EXPORT_SYMBOL(i2s_dma_mask_handler);
- +EXPORT_SYMBOL(i2s_dma_tx_init);
- +EXPORT_SYMBOL(i2s_dma_rx_init);
- +EXPORT_SYMBOL(i2s_tx_end_sleep_on);
- +EXPORT_SYMBOL(i2s_rx_end_sleep_on);
- +EXPORT_SYMBOL(i2s_mmap_phys_addr);
- +EXPORT_SYMBOL(i2s_open);
- +EXPORT_SYMBOL(pi2s_config);
- +#if defined(CONFIG_I2S_IN_MCLK)
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +EXPORT_SYMBOL(i2s_refclk_12m_enable);
- +#endif
- +#if defined(CONFIG_I2S_MCLK_12P288MHZ)
- +EXPORT_SYMBOL(i2s_refclk_12p288m_enable);
- +#endif
- +#endif
- +#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623)
- +EXPORT_SYMBOL(i2s_driving_strength_adjust);
- +#endif
- +EXPORT_SYMBOL(i2s_refclk_disable);
- +EXPORT_SYMBOL(i2s_refclk_gpio_out_config);
- +EXPORT_SYMBOL(i2s_refclk_gpio_in_config);
- +EXPORT_SYMBOL(i2s_share_pin_config);
- +EXPORT_SYMBOL(i2s_share_pin_mt7623);
- +EXPORT_SYMBOL(i2s_ws_config);
- +EXPORT_SYMBOL(i2s_mode_config);
- +EXPORT_SYMBOL(i2s_codec_frequency_config);
- +EXPORT_SYMBOL(i2s_dma_tx_transf_data);
- +EXPORT_SYMBOL(i2s_dma_tx_transf_zero);
- +EXPORT_SYMBOL(i2s_dma_rx_transf_data);
- +EXPORT_SYMBOL(i2s_dma_rx_transf_zero);
- +EXPORT_SYMBOL(i2s_dma_tx_end_handle);
- +EXPORT_SYMBOL(i2s_dma_tx_soft_stop);
- +EXPORT_SYMBOL(i2s_dma_rx_soft_stop);
- +EXPORT_SYMBOL(i2s_tx_task);
- +EXPORT_SYMBOL(i2s_rx_task);
- +
- +EXPORT_SYMBOL(i2s_memPool_Alloc);
- +EXPORT_SYMBOL(i2s_memPool_free);
- +EXPORT_SYMBOL(i2s_page_prepare);
- +EXPORT_SYMBOL(i2s_page_release);
- +EXPORT_SYMBOL(gdma_En_Switch);
- +EXPORT_SYMBOL(i2s_audio_exchange);
- +EXPORT_SYMBOL(gdma_mask_handler);
- +EXPORT_SYMBOL(gdma_unmask_handler);
- +#if defined(CONFIG_I2S_WITH_AEC)
- +EXPORT_SYMBOL(aecFuncP);
- +#endif
- +module_init(i2s_mod_init);
- +module_exit(i2s_mod_exit);
- +
- +MODULE_DESCRIPTION("Ralink SoC I2S Controller Module");
- +MODULE_AUTHOR("Qwert Chin <qwert.chin@ralinktech.com.tw>");
- +MODULE_SUPPORTED_DEVICE("I2S");
- +MODULE_VERSION(I2S_MOD_VERSION);
- +MODULE_LICENSE("GPL");
- +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
- +MODULE_PARM (i2sdrv_major, "i");
- +#else
- +module_param (i2sdrv_major, int, 0);
- +#endif
- --- /dev/null
- +++ b/sound/soc/mtk/i2s_ctrl.h
- @@ -0,0 +1,523 @@
- +#ifndef __RALINK_I2S_H_
- +#define __RALINK_I2S_H_
- +
- +#ifdef __KERNEL__
- +//#include <asm/rt2880/rt_mmap.h>
- +#endif
- +
- +#if defined(CONFIG_I2S_WITH_AEC)
- +#include "aec/aec_api.h"
- +#endif
- +
- +#define I2S_MAX_DEV 1
- +#define I2S_MOD_VERSION "0.1"
- +#define phys_to_bus(a) (a & 0x1FFFFFFF)
- +
- +#ifndef u32
- +#define u32 unsigned int
- +#endif
- +
- +#ifndef u16
- +#define u16 unsigned short
- +#endif
- +
- +#ifndef u8
- +#define u8 unsigned char
- +#endif
- +
- +#ifndef REGBIT
- +#define REGBIT(x, n) (x << n)
- +#endif
- +
- +#define Virtual2Physical(x) (((int)x) & 0x1fffffff)
- +#define Physical2Virtual(x) (((int)x) | 0x80000000)
- +#define Virtual2NonCache(x) (((int)x) | 0x20000000)
- +#define Physical2NonCache(x) (((int)x) | 0xa0000000)
- +#define NonCache2Virtual(x) (((int)x) & 0xDFFFFFFF)
- +
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +#define CONFIG_I2S_CODEC_PLL_EN 1
- +#else
- +#define CONFIG_I2S_CODEC_PLL_EN 0
- +#endif
- +
- +//#define CONFIG_I2S_MS_CTRL
- +//#define CONFIG_I2S_MS_MODE
- +//#define memory_test
- +
- +#if defined (CONFIG_ARCH_MT7623)
- +#define MT7623_ASIC_BOARD
- +#define ARM_ARCH
- +#endif
- +
- +#if defined (CONFIG_RALINK_MT7621)
- +#define MT7621_ASIC_BOARD
- +#endif
- +
- +#if defined (CONFIG_RALINK_MT7628)
- +#define MT7628_ASIC_BOARD
- +#endif
- +
- +//#define I2S_DEBUG_PRN
- +#ifdef I2S_DEBUG_PRN
- +#define MSG(fmt, args...) printk("I2S: " fmt, ## args)
- +#else
- +#define MSG(fmt, args...) { }
- +#endif
- +
- +#ifdef I2S_DEBUG_PRN
- +#define i2s_outw(address, value) do{printk("0x%08X = 0x%08X\n",(u32)address,(u32)value);*((volatile uint32_t *)(address)) = cpu_to_le32(value);}while(0)
- +#else
- +#define i2s_outw(address, value) *((volatile uint32_t *)(address)) = cpu_to_le32(value)
- +#endif
- +#define i2s_inw(address) le32_to_cpu(*(volatile u32 *)(address))
- +
- +/* HW feature definiations */
- +#if defined(CONFIG_RALINK_RT3883)
- +#define CONFIG_I2S_TXRX 1
- +#define CONFIG_I2S_IN_MCLK 1
- +//#define CONFIG_I2S_WS_EDGE 1
- +#define CONFIG_I2S_FRAC_DIV 1
- +#define CONFIG_I2S_IN_CLK 1
- +#define CONFIG_I2S_MS_MODE 1
- +#endif
- +
- +#if defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) \
- + || defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) \
- + || defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- +#define CONFIG_I2S_TXRX 1
- +//#define CONFIG_I2S_WS_EDGE 1
- +#define CONFIG_I2S_FRAC_DIV 1
- +#define CONFIG_I2S_IN_CLK 1
- +#endif
- +
- +#if defined(CONFIG_RALINK_RT3350)
- +#define CONFIG_I2S_IN_MCLK 1
- +#endif
- +
- +#if defined(CONFIG_RALINK_RT3052)
- +#define CONFIG_I2S_MS_MODE 1
- +#endif
- +
- +/* This is decided in menuconfig */
- +#define CONFIG_I2S_MMAP 1
- +
- +/* For MT7623 ASIC PLL Setting */
- +#if defined(CONFIG_ARCH_MT7623)
- +#define AUD1PLL_CON0 (0xF0209270)
- +#define AUD1PLL_CON1 (0xF0209274)
- +#define AUD1PLL_CON2 (0xF0209278)
- +#define AUD1PLL_PWR_CON0 (0xF020927C)
- +#define AUD2PLL_CON0 (0xF02092C0)
- +#define AUD2PLL_CON1 (0xF02092C4)
- +#define AUD2PLL_CON2 (0xF02092C8)
- +#define AUD2PLL_PWR_CON0 (0xF02092CC)
- +#endif
- +
- +/* Register Map, Ref to RT3052 Data Sheet */
- +
- +/* Register Map Detail */
- +#if defined(CONFIG_ARCH_MT7623)
- +#define I2S_I2SCFG (ETHDMASYS_I2S_BASE+0x0000)
- +#define I2S_INT_STATUS (ETHDMASYS_I2S_BASE+0x0004)
- +#define I2S_INT_EN (ETHDMASYS_I2S_BASE+0x0008)
- +#define I2S_FF_STATUS (ETHDMASYS_I2S_BASE+0x000c)
- +#define I2S_FIFO_WREG (ETHDMASYS_I2S_BASE+0x0010)
- +#define I2S_TX_FIFO_WREG I2S_FIFO_WREG
- +#define I2S_RX_FIFO_RREG (ETHDMASYS_I2S_BASE+0x0014)
- +#define I2S_I2SCFG1 (ETHDMASYS_I2S_BASE+0x0018)
- +#define I2S_DIVINT_CFG (ETHDMASYS_I2S_BASE+0x0024)
- +#define I2S_DIVCOMP_CFG (ETHDMASYS_I2S_BASE+0x0020)
- +#else
- +#define I2S_I2SCFG (RALINK_I2S_BASE+0x0000)
- +#define I2S_INT_STATUS (RALINK_I2S_BASE+0x0004)
- +#define I2S_INT_EN (RALINK_I2S_BASE+0x0008)
- +#define I2S_FF_STATUS (RALINK_I2S_BASE+0x000c)
- +#define I2S_FIFO_WREG (RALINK_I2S_BASE+0x0010)
- +#define I2S_TX_FIFO_WREG I2S_FIFO_WREG
- +#define I2S_RX_FIFO_RREG (RALINK_I2S_BASE+0x0014)
- +#define I2S_I2SCFG1 (RALINK_I2S_BASE+0x0018)
- +#define I2S_DIVINT_CFG (RALINK_I2S_BASE+0x0024)
- +#define I2S_DIVCOMP_CFG (RALINK_I2S_BASE+0x0020)
- +#endif
- +
- +
- +/* I2SCFG bit field */
- +#define I2S_EN 31
- +#define I2S_DMA_EN 30
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- +#define I2S_LITTLE_ENDIAN 29
- +#define I2S_SYS_ENDIAN 28
- +#elif defined(CONFIG_RALINK_RT6855A)
- +#define I2S_BYTE_SWAP 28
- +#endif
- +#define I2S_TX_EN 24
- +#define I2S_RX_EN 20
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- +#define I2S_NORM_24BIT 18
- +#define I2S_DATA_24BIT 17
- +#endif
- +#define I2S_SLAVE_MODE 16
- +#define I2S_RX_FF_THRES 12
- +#define I2S_RX_CH_SWAP 11
- +#define I2S_RX_CH1_OFF 10
- +#define I2S_RX_CH0_OFF 9
- +#if defined(CONFIG_RALINK_RT3052)
- +#define I2S_CLK_OUT_DIS 8
- +#endif
- +#define I2S_TX_FF_THRES 4
- +#define I2S_TX_CH_SWAP 3
- +#define I2S_TX_CH1_OFF 2
- +#define I2S_TX_CH0_OFF 1
- +#if defined(CONFIG_RALINK_RT3052)
- +#define I2S_SLAVE_EN 0
- +#else
- +#define I2S_WS_INV 0
- +#endif
- +/* INT_EN bit field */
- +#define I2S_RX_INT3_EN 7
- +#define I2S_RX_INT2_EN 6
- +#define I2S_RX_INT1_EN 5
- +#define I2S_RX_INT0_EN 4
- +#define I2S_TX_INT3_EN 3
- +#define I2S_TX_INT2_EN 2
- +#define I2S_TX_INT1_EN 1
- +#define I2S_TX_INT0_EN 0
- +
- +/* INT_STATUS bit field */
- +#define I2S_RX_DMA_FAULT 7
- +#define I2S_RX_OVRUN 6
- +#define I2S_RX_UNRUN 5
- +#define I2S_RX_THRES 4
- +#define I2S_TX_DMA_FAULT 3
- +#define I2S_TX_OVRUN 2
- +#define I2S_TX_UNRUN 1
- +#define I2S_TX_THRES 0
- +
- +/* FF_STATUS bit field */
- +#define I2S_RX_EPCNT 4
- +#define I2S_TX_EPCNT 0
- +/* I2S_DIVCOMP_CFG bit field */
- +#define I2S_CLKDIV_EN 31
- +
- +/* I2S_CFG1 bit field */
- +#define I2S_LBK_EN 31
- +#define I2S_EXT_LBK_EN 30
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- +#define I2S_DATA_FMT 0
- +#endif
- +
- +/* FIFO_WREG bit field */
- +#define I2S_FIFO_WDATA 0
- +
- +/* Constant definition */
- +#define NFF_THRES 4
- +#define I2S_PAGE_SIZE 3072//(3*4096)//(1152*2*2*2)
- +#define I2S_MIN_PAGE_SIZE 4096
- +#define MAX_I2S_PAGE 8
- +#define I2S_TOTAL_PAGE_SIZE (I2S_PAGE_SIZE*MAX_I2S_PAGE)
- +
- +#if defined(CONFIG_I2S_WM8960)
- +#define MAX_SRATE_HZ 48000
- +#define MIN_SRATE_HZ 8000
- +#elif defined(CONFIG_I2S_WM8750)
- +#define MAX_SRATE_HZ 96000
- +#define MIN_SRATE_HZ 8000
- +#endif
- +
- +#define MAX_VOL_DB +0
- +#define MIN_VOL_DB -127
- +
- +#define ALSA_MMAP_IDX_SHIFT 2
- +#if defined(CONFIG_SND_MT76XX_SOC)
- +#define STREAM_PLAYBACK SNDRV_PCM_STREAM_PLAYBACK
- +#define STREAM_CAPTURE SNDRV_PCM_STREAM_CAPTURE
- +#else
- +#define STREAM_PLAYBACK 0
- +#define STREAM_CAPTURE 1
- +#endif
- +
- +/* I2S I/O command */
- +#define I2S_SRATE 0
- +#define I2S_VOL 1
- +#define I2S_ENABLE 2
- +#define I2S_DISABLE 3
- +#define I2S_TX_ENABLE 27
- +#define I2S_TX_DISABLE 3
- +#define I2S_GET_WBUF 4
- +#define I2S_PUT_WBUF 5
- +#define I2S_RX_ENABLE 6
- +#define I2S_RX_DISABLE 7
- +#define I2S_PUT_AUDIO 4
- +#define I2S_GET_AUDIO 5
- +#define I2S_TX_VOL 1
- +#define I2S_RX_VOL 8
- +#define I2S_WORD_LEN 9
- +#define I2S_ENDIAN_FMT 10
- +#define I2S_INTERNAL_LBK 11
- +#define I2S_TX_STOP 12
- +#define I2S_DEBUG_CODEC 13
- +#define I2S_MS_MODE_CTRL 14
- +#define I2S_TX_PAUSE 15
- +#define I2S_TX_RESUME 16
- +#define I2S_RESET 17
- +#define I2S_RX_STOP 18
- +#define I2S_EXTERNAL_LBK 19
- +#define I2S_TXRX_COEXIST 20
- +#define I2S_RX_PAUSE 21
- +#define I2S_RX_RESUME 22
- +#define I2S_CODEC_MIC_BOOST 23
- +#define I2S_CODEC_MIC_IN 24
- +#define I2S_CLOCK_ENABLE 25
- +#define I2S_TEST_TEST 26
- +
- +#define I2S_DEBUG 30
- +#define I2S_DEBUG_CLKGEN 30
- +#define I2S_DEBUG_INLBK 31
- +#define I2S_DEBUG_EXLBK 32
- +#define I2S_DEBUG_FMT 33
- +#define I2S_DEBUG_RESET 34
- +#define I2S_DEBUG_CODECBYPASS 35
- +#if defined(CONFIG_I2S_WM8960)
- +#define I2S_DEBUG_CODEC_EXLBK 36
- +#endif
- +
- +/* configuration */
- +#define CONFIG_I2S_TFF_THRES NFF_THRES
- +#define CONFIG_I2S_CH_SWAP 0
- +#if defined(CONFIG_I2S_MS_MODE)
- +#define CONFIG_I2S_SLAVE_EN 0
- +#else
- +#define CONFIG_I2S_SLAVE_EN 1
- +#endif
- +
- +/* driver status definition */
- +#define I2S_OK 0
- +#define I2S_OUTOFMEM 0x01
- +#define I2S_GDMAFAILED 0x02
- +#define I2S_REQUEST_IRQ_FAILED 0x04
- +#define I2S_REG_SETUP_FAILED 0x08
- +
- +#define I2S_STATISTIC
- +//#define I2S_HW_INTERRUPT_EN
- +//#define I2S_SW_IRQ_EN
- +#define I2S_MAJOR 234
- +
- +/* parameter for ALSA */
- +/*GDMA for I2S Status*/
- +#define GDMA_I2S_DIS (0)
- +#define GDMA_I2S_EN (1)
- +
- +
- +typedef struct i2s_status_t
- +{
- + u32 txdmafault;
- + u32 txovrun;
- + u32 txunrun;
- + u32 txthres;
- + int txbuffer_unrun;
- + int txbuffer_ovrun;
- + int txbuffer_len;
- +
- + u32 rxdmafault;
- + u32 rxovrun;
- + u32 rxunrun;
- + u32 rxthres;
- + int rxbuffer_unrun;
- + int rxbuffer_ovrun;
- + int rxbuffer_len;
- +}i2s_status_type;
- +
- +
- +typedef struct i2s_config_t
- +{
- +
- + int srate;
- + int txvol;
- + int rxvol;
- + u32 pos;
- + u32 tx_isr_cnt;
- + u32 rx_isr_cnt;
- + int bSleep;
- + int bTxDMAEnable;
- + int bRxDMAEnable;
- + int enLable;
- + int micboost;
- + int micin;
- +
- + /* parameters fo ALSA */
- + int bALSAEnable;
- + int bALSAMMAPEnable;
- + unsigned char bTrigger[2];
- + unsigned char bPreTrigger[2];
- + unsigned char dmaStat[2];
- + unsigned char i2sStat[2];
- + unsigned int hw_base_frame[2];
- + struct snd_pcm_substream *pss[2];
- +
- +#ifdef __KERNEL__
- + spinlock_t lock;
- + wait_queue_head_t i2s_tx_qh, i2s_rx_qh;
- +#endif
- + u32 dmach;
- + u32 tx_unmask_ch;
- + u32 rx_unmask_ch;
- + u32 dma_unmask_status;
- + u32 dma_done_status;
- + u32 tx_ff_thres;
- + u32 tx_ch_swap;
- + u32 rx_ff_thres;
- + u32 rx_ch_swap;
- + u32 slave_en;
- +
- + u32 dis_match;
- + int start_cnt;
- +#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + int little_edn; /* test file's fmt: little endian->1; big endian->0 */
- + int sys_endian; /* kernal' system fmt: little endian->0; big endian->1 */
- +#endif
- + int wordlen_24b;
- + int codec_pll_en;
- + int codec_num;
- + int tx_pause_en;
- + int rx_pause_en;
- + int end_cnt;
- + int txrx_coexist;
- + int tx_stop_cnt;
- + int rx_stop_cnt;
- + /* for I2S_CFG1 */
- + u32 lbk;
- + u32 extlbk;
- + u32 fmt;
- +
- + int w_idx;
- + int r_idx;
- +
- + int tx_w_idx;
- + int tx_r_idx;
- + int rx_w_idx;
- + int rx_r_idx;
- + int mmap_index;
- + int next_p0_idx;
- + int next_p1_idx;
- +
- + u8* buf8ptr;
- + char* pMMAPBufPtr[MAX_I2S_PAGE*2];
- + char* pMMAPTxBufPtr[MAX_I2S_PAGE];
- + char* pMMAPRxBufPtr[MAX_I2S_PAGE];
- +
- + union {
- + u16* pPage0TxBuf16Ptr;
- + u8* pPage0TxBuf8ptr;
- + };
- + union {
- + u16* pPage1TxBuf16Ptr;
- + u8* pPage1TxBuf8ptr;
- + };
- +
- + union {
- + u16* pPage0RxBuf16Ptr;
- + u8* pPage0RxBuf8ptr;
- + };
- + union {
- + u16* pPage1RxBuf16Ptr;
- + u8* pPage1RxBuf8ptr;
- + };
- +
- +}i2s_config_type;
- +
- +
- +void i2s_gen_test_pattern(void);
- +int i2s_mem_unmap(i2s_config_type* ptri2s_config);
- +int i2s_param_init(i2s_config_type* ptri2s_config);
- +int i2s_txbuf_alloc(i2s_config_type* ptri2s_config);
- +int i2s_rxbuf_alloc(i2s_config_type* ptri2s_config);
- +int i2s_txPagebuf_alloc(i2s_config_type* ptri2s_config);
- +int i2s_rxPagebuf_alloc(i2s_config_type* ptri2s_config);
- +int i2s_txbuf_free(i2s_config_type* ptri2s_config);
- +int i2s_rxbuf_free(i2s_config_type* ptri2s_config);
- +int i2s_txPagebuf_free(i2s_config_type* ptri2s_config);
- +int i2s_rxPagebuf_free(i2s_config_type* ptri2s_config);
- +int i2s_reset_tx_param(i2s_config_type* ptri2s_config);
- +int i2s_reset_rx_param(i2s_config_type* ptri2s_config);
- +int i2s_tx_config(i2s_config_type* ptri2s_config);
- +int i2s_rx_config(i2s_config_type* ptri2s_config);
- +int i2s_tx_enable(i2s_config_type* ptri2s_config);
- +int i2s_tx_disable(i2s_config_type* ptri2s_config);
- +int i2s_rx_enable(i2s_config_type* ptri2s_config);
- +int i2s_rx_disable(i2s_config_type* ptri2s_config);
- +int i2s_codec_enable(i2s_config_type* ptri2s_config);
- +int i2s_codec_disable(i2s_config_type* ptri2s_config);
- +int i2s_clock_enable(i2s_config_type* ptri2s_config);
- +int i2s_clock_disable(i2s_config_type* ptri2s_config);
- +int i2s_reset_config(i2s_config_type* ptri2s_config);
- +int i2s_refclk_disable(void);
- +int i2s_refclk_gpio_out_config(void);
- +int i2s_refclk_gpio_in_config(void);
- +int i2s_share_pin_config(i2s_config_type* ptri2s_config);
- +int i2s_share_pin_mt7623(i2s_config_type* ptri2s_config);
- +int i2s_master_clock_gpio_out_mt7623(void);
- +int i2s_slave_clock_gpio_in_mt7623(void);
- +int i2s_ws_config(i2s_config_type* ptri2s_config, unsigned long index);
- +int i2s_mode_config(u32 slave_en);
- +int i2s_codec_frequency_config(i2s_config_type* ptri2s_config, unsigned long index);
- +void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config);
- +void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config);
- +
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- +int i2s_refclk_12m_enable(void);
- +#endif
- +#if defined(CONFIG_I2S_MCLK_12P288MHZ)
- +int i2s_refclk_12p288m_enable(void);
- +#endif
- +
- +#if defined(MT7621_ASIC_BOARD)
- +int i2s_pll_config_mt7621(unsigned long index);
- +int i2s_pll_refclk_set(void);
- +#endif
- +#if defined(MT7623_ASIC_BOARD)
- +int i2s_pll_config_mt7623(unsigned long index);
- +#endif
- +#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623)
- +int i2s_driving_strength_adjust(void);
- +#endif
- +#if defined(I2S_STATISTIC)
- +void i2s_int_status(u32 dma_ch);
- +#endif
- +void i2s_dma_tx_handler(u32 dma_ch);
- +void i2s_dma_rx_handler(u32 dma_ch);
- +void i2s_dma_unmask_handler(u32 dma_ch);
- +void i2s_dma_mask_handler(u32 dma_ch);
- +void i2s_dma_tx_init(i2s_config_type* ptri2s_config);
- +void i2s_dma_rx_init(i2s_config_type* ptri2s_config);
- +void i2s_tx_task(unsigned long pData);
- +void i2s_rx_task(unsigned long pData);
- +void i2s_dma_tx_unmask_handler(u32 dma_ch);
- +void i2s_dma_rx_unmask_handler(u32 dma_ch);
- +int i2s_dma_tx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch);
- +int i2s_dma_tx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch);
- +int i2s_dma_rx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch);
- +int i2s_dma_rx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch);
- +void i2s_dma_tx_end_handle(i2s_config_type* ptri2s_config);
- +int i2s_dma_tx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch);
- +int i2s_dma_rx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch);
- +
- +int i2s_page_prepare(i2s_config_type* ptri2s_config,int dir);
- +int i2s_page_release(i2s_config_type* ptri2s_config,int dir);
- +int gdma_En_Switch(i2s_config_type* ptri2s_config,int dir,int enabled);
- +int i2s_startup(void);
- +int i2s_audio_exchange(i2s_config_type* ptri2s_config,int dir,unsigned long arg);
- +void gdma_unmask_handler(u32 dma_ch);
- +char* i2s_memPool_Alloc(i2s_config_type* ptri2s_config,int dir);
- +void i2s_memPool_free(i2s_config_type* ptri2s_config,int dir);
- +u32 i2s_mmap_phys_addr(i2s_config_type* ptri2s_config);
- +
- +#if !defined(CONFIG_I2S_TXRX)
- +#define GdmaI2sRx //GdmaI2sRx
- +#endif
- +
- +#define RALINK_I2S_VERSION "1.0"
- +#define I2SDRV_DEVNAME "i2s0"
- +
- +#endif /* __RALINK_I2S_H_ */
- +
- --- /dev/null
- +++ b/sound/soc/mtk/mt76xx_i2s.c
- @@ -0,0 +1,304 @@
- +/*
- + * mtk_audio_drv.c
- + *
- + * Created on: 2013/8/20
- + * Author: MTK04880
- + */
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#include <linux/sched.h>
- +#endif
- +#include <linux/module.h>
- +#include <linux/kernel.h> /* printk() */
- +#include <linux/slab.h> /* kmalloc() */
- +#include <linux/fs.h> /* everything... */
- +#include <linux/errno.h> /* error codes */
- +#include <linux/types.h> /* size_t */
- +#include <linux/proc_fs.h>
- +#include <linux/fcntl.h> /* O_ACCMODE */
- +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
- +#include <asm/system.h> /* cli(), *_flags */
- +#endif
- +#include <asm/uaccess.h> /* copy_from/to_user */
- +#include <linux/interrupt.h>
- +#include <linux/mm.h>
- +#include <linux/dma-mapping.h>
- +#include <sound/core.h>
- +#include <linux/pci.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/soc-dapm.h>
- +#include <sound/initval.h>
- +#include "ralink_gdma.h"
- +#include "mt76xx_i2s.h"
- +
- +/****************************/
- +/*GLOBAL VARIABLE DEFINITION*/
- +/****************************/
- +extern i2s_config_type* pi2s_config;
- +
- +/****************************/
- +/*FUNCTION DECLRATION */
- +/****************************/
- +static int mt76xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,\
- + unsigned int fmt);
- +
- +//static int mt76xx_i2s_shutdown(struct snd_pcm_substream *substream,
- +// struct snd_soc_dai *dai);
- +static int mt76xx_i2s_startup(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai);
- +static int mt76xx_i2s_hw_params(struct snd_pcm_substream *substream,\
- + struct snd_pcm_hw_params *params,\
- + struct snd_soc_dai *dai);
- +static int mt76xx_i2s_play_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai);
- +static int mt76xx_i2s_rec_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai);
- +static int mt76xx_i2s_hw_free(struct snd_pcm_substream *substream,struct snd_soc_dai *dai);
- +static int mt76xx_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai);
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20)
- +static int mt76xx_i2s_drv_probe(struct platform_device *pdev);
- +static int mt76xx_i2s_drv_remove(struct platform_device *pdev);
- +#endif
- +/****************************/
- +/*STRUCTURE DEFINITION */
- +/****************************/
- +
- +
- +static struct snd_soc_dai_ops mt76xx_i2s_dai_ops = {
- + .startup = mt76xx_i2s_startup,
- + .hw_params = mt76xx_i2s_hw_params,
- + .hw_free = mt76xx_i2s_hw_free,
- + //.shutdown = mt76xx_i2s_shutdown,
- + .prepare = mt76xx_i2s_prepare,
- + .set_fmt = mt76xx_i2s_set_fmt,
- + //.set_sysclk = mt76xx_i2s_set_sysclk,
- +};
- +
- +const struct snd_soc_component_driver mt76xx_i2s_component = {
- + .name = "mt76xx-i2s",
- +};
- +
- +struct snd_soc_dai_driver mt76xx_i2s_dai = {
- + .playback = {
- + .channels_min = 1,
- + .channels_max = 2,
- + .rates = (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\
- + SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_32000|\
- + SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000),
- +
- + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- + SNDRV_PCM_FMTBIT_S24_LE),
- + },
- + .capture = {
- + .channels_min = 1,
- + .channels_max = 2,
- + .rates = (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\
- + SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_32000|\
- + SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000),
- + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- + SNDRV_PCM_FMTBIT_S24_LE),
- + },
- + .ops = &mt76xx_i2s_dai_ops,
- + .symmetric_rates = 1,
- +};
- +
- +/****************************/
- +/*FUNCTION BODY */
- +/****************************/
- +
- +static int mt76xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
- + unsigned int fmt)
- +{//TODO
- +
- + //printk("******* %s *******\n", __func__);
- + return 0;
- +}
- +
- +static int mt76xx_i2s_play_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
- +{
- + //printk("******* %s *******\n", __func__);
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + rtd->pss[SNDRV_PCM_STREAM_PLAYBACK] = substream;
- + if(! rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]){
- + i2s_reset_tx_param( rtd);
- + i2s_tx_config( rtd);
- + gdma_En_Switch(rtd, STREAM_PLAYBACK, GDMA_I2S_EN);
- +
- + if( rtd->bRxDMAEnable==0)
- + i2s_clock_enable( rtd);
- +
- + i2s_tx_enable( rtd);
- + rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK] = 1;
- + MSG("I2S_TXENABLE done\n");
- + }
- +
- + return 0;
- +}
- +
- +static int mt76xx_i2s_rec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
- +{
- +
- + //printk("******* %s *******\n", __func__);
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + rtd->pss[SNDRV_PCM_STREAM_CAPTURE] = substream;
- + if(! rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE]) {
- + i2s_reset_rx_param(rtd);
- + i2s_rx_config(rtd);
- + gdma_En_Switch(rtd, STREAM_CAPTURE, GDMA_I2S_EN);
- +
- + if(rtd->bTxDMAEnable==0)
- + i2s_clock_enable(rtd);
- +
- + i2s_rx_enable(rtd);
- + rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE] = 1;
- + }
- + return 0;
- +}
- +
- +/*static int mt76xx_i2s_shutdown(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + //i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + //printk("******* %s *******\n", __func__);
- + return 0;
- +}
- +*/
- +static int mt76xx_i2s_startup(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- +
- + //printk("******* %s *******\n", __func__);
- + if((!pi2s_config->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]) && (!pi2s_config->i2sStat[SNDRV_PCM_STREAM_CAPTURE])){
- + i2s_startup();
- + if(!pi2s_config)
- + return -1;
- + i2s_reset_config(pi2s_config);
- + }
- + substream->runtime->private_data = pi2s_config;
- + return 0;
- +}
- +
- +static int mt76xx_i2s_hw_params(struct snd_pcm_substream *substream,\
- + struct snd_pcm_hw_params *params,\
- + struct snd_soc_dai *dai){
- + unsigned int srate = 0;
- + //unsigned long data;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + i2s_config_type* rtd = runtime->private_data;
- +
- + //printk("******* %s *******\n", __func__);
- + switch(params_rate(params)){
- + case 8000:
- + srate = 8000;
- + break;
- + case 16000:
- + srate = 16000;
- + break;
- + case 32000:
- + srate = 32000;
- + break;
- + case 44100:
- + srate = 44100;
- + break;
- + case 48000:
- + srate = 48000;
- + break;
- + default:
- + srate = 44100;
- + //MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)params_rate(params), MIN_SRATE_HZ, MAX_SRATE_HZ);
- + break;
- + }
- + if(srate){
- + if((rtd->bRxDMAEnable != GDMA_I2S_EN) && (rtd->bTxDMAEnable != GDMA_I2S_EN)){
- + rtd->srate = srate;
- + MSG("set audio sampling rate to %d Hz\n", rtd->srate);
- + }
- + }
- +
- + return 0;
- +}
- +static int mt76xx_i2s_hw_free(struct snd_pcm_substream *substream,struct snd_soc_dai *dai){
- +
- + //printk("******* %s *******\n", __func__);
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + if(rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]){
- + MSG("I2S_TXDISABLE\n");
- + i2s_reset_tx_param(rtd);
- +
- + if((rtd->bRxDMAEnable==0)&&(rtd->bTxDMAEnable==0)){
- + i2s_clock_disable(rtd);
- + }
- + rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK] = 0;
- + }
- + }
- + else{
- + if(rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE]){
- + MSG("I2S_RXDISABLE\n");
- + i2s_reset_rx_param(rtd);
- +
- + if((rtd->bRxDMAEnable==0)&&(rtd->bTxDMAEnable==0)){
- + i2s_clock_disable(rtd);
- + }
- + rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE] = 0;
- + }
- + }
- + return 0;
- +}
- +static int mt76xx_i2s_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai)
- +{
- +
- + //printk("******* %s *******\n", __func__);
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + return mt76xx_i2s_play_prepare(substream, dai);
- + else
- + return mt76xx_i2s_rec_prepare(substream, dai);
- +
- + return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20)
- +static int mt76xx_i2s_drv_probe(struct platform_device *pdev)
- +{
- + //printk("****** %s ******\n", __func__);
- + return snd_soc_register_component(&pdev->dev, &mt76xx_i2s_component,
- + &mt76xx_i2s_dai, 1);
- +}
- +
- +static int mt76xx_i2s_drv_remove(struct platform_device *pdev)
- +{
- + snd_soc_unregister_component(&pdev->dev);
- + return 0;
- +}
- +
- +static struct platform_driver mt76xx_i2s_driver = {
- + .probe = mt76xx_i2s_drv_probe,
- + .remove = mt76xx_i2s_drv_remove,
- + .driver = {
- + .name = "mt76xx-i2s",
- + .owner = THIS_MODULE,
- + },
- +};
- +
- +static int __init mt76xx_i2s_init(void)
- +{
- +
- + //printk("****** %s ******\n", __func__);
- + return platform_driver_register(&mt76xx_i2s_driver);
- +}
- +
- +static void __exit mt76xx_i2s_exit(void)
- +{
- + //printk("****** %s ******\n", __func__);
- + platform_driver_unregister(&mt76xx_i2s_driver);
- +}
- +
- +module_init(mt76xx_i2s_init);
- +module_exit(mt76xx_i2s_exit);
- +
- +MODULE_AUTHOR("Dora Chen");
- +MODULE_DESCRIPTION("Stretch MT76xx I2S Interface");
- +MODULE_LICENSE("GPL");
- +#endif
- --- /dev/null
- +++ b/sound/soc/mtk/mt76xx_i2s.h
- @@ -0,0 +1,18 @@
- +/*
- + * mtk_i2s.h
- + *
- + * Created on: 2013/8/20
- + * Author: MTK04880
- + */
- +
- +#ifndef MTK_I2S_H_
- +#define MTK_I2S_H_
- +
- +
- +#ifdef __KERNEL__
- +//#include <asm/rt2880/rt_mmap.h>
- +#include <linux/fs.h>
- +#endif
- +
- +#include "i2s_ctrl.h"
- +#endif /* MTK_I2S_H_ */
- --- /dev/null
- +++ b/sound/soc/mtk/mt76xx_machine.c
- @@ -0,0 +1,317 @@
- +/*
- + * mt76xx_machine.c
- + *
- + */
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#include <linux/sched.h>
- +#endif
- +#include <linux/module.h>
- +#include <linux/kernel.h> /* printk() */
- +#include <linux/slab.h> /* kmalloc() */
- +#include <linux/fs.h> /* everything... */
- +#include <linux/errno.h> /* error codes */
- +#include <linux/types.h> /* size_t */
- +#include <linux/proc_fs.h>
- +#include <linux/fcntl.h> /* O_ACCMODE */
- +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
- +#include <asm/system.h> /* cli(), *_flags */
- +#endif
- +#include <asm/uaccess.h> /* copy_from/to_user */
- +#include <linux/interrupt.h>
- +#include <linux/mm.h>
- +#include <linux/dma-mapping.h>
- +#include <sound/core.h>
- +#include <linux/pci.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/soc-dapm.h>
- +#include <sound/initval.h>
- +#include <linux/i2c.h>
- +#include <linux/ioport.h>
- +#include <linux/delay.h>
- +#include "ralink_gdma.h"
- +#include "mt76xx_i2s.h"
- +#include "mt76xx_machine.h"
- +#if defined(CONFIG_SND_SOC_WM8960)
- +#include "../codecs/wm8960.h"
- +#endif
- +
- +#define I2C_AUDIO_DEV_ID (0)
- +/****************************/
- +/*FUNCTION DECLRATION */
- +/****************************/
- +extern unsigned long i2s_codec_12p288Mhz[11];
- +extern unsigned long i2s_codec_12Mhz[11];
- +
- +
- +static int mt76xx_codec_clock_hwparams(struct snd_pcm_substream *substream,\
- + struct snd_pcm_hw_params *params);
- +static int mt76xx_codec_startup(struct snd_pcm_substream *substream);
- +static int mt76xx_codec_init(struct snd_soc_pcm_runtime *rtd);
- +extern struct snd_soc_dai_driver mt76xx_i2s_dai;
- +extern struct snd_soc_platform_driver mt76xx_soc_platform;
- +struct platform_device *mt76xx_audio_device;
- +
- +#if defined(CONFIG_SND_SOC_WM8960)
- +extern struct snd_soc_dai wm8960_dai;
- +extern struct snd_soc_codec_device soc_codec_dev_wm8960;
- +#endif
- +
- +static struct snd_soc_ops mtk_audio_ops = {
- + .hw_params = mt76xx_codec_clock_hwparams,
- + .startup = mt76xx_codec_startup,
- +};
- +
- +static struct snd_soc_dai_link mtk_audio_dai = {
- + .name = "mtk_dai",
- + .stream_name = "WMserious PCM",
- + .cpu_dai_name = "mt76xx-i2s",
- + .codec_dai_name = "wm8960-hifi",
- + .codec_name = "wm8960.0-001a",
- + .platform_name = "mt76xx-pcm",
- + .ignore_pmdown_time = true,
- + .init = mt76xx_codec_init,
- + .ops = &mtk_audio_ops,
- +};
- +
- +static struct snd_soc_card mtk_audio_card = {
- + .name = "MTK APSoC I2S",
- + .owner = THIS_MODULE,
- + .dai_link = &mtk_audio_dai,//I2S/Codec
- + .num_links = 1,
- +};
- +
- +static int mt76xx_codec_clock_hwparams(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params)
- +{
- + struct snd_soc_pcm_runtime *p = substream->private_data;
- + struct snd_soc_dai *codec_dai = p->codec_dai;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + i2s_config_type* rtd = runtime->private_data;
- + unsigned long data,index = 0;
- + unsigned long* pTable;
- + int mclk,ret,targetClk = 0;
- +
- + /*For duplex mode, avoid setting twice.*/
- + if((rtd->bRxDMAEnable == GDMA_I2S_EN) || (rtd->bTxDMAEnable == GDMA_I2S_EN))
- + return 0;
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- + mclk = 12000000;
- +#elif defined(CONFIG_I2S_MCLK_12P288MHZ)
- + mclk = 12288000;
- +#else
- + mclk = 12000000;
- +#endif
- + //snd_soc_dai_set_sysclk(codec_dai,0,mclk, SND_SOC_CLOCK_IN);
- +
- + switch(params_rate(params)){
- + case 8000:
- + index = 0;
- + targetClk = 12288000;
- + break;
- + case 12000:
- + index = 2;
- + targetClk = 12288000;
- + break;
- + case 16000:
- + index = 3;
- + targetClk = 12288000;
- + break;
- + case 24000:
- + index = 5;
- + targetClk = 12288000;
- + break;
- + case 32000:
- + index = 6;
- + targetClk = 12288000;
- + break;
- + case 48000:
- + index = 8;
- + targetClk = 12288000;
- + break;
- + case 11025:
- + index = 1;
- + targetClk = 11289600;
- + break;
- + case 22050:
- + index = 4;
- + targetClk = 11289600;
- + break;
- + case 44100:
- + index = 7;
- + targetClk = 11289600;
- + break;
- + case 88200:
- + index = 9;
- + targetClk = 11289600;
- + break;
- + case 96000:
- + index = 10;
- + targetClk = 11289600;
- + break;
- + default:
- + index = 7;
- + targetClk = 12288000;
- + //MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)params_rate(params), MIN_SRATE_HZ, MAX_SRATE_HZ);
- + break;
- + }
- +#if defined(CONFIG_SND_SOC_WM8960)
- + /*
- + * There is a fixed divide by 4 in the PLL and a selectable
- + * divide by N after the PLL which should be set to divide by 2 to meet this requirement.
- + * */
- + ret = snd_soc_dai_set_pll(codec_dai, 0, 0,mclk, targetClk*2);
- + /* From app notes: allow Vref to stabilize to reduce clicks */
- + if(rtd->slave_en){
- + //printk("WM8960 is in master mode\n");
- + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DCLKDIV, 0x1c4);
- + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_SYSCLKDIV, 0x5);
- + }
- +
- +#endif
- + if(!rtd->slave_en)
- + snd_soc_dai_set_fmt(codec_dai,SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF);
- + else{
- + snd_soc_dai_set_fmt(codec_dai,SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF);
- + }
- + mdelay(5);
- +
- +#if defined(CONFIG_SND_SOC_WM8960)
- +#if defined(CONFIG_I2S_MCLK_12MHZ)
- + pTable = i2s_codec_12Mhz;
- + data = pTable[index];
- +#else
- + pTable = i2s_codec_12p288Mhz;
- + data = pTable[index];
- +#endif
- + if(rtd->codec_pll_en)
- + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DACDIV, (data<<3)|0x5);
- + else
- + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DACDIV, (data<<3|0x4));
- +#endif
- +
- + return 0;
- +}
- +
- +static int mt76xx_codec_startup(struct snd_pcm_substream *substream)
- +{
- + //printk("******* %s *******\n", __func__);
- + return 0;
- +}
- +static int mt76xx_codec_init(struct snd_soc_pcm_runtime *rtd)
- +{
- +
- + //printk("******* %s *******\n", __func__);
- + return 0;
- +}
- +
- +static struct i2c_board_info i2c_board_info[] = {
- + {
- +#if defined(CONFIG_SND_SOC_WM8750)
- + I2C_BOARD_INFO("wm8750", (0x36 >> 1)),
- +#elif defined(CONFIG_SND_SOC_WM8960)
- + I2C_BOARD_INFO("codec_wm8960", (0x34)),
- + }, {
- + I2C_BOARD_INFO("wm8960", (0x34 >> 1)),
- +#endif
- + }
- +};
- +
- +static struct platform_device *soc_mtk_i2s_dev;
- +static struct platform_device *soc_mtk_pcm_dev;
- +
- +static int __init mt76xx_machine_init(void)
- +{
- + //struct snd_soc_device *socdev = &mtk_audio_devdata;
- + //struct i2c_adapter *adapter = NULL;
- + //struct i2c_client *client = NULL;
- + int ret = 0;
- + struct i2c_adapter *adapter = NULL;
- + struct i2c_client *client = NULL;
- +
- + adapter = i2c_get_adapter(I2C_AUDIO_DEV_ID);
- + if (!adapter)
- + return -ENODEV;
- + client = i2c_new_device(adapter, &i2c_board_info[0]);
- + if (!client)
- + return -ENODEV;
- + i2c_get_clientdata(client);
- +
- + client = i2c_new_device(adapter, &i2c_board_info[1]);
- + if (!client)
- + return -ENODEV;
- + i2c_get_clientdata(client);
- +
- + i2c_put_adapter(adapter);
- +
- + soc_mtk_i2s_dev =
- + platform_device_register_simple("mt76xx-i2s", -1, NULL, 0);
- + if (IS_ERR(soc_mtk_i2s_dev))
- + return PTR_ERR(soc_mtk_i2s_dev);
- +
- + soc_mtk_pcm_dev =
- + platform_device_register_simple("mt76xx-pcm", -1, NULL, 0);
- + if (IS_ERR(soc_mtk_pcm_dev))
- + return PTR_ERR(soc_mtk_pcm_dev);
- +
- + mt76xx_audio_device = platform_device_alloc("soc-audio",-1);
- + if (mt76xx_audio_device == NULL) {
- + ret = -ENOMEM;
- + goto err_device_alloc;
- + }
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- + platform_set_drvdata(mt76xx_audio_device, &mtk_audio_card);
- +#else
- + platform_set_drvdata(mt76xx_audio_device, &mtk_audio_devdata);
- + mtk_audio_devdata.dev = &mt76xx_audio_device->dev;
- +#endif
- +
- + /*Ralink I2S register process end*/
- + ret = platform_device_add(mt76xx_audio_device);
- + if (ret) {
- + printk("mtk audio device : platform_device_add failed (%d)\n",ret);
- + goto err_device_add;
- + }
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- +#else
- + snd_soc_register_dai(&mt76xx_i2s_dai);
- +#endif
- +
- + return 0;
- +
- +err_device_add:
- + if (mt76xx_audio_device!= NULL) {
- + platform_device_put(mt76xx_audio_device);
- + mt76xx_audio_device = NULL;
- + }
- +err_device_alloc:
- + return ret;
- +}
- +
- +
- +static void __exit mt76xx_machine_exit(void)
- +{
- +
- + platform_device_unregister(mt76xx_audio_device);
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20)
- + /* Do nothing */
- +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- + snd_soc_unregister_platform(&mt76xx_audio_device->dev);
- +#else
- + snd_soc_unregister_platform(&mt76xx_soc_platform);
- +#endif
- + platform_device_unregister(soc_mtk_i2s_dev);
- + platform_device_unregister(soc_mtk_pcm_dev);
- +
- + mt76xx_audio_device = NULL;
- +}
- +
- +//module_init(mt76xx_machine_init);
- +late_initcall(mt76xx_machine_init);
- +module_exit(mt76xx_machine_exit);
- +//EXPORT_SYMBOL_GPL(mt76xx_soc_platform);
- +MODULE_LICENSE("GPL");
- --- /dev/null
- +++ b/sound/soc/mtk/mt76xx_machine.h
- @@ -0,0 +1,21 @@
- +/*
- + * mtk_audio_device.h
- + *
- + * Created on: 2013/10/23
- + * Author: MTK04880
- + */
- +
- +#ifndef MT76XX_MACHINE_H_
- +#define MT76XX_MACHINE_H_
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/soc-dapm.h>
- +
- +#if 0
- +#ifdef CONFIG_I2S_MMAP
- +#undef CONFIG_I2S_MMAP
- +#endif
- +#endif
- +
- +#endif /* MT76XX_MACHINE_H_ */
- --- /dev/null
- +++ b/sound/soc/mtk/mt76xx_pcm.c
- @@ -0,0 +1,499 @@
- +/*
- + * mt76xx_pcm.c
- + *
- + * Created on: 2013/9/6
- + * Author: MTK04880
- + */
- +
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- +#include <linux/sched.h>
- +#endif
- +#include <linux/module.h>
- +#include <linux/kernel.h> /* printk() */
- +#include <linux/slab.h> /* kmalloc() */
- +#include <linux/fs.h> /* everything... */
- +#include <linux/errno.h> /* error codes */
- +#include <linux/types.h> /* size_t */
- +#include <linux/proc_fs.h>
- +#include <linux/fcntl.h> /* O_ACCMODE */
- +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
- +#include <asm/system.h> /* cli(), *_flags */
- +#endif
- +#include <asm/uaccess.h> /* copy_from/to_user */
- +#include <linux/interrupt.h>
- +#include <linux/mm.h>
- +#include <linux/dma-mapping.h>
- +#include <sound/core.h>
- +#include <linux/pci.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/soc-dapm.h>
- +#include <sound/initval.h>
- +#include "ralink_gdma.h"
- +#include "mt76xx_i2s.h"
- +
- +#define GDMA_PAGE_SIZE I2S_PAGE_SIZE
- +#define GDMA_PAGE_NUM MAX_I2S_PAGE
- +#define GDMA_TOTAL_PAGE_SIZE I2S_TOTAL_PAGE_SIZE
- +
- +dma_addr_t i2s_txdma_addr, i2s_rxdma_addr;
- +dma_addr_t i2s_mmap_addr[GDMA_PAGE_NUM*2];
- +
- +extern struct tasklet_struct i2s_tx_tasklet;
- +extern struct tasklet_struct i2s_rx_tasklet;
- +extern int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size);
- +extern void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config);
- +extern void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config);
- +
- +static int mt76xx_pcm_open(struct snd_pcm_substream *substream);
- +static int mt76xx_pcm_new(struct snd_soc_pcm_runtime *rtd);
- +static void mt76xx_pcm_free(struct snd_pcm *pcm);
- +static int mt76xx_pcm_close(struct snd_pcm_substream *substream);
- +static snd_pcm_uframes_t mt76xx_pcm_pointer(struct snd_pcm_substream *substream);
- +static int mt76xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
- +static int mt76xx_pcm_prepare(struct snd_pcm_substream *substream);
- +static int mt76xx_pcm_hw_params(struct snd_pcm_substream *substream,\
- + struct snd_pcm_hw_params *hw_params);
- +static int mt76xx_pcm_copy(struct snd_pcm_substream *substream, int channel,\
- + snd_pcm_uframes_t pos,void __user *buf, snd_pcm_uframes_t count);
- +static int mt76xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
- +static int mt76xx_pcm_hw_free(struct snd_pcm_substream *substream);
- +
- +static int mt76xx_pcm_free_dma_buffer(struct snd_pcm_substream *substream,int stream);
- +static int mt76xx_pcm_allocate_dma_buffer(struct snd_pcm_substream *substream,int stream);
- +
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,20)
- +static int mt76xx_platform_drv_probe(struct platform_device *pdev);
- +static int mt76xx_platform_drv_remove(struct platform_device *pdev);
- +#endif
- +
- +static const struct snd_pcm_hardware mt76xx_pcm_hwparam = {
- +#if defined(CONFIG_I2S_MMAP)
- + .info = (SNDRV_PCM_INFO_INTERLEAVED |
- + SNDRV_PCM_INFO_PAUSE |
- + SNDRV_PCM_INFO_RESUME |
- + SNDRV_PCM_INFO_MMAP |
- + SNDRV_PCM_INFO_MMAP_VALID),
- +#else
- + .info = (SNDRV_PCM_INFO_INTERLEAVED |
- + SNDRV_PCM_INFO_PAUSE |
- + SNDRV_PCM_INFO_RESUME),
- +#endif
- + .formats = SNDRV_PCM_FMTBIT_S16_LE,
- + .period_bytes_min = GDMA_PAGE_SIZE,
- + .period_bytes_max = GDMA_PAGE_SIZE,
- + .periods_min = 1,
- + .periods_max = GDMA_PAGE_NUM,
- + .buffer_bytes_max = GDMA_TOTAL_PAGE_SIZE,
- +};
- +
- +static struct snd_pcm_ops mt76xx_pcm_ops = {
- +
- + .open = mt76xx_pcm_open,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = mt76xx_pcm_hw_params,
- + .hw_free = mt76xx_pcm_hw_free,
- + .trigger = mt76xx_pcm_trigger,
- + .prepare = mt76xx_pcm_prepare,
- + .pointer = mt76xx_pcm_pointer,
- + .close = mt76xx_pcm_close,
- +#if defined(CONFIG_I2S_MMAP)
- + .mmap = mt76xx_pcm_mmap,
- +#endif
- + .copy = mt76xx_pcm_copy,
- +};
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
- +struct snd_soc_platform_driver mt76xx_soc_platform = {
- + .ops = &mt76xx_pcm_ops,
- + .pcm_new = mt76xx_pcm_new,
- + .pcm_free = mt76xx_pcm_free,
- +};
- +#else
- +struct snd_soc_platform mt76xx_soc_platform = {
- + .name = "mtk-dma",
- + .pcm_ops = &mt76xx_pcm_ops,
- + .pcm_new = mt76xx_pcm_new,
- + .pcm_free = mt76xx_pcm_free,
- +};
- +#endif
- +
- +static int mt76xx_pcm_close(struct snd_pcm_substream *substream){
- +
- + //printk("******* %s *********\n", __func__);
- + return 0;
- +}
- +
- +static snd_pcm_uframes_t mt76xx_pcm_pointer(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + i2s_config_type* rtd = runtime->private_data;
- + unsigned int offset = 0;
- + //int buff_frame_bond = bytes_to_frames(runtime, GDMA_PAGE_SIZE);
- + //printk("\n******* %s *********\n", __func__);
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + offset = bytes_to_frames(runtime, GDMA_PAGE_SIZE*rtd->tx_r_idx);
- + //printk("r:%d w:%d (%d) \n",rtd->tx_r_idx,rtd->tx_w_idx,(runtime->control->appl_ptr/buff_frame_bond)%GDMA_PAGE_NUM);
- + }
- + else{
- + offset = bytes_to_frames(runtime, GDMA_PAGE_SIZE*rtd->rx_w_idx);
- + //printk("w:%d r:%d appl_ptr:%x\n",rtd->rx_w_idx,rtd->rx_r_idx,(runtime->control->appl_ptr/buff_frame_bond)%GDMA_PAGE_NUM);
- + }
- + return offset;
- +}
- +
- +
- +static int mt76xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
- +{
- + int ret = 0;
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + //struct snd_pcm_runtime *runtime= substream->runtime;
- +
- + //printk("******* %s *********\n", __func__);
- +/* printk("trigger cmd:%s\n",(cmd==SNDRV_PCM_TRIGGER_START)?"START":\
- + (cmd==SNDRV_PCM_TRIGGER_RESUME)?"RESUME":\
- + (cmd==SNDRV_PCM_TRIGGER_PAUSE_RELEASE)?"PAUSE_RELEASE":\
- + (cmd==SNDRV_PCM_TRIGGER_STOP)?"STOP":\
- + (cmd==SNDRV_PCM_TRIGGER_SUSPEND)?"SUSPEND":\
- + (cmd==SNDRV_PCM_TRIGGER_PAUSE_PUSH)?"PAUSE_PUSH":"default");
- +*/
- + switch (cmd) {
- + case SNDRV_PCM_TRIGGER_START:
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + rtd->bTrigger[SNDRV_PCM_STREAM_PLAYBACK] = 1;
- + } else {
- + rtd->bTrigger[SNDRV_PCM_STREAM_CAPTURE] = 1;
- + }
- + break;
- + case SNDRV_PCM_TRIGGER_STOP:
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + rtd->bTrigger[SNDRV_PCM_STREAM_PLAYBACK] = 0;
- + } else {
- + rtd->bTrigger[SNDRV_PCM_STREAM_CAPTURE] = 0;
- + }
- + break;
- + case SNDRV_PCM_TRIGGER_RESUME:
- + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + rtd->tx_pause_en = 0;
- + } else {
- + rtd->rx_pause_en = 0;
- + }
- + break;
- +
- + case SNDRV_PCM_TRIGGER_SUSPEND:
- + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + rtd->tx_pause_en = 1;
- + } else {
- + rtd->rx_pause_en = 1;
- + }
- + break;
- + default:
- + ret = -EINVAL;
- + break;
- + }
- + return ret;
- +}
- +
- +static int mt76xx_pcm_copy(struct snd_pcm_substream *substream, int channel,\
- + snd_pcm_uframes_t pos,void __user *buf, snd_pcm_uframes_t count)
- +{
- + struct snd_pcm_runtime *runtime= substream->runtime;
- + i2s_config_type* rtd = runtime->private_data;
- + int tx_w_idx = 0;
- + int rx_r_idx = 0;
- + char *hwbuf = NULL;
- +
- + //printk("******* %s *********\n", __func__);
- + hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos);
- + //MSG("%s bur:%x\n",__func__,hwbuf);
- + //printk("hw_ptr:%d, buffer_size:%d, appl_prt:%d, boundary:%d\n",
- + // runtime->status->hw_ptr, runtime->buffer_size, runtime->control->appl_ptr, runtime->boundary);
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + rtd->tx_w_idx = (rtd->tx_w_idx+1)%MAX_I2S_PAGE;
- + tx_w_idx = rtd->tx_w_idx;
- + //printk("put TB[%d - %x] for user write\n",rtd->tx_w_idx,pos);
- + copy_from_user(rtd->pMMAPTxBufPtr[tx_w_idx], (char*)buf, I2S_PAGE_SIZE);
- + }
- + else{
- + rx_r_idx = rtd->rx_r_idx;
- + rtd->rx_r_idx = (rtd->rx_r_idx+1)%MAX_I2S_PAGE;
- + copy_to_user((char*)buf, rtd->pMMAPRxBufPtr[rx_r_idx], I2S_PAGE_SIZE);
- + }
- + return 0;
- +}
- +
- +static int mt76xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
- +{
- + int ret;
- + unsigned long size;
- +
- + size = vma->vm_end-vma->vm_start;
- + printk("******* %s: size :%lx end:%lx start:%lx *******\n", __func__,size,vma->vm_end,vma->vm_start);
- + ret = i2s_mmap_remap(vma, size);
- +
- + return ret;
- +}
- +
- +
- +static int mt76xx_pcm_prepare(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime= substream->runtime;
- + i2s_config_type *rtd = (i2s_config_type*)runtime->private_data;
- + //runtime->buffer_size = GDMA_PAGE_NUM*GDMA_PAGE_SIZE;
- + //runtime->boundary = (GDMA_PAGE_NUM*GDMA_PAGE_SIZE)/4;
- +
- + //printk("******* %s *******\n", __func__);
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + //printk("===== %s:%s:%d =====\n", __FILE__, __func__, __LINE__);
- + mt76xx_pcm_allocate_dma_buffer(substream,SNDRV_PCM_STREAM_PLAYBACK);
- +
- + if(! rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK]){
- + i2s_page_prepare(rtd,STREAM_PLAYBACK);
- + tasklet_init(&i2s_tx_tasklet, i2s_tx_task, (u32)rtd);
- + rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK] = 1;
- + gdma_unmask_handler(GDMA_I2S_TX0);
- + }
- + } else {
- + mt76xx_pcm_allocate_dma_buffer(substream,SNDRV_PCM_STREAM_CAPTURE);
- +
- + if(! rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE]){
- + i2s_page_prepare(rtd,STREAM_CAPTURE); /* TX:enLabel=1; RX:enLabel=2 */
- + tasklet_init(&i2s_rx_tasklet, i2s_rx_task, (u32)rtd);
- + rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE] = 1;
- + gdma_unmask_handler(GDMA_I2S_RX0);
- + }
- + }
- +
- + return 0;
- +}
- +
- +
- +static int mt76xx_pcm_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *hw_params)
- +{
- + /*struct snd_pcm_runtime *runtime = substream->runtime;
- + i2s_config_type *rtd = (i2s_config_type*)runtime->private_data;
- + */
- + int ret,i;
- + ret = i = 0;
- +
- + //printk("******* %s *******\n", __func__);
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + //i2s_page_prepare(rtd,STREAM_PLAYBACK);
- + } else {
- + //i2s_page_prepare(rtd,STREAM_CAPTURE);
- + }
- +
- + return ret;
- +}
- +
- +static int mt76xx_pcm_hw_free(struct snd_pcm_substream *substream)
- +{
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- + //struct snd_dma_buffer *buf = &substream->dma_buffer;
- +
- + //printk("******* %s *******\n", __func__);
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
- + if(rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK]){
- +
- + gdma_En_Switch(rtd,STREAM_PLAYBACK,GDMA_I2S_DIS);
- + i2s_tx_end_sleep_on(rtd);
- + tasklet_kill(&i2s_tx_tasklet);
- + i2s_tx_disable(rtd);
- + //mt76xx_pcm_free_dma_buffer(substream,substream->stream);
- + i2s_page_release(rtd,STREAM_PLAYBACK);
- + rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK] = 0;
- + }
- + mt76xx_pcm_free_dma_buffer(substream,substream->stream);
- + }
- + else{
- + if(rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE]){
- +
- + gdma_En_Switch(rtd,STREAM_CAPTURE,GDMA_I2S_DIS);
- + i2s_rx_end_sleep_on(rtd);
- + tasklet_kill(&i2s_rx_tasklet);
- + i2s_rx_disable(rtd);
- + //mt76xx_pcm_free_dma_buffer(substream,substream->stream);
- + i2s_page_release(rtd,STREAM_CAPTURE);
- + rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE] = 0;
- + }
- + mt76xx_pcm_free_dma_buffer(substream,substream->stream);
- + }
- + return 0;
- +}
- +
- +static int mt76xx_pcm_free_dma_buffer(struct snd_pcm_substream *substream,
- + int stream)
- +{
- +
- + //struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- + struct snd_dma_buffer *buf = &substream->dma_buffer;
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- +
- + //printk("******* %s *******\n", __func__);
- + if (!buf->area)
- + return 0;
- + if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + i2s_memPool_free(rtd,STREAM_PLAYBACK);
- + else
- + i2s_memPool_free(rtd,STREAM_CAPTURE);
- + buf->area = NULL;
- + snd_pcm_set_runtime_buffer(substream, NULL);
- + return 0;
- +}
- +
- +static int mt76xx_pcm_allocate_dma_buffer(struct snd_pcm_substream *substream,
- + int stream)
- +{
- + //struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- + struct snd_dma_buffer *buf = &substream->dma_buffer;
- + i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data;
- +
- + //printk("******* %s *******\n", __func__);
- + if(!buf->area){
- +#if defined(CONFIG_I2S_MMAP)
- + printk("\n############## MMAP ##############\n");
- + buf->dev.type = SNDRV_DMA_TYPE_DEV;
- +#else
- + buf->dev.type = SNDRV_DMA_TYPE_UNKNOWN;
- +#endif
- + buf->dev.dev = NULL;
- + buf->private_data = NULL;
- + if(stream == SNDRV_PCM_STREAM_PLAYBACK)
- + buf->area = i2s_memPool_Alloc(rtd,STREAM_PLAYBACK);
- + else
- + buf->area = i2s_memPool_Alloc(rtd,STREAM_CAPTURE);
- +
- + if (!buf->area)
- + return -ENOMEM;
- + buf->bytes = GDMA_TOTAL_PAGE_SIZE;
- +#if defined(CONFIG_I2S_MMAP)
- + buf->addr = i2s_mmap_phys_addr(rtd);
- +#endif
- + snd_pcm_set_runtime_buffer(substream, buf);
- + } else{
- + //printk("Buffer have been allocated!\n");
- + }
- +
- + return 0;
- +}
- +
- +static int mt76xx_pcm_open(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime= substream->runtime;
- + struct snd_dma_buffer *buf = &substream->dma_buffer;
- + int stream = substream->stream;
- + int ret = 0;
- +
- + //printk("******* %s *******\n", __func__);
- + snd_soc_set_runtime_hwparams(substream, &mt76xx_pcm_hwparam);
- + /* ensure that buffer size is a multiple of period size */
- + ret = snd_pcm_hw_constraint_integer(runtime,
- + SNDRV_PCM_HW_PARAM_PERIODS);
- + if (ret < 0)
- + goto out;
- +
- +#if 1
- + if(stream == SNDRV_PCM_STREAM_PLAYBACK){
- + ret = mt76xx_pcm_allocate_dma_buffer(substream,
- + SNDRV_PCM_STREAM_PLAYBACK);
- + }
- + else{
- + ret = mt76xx_pcm_allocate_dma_buffer(substream,
- + SNDRV_PCM_STREAM_CAPTURE);
- + }
- +#endif
- +
- + if (ret)
- + goto out;
- +
- + if(buf)
- + memset(buf->area,0,sizeof(I2S_PAGE_SIZE*MAX_I2S_PAGE));
- +
- + out:
- + return ret;
- +}
- +
- +
- +
- +static int mt76xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
- +{
- +// int ret = 0;
- +
- + //printk("******* %s *******\n", __func__);
- + return 0;
- +}
- +
- +static void mt76xx_pcm_free(struct snd_pcm *pcm)
- +{
- + /*struct snd_pcm_substream *substream;
- + struct snd_dma_buffer *buf;
- + i2s_config_type* rtd;
- + int stream;
- +*/
- + //printk("******* %s *******\n", __func__);
- + //return 0;
- +}
- +
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20)
- +static int mt76xx_platform_drv_probe(struct platform_device *pdev)
- +{
- + //printk("******* %s *******\n", __func__);
- + return snd_soc_register_platform(&pdev->dev, &mt76xx_soc_platform);
- +}
- +
- +static int mt76xx_platform_drv_remove(struct platform_device *pdev)
- +{
- + //printk("******* %s *******\n", __func__);
- + snd_soc_unregister_platform(&pdev->dev);
- + return 0;
- +}
- +
- +static struct platform_driver mt76xx_pcm_driver = {
- + .driver = {
- + .name = "mt76xx-pcm",
- + .owner = THIS_MODULE,
- + },
- +
- + .probe = mt76xx_platform_drv_probe,
- + .remove = mt76xx_platform_drv_remove,
- +};
- +
- +static int __init mt76xx_pcm_init(void)
- +{
- +
- + printk("******* %s *******\n", __func__);
- + return platform_driver_register(&mt76xx_pcm_driver);
- +}
- +
- +static void __exit mt76xx_pcm_exit(void)
- +{
- + platform_driver_unregister(&mt76xx_pcm_driver);
- +}
- +#else
- +static int __init mt76xx_pcm_init(void)
- +{
- +
- + printk("******* %s *******\n", __func__);
- + return snd_soc_register_platform(&mt76xx_soc_platform);
- +}
- +
- +static void __exit mt76xx_pcm_exit(void)
- +{
- + printk("******* %s *******\n", __func__);
- + snd_soc_unregister_platform(&mt76xx_soc_platform);
- +}
- +#endif
- +module_init(mt76xx_pcm_init);
- +module_exit(mt76xx_pcm_exit);
- +
- +MODULE_AUTHOR("Dora Chen");
- +MODULE_DESCRIPTION("MTK APSoC I2S DMA driver");
- +MODULE_LICENSE("GPL");
- +
- --- /dev/null
- +++ b/sound/soc/mtk/ralink_gdma.c
- @@ -0,0 +1,918 @@
- +/*
- + ***************************************************************************
- + * Ralink Tech Inc.
- + * 5F., No.36, Taiyuan St., Jhubei City,
- + * Hsinchu County 302,
- + * Taiwan, R.O.C.
- + *
- + * (c) Copyright, Ralink Technology, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 675 Mass Ave, Cambridge, MA 02139, USA.
- + *
- + *
- + ***************************************************************************
- + *
- + Module Name:
- + ralink_gdma.c
- +
- + Abstract:
- +
- + Revision History:
- + Who When What
- + -------- ---------- ----------------------------------------------
- + Name Date Modification logs
- + Steven Liu 2009-03-24 Support RT3883
- + *
- + */
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/interrupt.h>
- +#include <linux/fs.h>
- +#if defined (CONFIG_MIPS)
- + #include <asm/uaccess.h>
- + #include <asm/addrspace.h>
- +#endif
- +
- +#include "ralink_gdma.h"
- +
- +/*
- + * RT305x:
- + * Ch0 : Pcm0_Rx0 | Pcm0_Rx0 | ALL
- + * Ch1 : Pcm0_Rx1 | Pcm0_Rx1 | ALL
- + * Ch2 : Pcm0_Tx0 | Pcm0_Tx0 | ALL
- + * Ch3 : Pcm0_Tx1 | Pcm0_Tx1 | ALL
- + * Ch4 : Pcm1_Rx0 | I2S_Tx0 | ALL
- + * Ch5 : Pcm1_Rx1 | I2S_Tx1 | ALL
- + * Ch6 : Pcm1_Tx0 | ALL | ALL
- + * Ch7 : Pcm1_Tx1 | ALL | ALL
- + *
- + * RT3883:
- + * Ch0 : Pcm0_Rx0 | Pcm0_Rx0 | ALL
- + * Ch1 : Pcm0_Rx1 | Pcm0_Rx1 | ALL
- + * Ch2 : Pcm0_Tx0 | Pcm0_Tx0 | ALL
- + * Ch3 : Pcm0_Tx1 | Pcm0_Tx1 | ALL
- + * Ch4 : Pcm1_Rx0 | I2S_Tx0 | ALL
- + * Ch5 : Pcm1_Rx1 | I2S_Tx1 | ALL
- + * Ch6 : Pcm1_Tx0 | I2S_Rx0 | ALL
- + * Ch7 : Pcm1_Tx1 | I2S_Rx1 | ALL
- + * Ch8 : ALL | ALL | ALL
- + * Ch9 : ALL | ALL | ALL
- + * Ch10 : ALL | ALL | ALL
- + * Ch11 : ALL | ALL | ALL
- + * Ch12 : ALL | ALL | ALL PCI TX
- + * Ch13 : ALL | ALL | ALL PCI RX
- + * Ch14 : ALL | ALL | ALL
- + * Ch15 : ALL | ALL | ALL
- + *
- + */
- +
- +spinlock_t gdma_lock;
- +spinlock_t gdma_lock_mem;
- +spinlock_t gdma_int_lock;
- +void (*GdmaDoneIntCallback[MAX_GDMA_CHANNEL])(uint32_t);
- +void (*GdmaUnMaskIntCallback[MAX_GDMA_CHANNEL])(uint32_t);
- +
- +
- +/**
- + * @brief Get free GDMA channel
- + *
- + * @param ChNum GDMA channel number
- + * @retval 1 channel is available
- + * @retval 0 channels are all busy
- + */
- +int _GdmaGetFreeCh(uint32_t *ChNum)
- +{
- + unsigned long flags;
- + uint32_t Data=0;
- + uint32_t Ch=0;
- +#if defined (CONFIG_GDMA_DEBUG)
- + static uint32_t Ch_RR=0;
- +#endif
- +
- + spin_lock_irqsave(&gdma_lock, flags);
- +
- +#if defined (CONFIG_GDMA_PCM_ONLY)
- +#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + for(Ch=14; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 14~max_channe, channel 0~13 be usedl
- +#else
- + for(Ch=MAX_GDMA_CHANNEL; Ch<MAX_GDMA_CHANNEL;Ch++) //no free channel
- +#endif
- +#elif defined (CONFIG_GDMA_PCM_I2S_OTHERS)
- +#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + for(Ch=14; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 14~max_channe, channel 0~13 be usedl
- +#else
- + for(Ch=6; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 6~max_channel
- +#endif
- +#elif defined (CONFIG_GDMA_EVERYBODY)
- + for(Ch=0; Ch<MAX_GDMA_CHANNEL;Ch++) //all channel
- +#elif defined (CONFIG_GDMA_DEBUG)
- + for(Ch=(Ch_RR++)%MAX_GDMA_CHANNEL; Ch<MAX_GDMA_CHANNEL;Ch++) //round robin
- +#endif
- + {
- + Data=GDMA_READ_REG(GDMA_CTRL_REG(Ch));
- +
- + /* hardware will reset this bit if transaction is done.
- + * It means channel is free */
- + if((Data & (0x01<<CH_EBL_OFFSET))==0) {
- + *ChNum = Ch;
- + spin_unlock_irqrestore(&gdma_lock, flags);
- + return 1; //Channel is free
- + }
- + }
- +
- + spin_unlock_irqrestore(&gdma_lock, flags);
- + return 0; // Channels are all busy
- +
- +}
- +
- +/**
- + * @brief Set channel is masked
- + *
- + * When channel is masked, the GDMA transaction will stop.
- + * When GDMA controller comes back from another channel (chain feature)
- + *
- + * >> Channel Mask=0: It's strange, and turns on related bit in GDMA interrupt
- + * status register (16:23 Unmasked)
- + *
- + * >> Channel Mask=1: It'll start GDMA transation, and clear this bit.
- + *
- + * @param ChNum GDMA channel number
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaMaskChannel(uint32_t ChNum)
- +{
- + uint32_t Data=0;
- +
- + Data=GDMA_READ_REG(GDMA_CTRL_REG1(ChNum));
- + Data |= ( 0x01 << CH_MASK_OFFSET);
- + GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data);
- + GDMA_PRINT("%s: Write %0X to %X\n", __FUNCTION__, Data, GDMA_CTRL_REG1(ChNum));
- +
- + return 1;
- +}
- +
- +/**
- + * @brief Set channel is unmasked
- + *
- + * You can unmask the channel to start GDMA transaction.
- + *
- + * When GDMA controller comes back from another channel (chain feature)
- + *
- + * >> Channel Mask=0: It's strange, and turns on related bit in GDMA interrupt
- + * status register (16:23 Unmasked)
- + *
- + * >> Channel Mask=1: It'll start GDMA transation, and clear this bit.
- + *
- + * @param ChNum GDMA channel number
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaUnMaskChannel(uint32_t ChNum)
- +{
- + uint32_t Data=0;
- +
- + Data=GDMA_READ_REG(GDMA_CTRL_REG1(ChNum));
- + Data &= ~( 0x01 << CH_MASK_OFFSET);
- + GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data);
- + GDMA_PRINT("%s: Write %0X to %X\n", __FUNCTION__, Data, GDMA_CTRL_REG1(ChNum));
- +
- + return 1;
- +}
- +
- +/**
- + * @brief Insert new GDMA entry to start GDMA transaction
- + *
- + * @param ChNum GDMA channel number
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaReqQuickIns(uint32_t ChNum)
- +{
- + uint32_t Data=0;
- +
- + //Mask Channel
- + Data = GDMA_READ_REG(GDMA_CTRL_REG1(ChNum));
- + Data |= ( 0x1 << CH_MASK_OFFSET);
- + GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data);
- +
- + //Channel Enable
- + Data = GDMA_READ_REG(GDMA_CTRL_REG(ChNum));
- + Data |= (0x01<<CH_EBL_OFFSET);
- + GDMA_WRITE_REG(GDMA_CTRL_REG(ChNum), Data);
- +
- + return 1;
- +
- +}
- +
- +int _GdmaReqEntryIns(GdmaReqEntry *NewEntry)
- +{
- + uint32_t Data=0;
- +
- + GDMA_PRINT("== << GDMA Control Reg (Channel=%d) >> ===\n", NewEntry->ChNum);
- + GDMA_PRINT(" Channel Source Addr = %x \n", NewEntry->Src);
- + GDMA_PRINT(" Channel Dest Addr = %x \n", NewEntry->Dst);
- + GDMA_PRINT(" Transfer Count=%d\n", NewEntry->TransCount);
- + GDMA_PRINT(" Source DMA Req= DMA_REQ%d\n", NewEntry->SrcReqNum);
- + GDMA_PRINT(" Dest DMA Req= DMA_REQ%d\n", NewEntry->DstReqNum);
- + GDMA_PRINT(" Source Burst Mode=%s\n", NewEntry->SrcBurstMode ? "Fix" : "Inc");
- + GDMA_PRINT(" Dest Burst Mode=%s\n", NewEntry->DstBurstMode ? "Fix" : "Inc");
- + GDMA_PRINT(" Burst Size=%s\n", NewEntry->BurstSize ==0 ? "1 transfer" : \
- + NewEntry->BurstSize ==1 ? "2 transfer" :\
- + NewEntry->BurstSize ==2 ? "4 transfer" :\
- + NewEntry->BurstSize ==3 ? "8 transfer" :\
- + NewEntry->BurstSize ==4 ? "16 transfer" :\
- + "Error");
- + GDMA_PRINT(" Hardware/Software Mode = %s\n", NewEntry->SoftMode ?
- + "Soft" : "Hw");
- + GDMA_PRINT("== << GDMA Control Reg1 (Channel=%d) >> =\n", NewEntry->ChNum);
- + GDMA_PRINT("Channel Done Interrput=%s\n", (NewEntry->DoneIntCallback!=NULL) ?
- + "Enable" : "Disable");
- + GDMA_PRINT("Channel Unmasked Int=%s\n", (NewEntry->UnMaskIntCallback!=NULL) ?
- + "Enable" : "Disable");
- +#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3883)
- + GDMA_PRINT("Coherent Interrupt =%s\n", (NewEntry->CoherentIntEbl==1)?
- + "Enable" : "Disable");
- +#endif
- + GDMA_PRINT("Next Unmasked Channel=%d\n", NewEntry->NextUnMaskCh);
- + GDMA_PRINT("Channel Mask=%d\n", NewEntry->ChMask);
- + GDMA_PRINT("========================================\n");
- +
- + GDMA_WRITE_REG(GDMA_SRC_REG(NewEntry->ChNum), NewEntry->Src);
- + GDMA_PRINT("SrcAddr: Write %0X to %X\n", \
- + NewEntry->Src, GDMA_SRC_REG(NewEntry->ChNum));
- +
- + GDMA_WRITE_REG(GDMA_DST_REG(NewEntry->ChNum), NewEntry->Dst);
- + GDMA_PRINT("DstAddr: Write %0X to %X\n", \
- + NewEntry->Dst, GDMA_DST_REG(NewEntry->ChNum));
- +
- + Data |= ( (NewEntry->NextUnMaskCh) << NEXT_UNMASK_CH_OFFSET);
- + Data |= ( NewEntry->ChMask << CH_MASK_OFFSET);
- +#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3883)
- + Data |= ( NewEntry->CoherentIntEbl << COHERENT_INT_EBL_OFFSET);
- +#endif
- +
- + if(NewEntry->UnMaskIntCallback!=NULL) {
- + Data |= (0x01<<CH_UNMASKINT_EBL_OFFSET);
- + GdmaUnMaskIntCallback[NewEntry->ChNum] = NewEntry->UnMaskIntCallback;
- + }
- +
- +#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + Data |= (NewEntry->SrcReqNum << SRC_DMA_REQ_OFFSET);
- + Data |= (NewEntry->DstReqNum << DST_DMA_REQ_OFFSET);
- +#endif
- +
- + GDMA_WRITE_REG(GDMA_CTRL_REG1(NewEntry->ChNum), Data);
- + GDMA_PRINT("CTRL1: Write %08X to %8X\n", Data, GDMA_CTRL_REG1(NewEntry->ChNum));
- +
- + Data = ((NewEntry->TransCount) << TRANS_CNT_OFFSET);
- +#if defined (CONFIG_RALINK_RT3052)
- + Data |= (NewEntry->SrcReqNum << SRC_DMA_REQ_OFFSET);
- + Data |= (NewEntry->DstReqNum << DST_DMA_REQ_OFFSET);
- +#endif
- + Data |= (NewEntry->SrcBurstMode << SRC_BRST_MODE_OFFSET);
- + Data |= (NewEntry->DstBurstMode << DST_BRST_MODE_OFFSET);
- + Data |= (NewEntry->BurstSize << BRST_SIZE_OFFSET);
- +
- + if(NewEntry->DoneIntCallback!=NULL) {
- + Data |= (0x01<<CH_DONEINT_EBL_OFFSET);
- + GdmaDoneIntCallback[NewEntry->ChNum] = NewEntry->DoneIntCallback;
- + }
- +
- + if(NewEntry->SoftMode) {
- + Data |= (0x01<<MODE_SEL_OFFSET);
- + }
- +
- + Data |= (0x01<<CH_EBL_OFFSET);
- + GDMA_WRITE_REG(GDMA_CTRL_REG(NewEntry->ChNum), Data);
- + //GDMA_READ_REG(GDMA_CTRL_REG(NewEntry->ChNum));
- + GDMA_PRINT("CTRL: Write %08X to %8X\n", Data, GDMA_CTRL_REG(NewEntry->ChNum));
- + //if there is no interrupt handler, this function will
- + //return 1 until GDMA done.
- + if(NewEntry->DoneIntCallback==NULL) {
- + //wait for GDMA processing done
- +#if defined (CONFIG_RALINK_RT3052)
- + while((GDMA_READ_REG(RALINK_GDMAISTS) &
- + (0x1<<NewEntry->ChNum))==0);
- + //write 1 clear
- + GDMA_WRITE_REG(RALINK_GDMAISTS, 1<< NewEntry->ChNum);
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + while((GDMA_READ_REG(RALINK_GDMA_DONEINT) &
- + (0x1<<NewEntry->ChNum))==0);
- + //write 1 clear
- + GDMA_WRITE_REG(RALINK_GDMA_DONEINT, 1<< NewEntry->ChNum);
- +#endif
- + }
- +
- + return 1;
- +
- +}
- +
- +#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +/**
- + * @brief Start GDMA transaction for sending data to SPI
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- +
- + * @param TransCount data length
- + * @param *DoneIntCallback callback function when transcation is done
- + * @param *UnMaskIntCallback callback func when ch mask field is incorrect
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaSpiTx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- +
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=INC_MODE;
- + Entry.DstBurstMode=FIX_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.SrcReqNum=DMA_MEM_REQ;
- + Entry.DstReqNum=DMA_SPI_TX_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0;
- + Entry.ChMask=0;
- + Entry.CoherentIntEbl=0;
- +
- + //enable chain feature
- + Entry.ChNum = GDMA_SPI_TX;
- + Entry.NextUnMaskCh = GDMA_SPI_TX;
- +
- + return _GdmaReqEntryIns(&Entry);
- +}
- +
- +int GdmaSpiRx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- +
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=FIX_MODE;
- + Entry.DstBurstMode=INC_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.SrcReqNum=DMA_SPI_RX_REQ;
- + Entry.DstReqNum=DMA_MEM_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0;
- + Entry.ChMask=0;
- + Entry.CoherentIntEbl=1;
- +
- +
- + //enable chain feature
- + Entry.ChNum=GDMA_SPI_RX;
- + Entry.NextUnMaskCh=GDMA_SPI_RX;
- +
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +}
- +#endif
- +
- +
- +/**
- + * @brief Start GDMA transaction for sending data to I2S
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- + * @param TxNo I2S Tx number
- + * @param TransCount data length
- + * @param *DoneIntCallback callback function when transcation is done
- + * @param *UnMaskIntCallback callback func when ch mask field is incorrect
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaI2sTx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint8_t TxNo,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- +
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=INC_MODE;
- + Entry.DstBurstMode=FIX_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.SrcReqNum=DMA_MEM_REQ;
- + Entry.DstReqNum=DMA_I2S_TX_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0;
- + Entry.ChMask=1;
- + Entry.CoherentIntEbl=0;
- +
- + if(TxNo==0) { //TX0
- + //enable chain feature
- + Entry.ChNum=GDMA_I2S_TX0;
- + Entry.NextUnMaskCh= (TransCount==4) ? GDMA_I2S_TX0 : GDMA_I2S_TX1;
- + }else if(TxNo==1) { //TX1
- + //enable chain feature
- + Entry.ChNum=GDMA_I2S_TX1;
- + Entry.NextUnMaskCh= (TransCount==4) ? GDMA_I2S_TX1 : GDMA_I2S_TX0;
- + }else {
- + GDMA_PRINT("I2S Tx Number %x is invalid\n", TxNo);
- + return 0;
- + }
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +}
- +
- +
- +#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +/**
- + * @brief Start GDMA transaction for receiving data to I2S
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- + * @param TxNo I2S Tx number
- + * @param TransCount data length
- + * @param *DoneIntCallback callback function when transcation is done
- + * @param *UnMaskIntCallback callback func when ch mask field is incorrect
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaI2sRx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint8_t RxNo,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=FIX_MODE;
- + Entry.DstBurstMode=INC_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.SrcReqNum=DMA_I2S_RX_REQ;
- + Entry.DstReqNum=DMA_MEM_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0;
- + Entry.ChMask=1;
- + Entry.CoherentIntEbl=1;
- +
- + if(RxNo==0) { //RX0
- + //enable chain feature
- + Entry.ChNum=GDMA_I2S_RX0;
- + Entry.NextUnMaskCh=(TransCount==4) ? GDMA_I2S_RX0 : GDMA_I2S_RX1;
- + }else if(RxNo==1) { //RX1
- + //enable chain feature
- + Entry.ChNum=GDMA_I2S_RX1;
- + Entry.NextUnMaskCh=(TransCount==4) ? GDMA_I2S_RX1 : GDMA_I2S_RX0;
- + }else {
- + GDMA_PRINT("I2S Rx Number %x is invalid\n", RxNo);
- + return 0;
- + }
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +}
- +
- +#endif
- +
- +/**
- + * @brief Start GDMA transaction for receiving data from PCM
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- + * @param TransCount data length
- + * @param PcmNo PCM channel
- + * @param RxNo PCM Rx number
- + * @param *DoneIntCallback callback function when transcation is done
- + * @param *UnMaskIntCallback callback func when ch mask field is incorrect
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaPcmRx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint8_t PcmNo,
- + uint8_t RxNo,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- +
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=FIX_MODE;
- + Entry.DstBurstMode=INC_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.DstReqNum=DMA_MEM_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0;
- + Entry.ChMask=1;
- + Entry.CoherentIntEbl=1;
- +
- + if(RxNo > 2) {
- + GDMA_PRINT("PCM Rx Number %x is invalid\n", RxNo);
- + return 0;
- + }
- +
- + switch(PcmNo)
- + {
- + case 0:
- + Entry.SrcReqNum=DMA_PCM_RX0_REQ;
- + break;
- + case 1:
- + Entry.SrcReqNum=DMA_PCM_RX1_REQ;
- + break;
- +#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + case 2:
- + Entry.SrcReqNum=DMA_PCM_RX2_REQ;
- + break;
- + case 3:
- + Entry.SrcReqNum=DMA_PCM_RX3_REQ;
- + break;
- +#endif
- + default:
- + GDMA_PRINT("PCM Channel %x is invalid\n", PcmNo);
- + return 0;
- + }
- + Entry.ChNum=GDMA_PCM_RX(PcmNo,RxNo);
- + Entry.NextUnMaskCh=GDMA_PCM_RX(PcmNo,1-RxNo);
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +}
- +
- +/**
- + * @brief Start GDMA transaction for sending data to PCM
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- + * @param TransCount data length
- + * @param PcmNo PCM channel
- + * @param TxNo PCM Tx number
- + * @param *DoneIntCallback callback func when transcation is done
- + * @param *UnMaskIntCallback callback func when ch mask field is incorrect
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaPcmTx(
- + uint32_t Src,
- + uint32_t Dst,
- + uint8_t PcmNo,
- + uint8_t TxNo,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data)
- + )
- +{
- + GdmaReqEntry Entry;
- +
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=INC_MODE;
- + Entry.DstBurstMode=FIX_MODE;
- + Entry.BurstSize=BUSTER_SIZE_4B;
- + Entry.SrcReqNum=DMA_MEM_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=UnMaskIntCallback;
- + Entry.SoftMode=0; //Hardware Mode
- + Entry.ChMask=1;
- + Entry.CoherentIntEbl=0;
- +
- + if(TxNo > 2) {
- + GDMA_PRINT("PCM Tx Number %x is invalid\n", TxNo);
- + return 0;
- + }
- + switch(PcmNo)
- + {
- + case 0:
- + Entry.DstReqNum=DMA_PCM_TX0_REQ;
- + break;
- + case 1:
- + Entry.DstReqNum=DMA_PCM_TX1_REQ;
- + break;
- +#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + case 2:
- + Entry.DstReqNum=DMA_PCM_TX2_REQ;
- + break;
- + case 3:
- + Entry.DstReqNum=DMA_PCM_TX3_REQ;
- + break;
- +#endif
- + default:
- + GDMA_PRINT("PCM Channel %x is invalid\n", PcmNo);
- + return 0;
- + }
- + Entry.ChNum=GDMA_PCM_TX(PcmNo,TxNo);
- + Entry.NextUnMaskCh=GDMA_PCM_TX(PcmNo,1-TxNo);
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +}
- +
- +
- +/**
- + * @brief Start GDMA transaction for memory to memory copy
- + *
- + * @param *Src source address
- + * @param *Dst destination address
- + * @param TransCount data length
- + * @param *DoneIntCallback callback function when transcation is done
- + * @retval 1 success
- + * @retval 0 fail
- + */
- +int GdmaMem2Mem(
- + uint32_t Src,
- + uint32_t Dst,
- + uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data)
- + )
- +
- +{
- +
- + GdmaReqEntry Entry;
- + #if defined (CONFIG_MIPS)
- + Entry.Src= (Src & 0x1FFFFFFF);
- + Entry.Dst= (Dst & 0x1FFFFFFF);
- + #else
- + Entry.Src= Src;
- + Entry.Dst= Dst;
- + #endif
- +
- + //Entry.Src= virt_to_phys(Src);
- + //Entry.Dst= virt_to_phys(Dst);
- +
- +
- +
- + Entry.TransCount = TransCount;
- + Entry.SrcBurstMode=INC_MODE;
- + Entry.DstBurstMode=INC_MODE;
- + Entry.BurstSize=BUSTER_SIZE_64B;
- + Entry.SrcReqNum=DMA_MEM_REQ;
- + Entry.DstReqNum=DMA_MEM_REQ;
- + Entry.DoneIntCallback=DoneIntCallback;
- + Entry.UnMaskIntCallback=NULL;
- + Entry.SoftMode=1;
- + Entry.ChMask=0;
- +
- + Entry.CoherentIntEbl=1;
- +
- + //No reserved channel for Memory to Memory GDMA,
- + //get free channel on demand
- + if(!_GdmaGetFreeCh(&Entry.ChNum)) {
- + GDMA_PRINT("GDMA Channels are all busy\n");
- + return 0;
- + }
- +
- +
- + //set next channel to their own channel
- + //to disable chain feature
- + Entry.NextUnMaskCh= Entry.ChNum;
- + //printk ("ChNum = %d\n", Entry.ChNum);
- + //set next channel to another channel
- + //to enable chain feature
- + //Entry.NextUnMaskCh= (Entry.ChNum+1) % MAX_GDMA_CHANNEL;
- +
- + return _GdmaReqEntryIns(&Entry);
- +
- +
- +}
- +
- +/**
- + * @brief GDMA interrupt handler
- + *
- + * When GDMA transcation is done, call related handler
- + * to do the remain job.
- + *
- + */
- +irqreturn_t GdmaIrqHandler(
- + int irq,
- + void *irqaction
- + )
- +{
- +
- + u32 Ch=0;
- + unsigned long flags;
- +#if defined (CONFIG_RALINK_RT3052)
- + u32 GdmaUnMaskStatus=GDMA_READ_REG(RALINK_GDMAISTS) & 0xFF0000;
- + u32 GdmaDoneStatus=GDMA_READ_REG(RALINK_GDMAISTS) & 0xFF;
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + u32 GdmaUnMaskStatus=GDMA_READ_REG(RALINK_GDMA_UNMASKINT);
- + u32 GdmaDoneStatus=GDMA_READ_REG(RALINK_GDMA_DONEINT);
- +#endif
- + //printk("********GDMA Interrupt*******************\n");
- +
- + //GDMA_PRINT("========================================\n");
- + //GDMA_PRINT("GdmaUnMask Interrupt=%x\n",GdmaUnMaskStatus);
- + //GDMA_PRINT("GdmaDone Interrupt=%x\n",GdmaDoneStatus);
- + //GDMA_PRINT("========================================\n");
- +
- + spin_lock_irqsave(&gdma_int_lock, flags);
- +
- + //write 1 clear
- +#if defined (CONFIG_RALINK_RT3052)
- + GDMA_WRITE_REG(RALINK_GDMAISTS, GdmaUnMaskStatus);
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + GDMA_WRITE_REG(RALINK_GDMA_UNMASKINT, GdmaUnMaskStatus);
- +#endif
- +
- + //UnMask error
- + for(Ch=0;Ch<MAX_GDMA_CHANNEL;Ch++) {
- +
- + if(GdmaUnMaskStatus & (0x1 << (UNMASK_INT_STATUS(Ch))) ) {
- + if(GdmaUnMaskIntCallback[Ch] != NULL) {
- + GdmaUnMaskIntCallback[Ch](Ch);
- + // printk("GdmaUnMaskIntCallback \n");
- + }
- + }
- + }
- +
- + //write 1 clear
- +#if defined (CONFIG_RALINK_RT3052)
- + GDMA_WRITE_REG(RALINK_GDMAISTS, GdmaDoneStatus);
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + GDMA_WRITE_REG(RALINK_GDMA_DONEINT, GdmaDoneStatus);
- +#endif
- +
- + //printk("interrupt status = %x \n", GdmaDoneStatus);
- + //processing done
- + for(Ch=0;Ch<MAX_GDMA_CHANNEL;Ch++) {
- + if(GdmaDoneStatus & (0x1<<Ch)) {
- + if(GdmaDoneIntCallback[Ch] != NULL) {
- + //printk("*************Interrupt Ch=%d***********\n", Ch);
- + GdmaDoneIntCallback[Ch](Ch);
- + }
- + }
- + }
- +
- +//printk("interrupt status clear = %x \n", GDMA_READ_REG(RALINK_GDMA_DONEINT));
- + spin_unlock_irqrestore(&gdma_int_lock, flags);
- +
- + return IRQ_HANDLED;
- +
- +}
- +
- +static int RalinkGdmaInit(void)
- +{
- +
- + uint32_t Ret=0;
- + uint32_t val = 0;
- + printk("Enable Ralink GDMA Controller Module \n");
- +#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + printk("GDMA IP Version=%d\n", GET_GDMA_IP_VER);
- +#endif
- +spin_lock_init(&gdma_int_lock);
- +spin_lock_init(&gdma_lock);
- +//spin_lock_init(&gdma_lock_mem);
- +
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- + #if defined (CONFIG_MIPS)
- + Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \
- + IRQF_DISABLED, "Ralink_DMA", NULL);
- + #else
- + Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \
- + IRQF_TRIGGER_LOW, "Ralink_DMA", NULL);
- + #endif
- +#else
- + Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \
- + SA_INTERRUPT, "Ralink_DMA", NULL);
- +#endif
- +
- +/*
- + Ret = request_irq(131, GdmaIrqHandler, \
- + IRQF_TRIGGER_LOW, "Ralink_DMA", NULL);
- + */
- + if(Ret){
- + GDMA_PRINT("IRQ %d is not free.\n", SURFBOARDINT_DMA);
- + return 1;
- + }
- +
- +#if defined (CONFIG_MIPS)
- + //Enable GDMA interrupt
- + val = le32_to_cpu(*(volatile u32 *)(RALINK_REG_INTENA));
- + val |= RALINK_INTCTL_DMA;
- + GDMA_WRITE_REG(RALINK_REG_INTENA, val);
- +#endif
- +
- + //Channel0~Channel7 are round-robin
- +#if defined (CONFIG_RALINK_RT3052)
- + GDMA_WRITE_REG(RALINK_GDMAGCT, 0x01);
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + GDMA_WRITE_REG(RALINK_GDMA_GCT, 0x01);
- +#else
- +#error Please Choose System Type
- +#endif
- +
- + return 0;
- +}
- +
- +static void __exit RalinkGdmaExit(void)
- +{
- +
- + printk("Disable Ralink GDMA Controller Module\n");
- +#if defined (CONFIG_MIPS)
- + //Disable GDMA interrupt
- + GDMA_WRITE_REG(RALINK_REG_INTDIS, RALINK_INTCTL_DMA);
- +#endif
- + free_irq(SURFBOARDINT_DMA, NULL);
- +}
- +
- +module_init(RalinkGdmaInit);
- +module_exit(RalinkGdmaExit);
- +
- +EXPORT_SYMBOL(GdmaI2sRx);
- +EXPORT_SYMBOL(GdmaI2sTx);
- +EXPORT_SYMBOL(GdmaPcmRx);
- +EXPORT_SYMBOL(GdmaPcmTx);
- +#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +EXPORT_SYMBOL(GdmaSpiRx);
- +EXPORT_SYMBOL(GdmaSpiTx);
- +#endif
- +EXPORT_SYMBOL(GdmaMem2Mem);
- +EXPORT_SYMBOL(GdmaReqQuickIns);
- +EXPORT_SYMBOL(GdmaMaskChannel);
- +EXPORT_SYMBOL(GdmaUnMaskChannel);
- +
- +
- +MODULE_DESCRIPTION("Ralink SoC GDMA Controller API Module");
- +MODULE_AUTHOR("Steven Liu <steven_liu@ralinktech.com.tw>");
- +MODULE_LICENSE("GPL");
- +MODULE_VERSION(MOD_VERSION);
- --- /dev/null
- +++ b/sound/soc/mtk/ralink_gdma.h
- @@ -0,0 +1,326 @@
- +/*
- + ***************************************************************************
- + * Ralink Tech Inc.
- + * 5F., No.36, Taiyuan St., Jhubei City,
- + * Hsinchu County 302,
- + * Taiwan, R.O.C.
- + *
- + * (c) Copyright, Ralink Technology, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 675 Mass Ave, Cambridge, MA 02139, USA.
- + *
- + *
- + ***************************************************************************
- + */
- +
- +#ifndef __RALINK_DMA_CTRL_H__
- +#define __RALINK_DMA_CTRL_H__
- +
- +//#include <asm/rt2880/rt_mmap.h>
- +
- +/*
- + * DEFINITIONS AND MACROS
- + */
- +#define MOD_VERSION "0.4"
- +
- +#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
- +#define MAX_GDMA_CHANNEL 16
- +#elif defined (CONFIG_RALINK_RT3052)
- +#define MAX_GDMA_CHANNEL 8
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628)
- +#define MAX_GDMA_CHANNEL 16
- +#else
- +#error Please Choose System Type
- +#endif
- +
- +
- +#define RALINK_GDMA_CTRL_BASE (RALINK_GDMA_BASE)
- +#if defined (CONFIG_RALINK_RT3052)
- +#define RALINK_GDMAISTS (RALINK_GDMA_BASE + 0x80)
- +#define RALINK_GDMAGCT (RALINK_GDMA_BASE + 0x88)
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +#define RALINK_GDMA_UNMASKINT (RALINK_GDMA_BASE + 0x200)
- +#define RALINK_GDMA_DONEINT (RALINK_GDMA_BASE + 0x204)
- +#define RALINK_GDMA_GCT (RALINK_GDMA_BASE + 0x220)
- +#endif
- +
- +#define KSEG1 0xa0000000
- +#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
- +#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
- +
- +
- +
- +
- +#if defined (CONFIG_ARCH_MT7623)
- +#include <mach/sync_write.h>
- +#define GDMA_READ_REG(phys) (*(volatile unsigned int *)((phys)))
- +#define GDMA_WRITE_REG(phys, val) mt65xx_reg_sync_writel((val), (phys))
- +
- +#else
- +#define GDMA_READ_REG(addr) (le32_to_cpu(*(volatile u32 *)(addr)))
- +#define GDMA_WRITE_REG(addr, val) *((volatile uint32_t *)(addr)) = cpu_to_le32(val)
- +
- +
- +
- +#endif
- +
- +
- +#define GET_GDMA_IP_VER (GDMA_READ_REG(RALINK_GDMA_GCT) & 0x6) >> 1 //GDMA_GCT[2:1]
- +
- +#define RALINK_IRQ_ADDR RALINK_INTCL_BASE
- +#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7628)
- +#define RALINK_REG_INTENA (RALINK_IRQ_ADDR + 0x80)
- +#define RALINK_REG_INTDIS (RALINK_IRQ_ADDR + 0x78)
- +#else
- +#define RALINK_REG_INTENA (RALINK_IRQ_ADDR + 0x34)
- +#define RALINK_REG_INTDIS (RALINK_IRQ_ADDR + 0x38)
- +#endif
- +
- +/*
- + * 12bytes=GDMA Channel n Source Address(4) +
- + * GDMA Channel n Destination Address(4) +
- + * GDMA Channel n Control Register(4)
- + *
- + */
- +#define GDMA_SRC_REG(ch) (RALINK_GDMA_BASE + ch*16)
- +#define GDMA_DST_REG(ch) (GDMA_SRC_REG(ch) + 4)
- +#define GDMA_CTRL_REG(ch) (GDMA_DST_REG(ch) + 4)
- +#define GDMA_CTRL_REG1(ch) (GDMA_CTRL_REG(ch) + 4)
- +
- +//GDMA Interrupt Status Register
- +#if defined (CONFIG_RALINK_RT3052)
- +#define UNMASK_INT_STATUS(ch) (ch+16)
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +#define UNMASK_INT_STATUS(ch) (ch)
- +#endif
- +#define TXDONE_INT_STATUS(ch) (ch)
- +
- +//Control Reg0
- +#define MODE_SEL_OFFSET 0
- +#define CH_EBL_OFFSET 1
- +#define CH_DONEINT_EBL_OFFSET 2
- +#define BRST_SIZE_OFFSET 3
- +#define DST_BRST_MODE_OFFSET 6
- +#define SRC_BRST_MODE_OFFSET 7
- +#define TRANS_CNT_OFFSET 16
- +
- +//Control Reg1
- +#if defined (CONFIG_RALINK_RT3052)
- +#define CH_UNMASKINT_EBL_OFFSET 4
- +#define NEXT_UNMASK_CH_OFFSET 1
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +#define CH_UNMASKINT_EBL_OFFSET 1
- +#define NEXT_UNMASK_CH_OFFSET 3
- +#endif
- +#define COHERENT_INT_EBL_OFFSET 2
- +#define CH_MASK_OFFSET 0
- +
- +
- +#if defined (CONFIG_RALINK_RT3052)
- +//Control Reg0
- +#define DST_DMA_REQ_OFFSET 8
- +#define SRC_DMA_REQ_OFFSET 12
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- +//Control Reg1
- +#define DST_DMA_REQ_OFFSET 8
- +#define SRC_DMA_REQ_OFFSET 16
- +#endif
- +
- +#define GDMA_PCM0_RX0 0
- +#define GDMA_PCM0_RX1 1
- +#define GDMA_PCM0_TX0 2
- +#define GDMA_PCM0_TX1 3
- +
- +#define GDMA_PCM1_RX0 4
- +#define GDMA_PCM1_RX1 5
- +#define GDMA_PCM1_TX0 6
- +#define GDMA_PCM1_TX1 7
- +
- +#define GDMA_PCM_RX(i,j) (0+((i)<<2)+j)
- +#define GDMA_PCM_TX(i,j) (2+((i)<<2)+j)
- +
- +#define GDMA_I2S_TX0 4
- +#define GDMA_I2S_TX1 5
- +#define GDMA_I2S_RX0 6
- +#define GDMA_I2S_RX1 7
- +
- +#define GDMA_SPI_TX 13
- +#define GDMA_SPI_RX 12
- +
- +
- +//#define GDMA_DEBUG
- +#ifdef GDMA_DEBUG
- +#define GDMA_PRINT(fmt, args...) printk(KERN_INFO "GDMA: " fmt, ## args)
- +#else
- +#define GDMA_PRINT(fmt, args...) { }
- +#endif
- +
- +/*
- + * TYPEDEFS AND STRUCTURES
- + */
- +
- +enum GdmaBusterMode {
- + INC_MODE=0,
- + FIX_MODE=1
- +};
- +
- +enum GdmaBusterSize {
- + BUSTER_SIZE_4B=0, /* 1 transfer */
- + BUSTER_SIZE_8B=1, /* 2 transfer */
- + BUSTER_SIZE_16B=2, /* 4 transfer */
- + BUSTER_SIZE_32B=3, /* 8 transfer */
- + BUSTER_SIZE_64B=4 /* 16 transfer */
- +};
- +
- +enum GdmaDmaReqNum {
- +#if defined (CONFIG_RALINK_RT3052)
- + DMA_REQ0=0,
- + DMA_NAND_REQ=1,
- + DMA_I2S_TX_REQ=2,
- + DMA_PCM_RX0_REQ=3,
- + DMA_PCM_RX1_REQ=4,
- + DMA_PCM_TX0_REQ=5,
- + DMA_PCM_TX1_REQ=6,
- + DMA_REG7=7,
- + DMA_MEM_REQ=8
- +#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855)
- + DMA_REQ0=0,
- + DMA_NAND_REQ=1,
- + DMA_I2S_TX_REQ=2,
- + DMA_I2S_RX_REQ=3,
- + DMA_PCM_RX0_REQ=4,
- + DMA_PCM_RX1_REQ=5,
- + DMA_PCM_TX0_REQ=6,
- + DMA_PCM_TX1_REQ=7,
- + DMA_CODEC0_REQ8=8,
- + DMA_CODEC1_REQ9=9,
- + DMA_REQ10=10,
- + DMA_REQ11=11,
- + DMA_REQ12=12,
- + DMA_REQ13=13,
- + DMA_REQ14=14,
- + DMA_REQ15=15,
- +
- + #if defined (CONFIG_RALINK_RT3883)
- + DMA_MEM_REQ=16
- + #elif defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855)
- + DMA_MEM_REQ=32
- + #endif
- +
- +#elif defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
- + DMA_REQ0=0,
- + DMA_NAND_REQ=1,
- + DMA_I2S_TX_REQ=2,
- + DMA_I2S_RX_REQ=3,
- + DMA_PCM_RX0_REQ=4,
- + DMA_PCM_RX1_REQ=5,
- + DMA_PCM_TX0_REQ=6,
- + DMA_PCM_TX1_REQ=7,
- + DMA_PCM_RX2_REQ=8,
- + DMA_PCM_RX3_REQ=9,
- + DMA_PCM_TX2_REQ=10,
- + DMA_PCM_TX3_REQ=11,
- + DMA_SPI_RX_REQ=12,
- + DMA_SPI_TX_REQ=13,
- + DMA_MEM_REQ=32
- +
- +#elif defined (CONFIG_RALINK_RT6855A)
- + DMA_NAND_REQ=0,
- + DMA_I2S_TX_REQ=1,
- + DMA_I2S_RX_REQ=2,
- + DMA_REQ0=3,
- + DMA_PCM_RX0_REQ=4,
- + DMA_PCM_RX1_REQ=5,
- + DMA_PCM_TX0_REQ=6,
- + DMA_PCM_TX1_REQ=7,
- + DMA_CODEC0_REQ8=8,
- + DMA_CODEC1_REQ9=9,
- + DMA_REQ10=10,
- + DMA_REQ11=11,
- + DMA_REQ12=12,
- + DMA_REQ13=13,
- + DMA_REQ14=14,
- + DMA_REQ15=15,
- + DMA_MEM_REQ=32
- +#else
- +#error Please Choose System Type
- +#endif
- +};
- +
- +
- +
- +typedef struct {
- + uint32_t Src;
- + uint32_t Dst;
- + uint16_t TransCount;
- + uint8_t SoftMode;
- + uint8_t NextUnMaskCh;
- + uint8_t ChMask;
- + uint8_t CoherentIntEbl;
- + uint32_t ChNum;
- + enum GdmaDmaReqNum SrcReqNum;
- + enum GdmaDmaReqNum DstReqNum;
- + enum GdmaBusterMode SrcBurstMode;
- + enum GdmaBusterMode DstBurstMode;
- + enum GdmaBusterSize BurstSize;
- + void (*DoneIntCallback)(uint32_t);
- + void (*UnMaskIntCallback)(uint32_t);
- +} GdmaReqEntry;
- +
- +/*
- + * EXPORT FUNCTION
- + */
- +int GdmaI2sTx(uint32_t Src, uint32_t Dst, uint8_t TxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +int GdmaI2sRx(uint32_t Src, uint32_t Dst, uint8_t RxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +int GdmaPcmRx(uint32_t Src, uint32_t Dst, uint8_t PcmNo, uint8_t RxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +int GdmaPcmTx(uint32_t Src, uint32_t Dst, uint8_t PcmNo, uint8_t TxNo, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +int GdmaSpiTx(uint32_t Src, uint32_t Dst, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +int GdmaSpiRx(uint32_t Src, uint32_t Dst, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data),
- + void (*UnMaskIntCallback)(uint32_t data));
- +
- +
- +int GdmaMem2Mem(uint32_t Src, uint32_t Dst, uint16_t TransCount,
- + void (*DoneIntCallback)(uint32_t data));
- +
- +int GdmaMaskChannel(uint32_t ChNum);
- +
- +int GdmaUnMaskChannel(uint32_t ChNum);
- +
- +int GdmaReqQuickIns(uint32_t ChNum);
- +
- +
- +#endif
- --- a/sound/soc/soc-core.c
- +++ b/sound/soc/soc-core.c
- @@ -1851,7 +1851,8 @@ static int soc_probe(struct platform_dev
- /* Bodge while we unpick instantiation */
- card->dev = &pdev->dev;
-
- - return snd_soc_register_card(card);
- + snd_soc_register_card(card);
- + return 0;
- }
-
- static int soc_cleanup_card_resources(struct snd_soc_card *card)
- --- /dev/null
- +++ b/sound/soc/mtk/i2s_debug.c
- @@ -0,0 +1,698 @@
- +#include <linux/init.h>
- +#include <linux/version.h>
- +#include <linux/module.h>
- +#include <linux/kernel.h> /* printk() */
- +#include "i2s_ctrl.h"
- +#include <linux/delay.h>
- +#include <linux/jiffies.h>
- +#include <linux/random.h>
- +#include <linux/slab.h>
- +#include <asm/uaccess.h> /* copy_from/to_user */
- +
- +#if defined(CONFIG_SND_RALINK_SOC)
- +#include <sound/soc/mtk/mtk_audio_device.h>
- +#endif
- +
- +#if defined(CONFIG_I2S_WM8750)
- +#include "../codec/i2c_wm8750.h"
- +#endif
- +#if defined(CONFIG_I2S_WM8751)
- +#include "../codec/i2c_wm8751.h"
- +#endif
- +#if defined(CONFIG_I2S_WM8960)
- +#include "i2c_wm8960.h"
- +#endif
- +
- +
- +//#define INTERNAL_LOOPBACK_DEBUG
- +
- +extern unsigned long i2s_codec_12p288Mhz[11];
- +extern unsigned long i2s_codec_12Mhz[11];
- +#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- +extern unsigned long i2s_inclk_int_16bit[13];
- +extern unsigned long i2s_inclk_comp_16bit[13];
- +extern unsigned long i2s_inclk_int_24bit[13];
- +extern unsigned long i2s_inclk_comp_24bit[13];
- +#else
- +extern unsigned long i2s_inclk_int[11];
- +extern unsigned long i2s_inclk_comp[11];
- +#endif
- +extern int i2s_pll_config_mt7621(unsigned long index);
- +extern int i2s_pll_config_mt7623(unsigned long index);
- +
- +#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- +extern void audiohw_loopback(int fsel);
- +extern void audiohw_bypass(void);
- +extern int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r);
- +extern int audiohw_set_linein_vol(int vol_l, int vol_r);
- +#endif
- +
- +#if defined(CONFIG_I2S_WM8960)
- +extern void audiohw_codec_exlbk(void);
- +#endif
- +
- +unsigned long txbuffer[512] = {
- + 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 1
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 2
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 3
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 4
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 5
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 6
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 7
- +0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20,
- + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40,
- + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60,
- + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80,
- + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0,
- + 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0,
- + 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0,
- + 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00 //round 8
- + };
- +
- +int i2s_debug_cmd(unsigned int cmd, unsigned long arg)
- +{
- + unsigned long data, index;
- + unsigned long *pTable;
- + int i;
- +
- + switch(cmd)
- + {
- + case I2S_DEBUG_CLKGEN:
- + MSG("I2S_DEBUG_CLKGEN\n");
- +#if defined(CONFIG_RALINK_RT3052)
- + *(volatile unsigned long*)(0xB0000060) = 0x00000016;
- + *(volatile unsigned long*)(0xB0000030) = 0x00009E00;
- + *(volatile unsigned long*)(0xB0000A00) = 0xC0000040;
- +#elif defined(CONFIG_RALINK_RT3350)
- + *(volatile unsigned long*)(0xB0000060) = 0x00000018;
- + *(volatile unsigned long*)(0xB000002C) = 0x00000100;
- + *(volatile unsigned long*)(0xB0000030) = 0x00009E00;
- + *(volatile unsigned long*)(0xB0000A00) = 0xC0000040;
- +#elif defined(CONFIG_RALINK_RT3883)
- + *(volatile unsigned long*)(0xB0000060) = 0x00000018;
- + *(volatile unsigned long*)(0xB000002C) = 0x00003000;
- + *(volatile unsigned long*)(0xB0000A00) = 0xC1104040;
- + *(volatile unsigned long*)(0xB0000A24) = 0x00000027;
- + *(volatile unsigned long*)(0xB0000A20) = 0x80000020;
- +#elif (defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350)) || defined (CONFIG_RALINK_RT6855)
- + *(volatile unsigned long*)(0xB0000060) = 0x00000018;
- + *(volatile unsigned long*)(0xB000002C) = 0x00000300;
- + *(volatile unsigned long*)(0xB0000A00) = 0xC1104040;
- + *(volatile unsigned long*)(0xB0000A24) = 0x00000027;
- + *(volatile unsigned long*)(0xB0000A20) = 0x80000020;
- +#elif defined(CONFIG_RALINK_RT6855A)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) = 0x00008080;
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xC1104040;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = 0x00000027;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = 0x80000020;
- +#else
- +//#error "I2S debug mode not support this Chip"
- +#endif
- + break;
- + case I2S_DEBUG_INLBK:
- + MSG("I2S_DEBUG_INLBK\n");
- +#if defined(CONFIG_RALINK_MT7621)
- + switch(96000)
- + {
- + case 8000:
- + index = 0;
- + break;
- + case 11025:
- + index = 1;
- + break;
- + case 12000:
- + index = 2;
- + break;
- + case 16000:
- + index = 3;
- + break;
- + case 22050:
- + index = 4;
- + break;
- + case 24000:
- + index = 5;
- + break;
- + case 32000:
- + index = 6;
- + break;
- + case 44100:
- + index = 7;
- + break;
- + case 48000:
- + index = 8;
- + break;
- + case 88200:
- + index = 9;
- + break;
- + case 96000:
- + index = 10;
- + break;
- + case 192000:
- + index = 11;
- + break;
- + default:
- + index = 7;
- + }
- + i2s_pll_config_mt7621(index);
- +#elif defined(CONFIG_ARCH_MT7623)
- + i2s_pll_config_mt7623(11);
- +#endif
- +
- +
- +#if defined(CONFIG_RALINK_RT3052)
- + break;
- +#endif
- +#if defined(CONFIG_RALINK_RT6855A)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x834) |= 0x00020000;
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x834) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) |= 0x00008080;
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300;
- +#elif defined(CONFIG_RALINK_MT7621)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) |= 0x00020000;
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) = 0x00000010; //GPIO purpose selection
- +#elif defined(CONFIG_RALINK_MT7628)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) |= 0x00020000;
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) &= ~((0x3)<<6); //GPIO purpose selection /*FIXME*/
- +#elif defined(CONFIG_ARCH_MT7623)
- + *(volatile unsigned long*)(0xFB000034) |= 0x00020000;
- + *(volatile unsigned long*)(0xFB000034) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(ETHDMASYS_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule
- +
- + *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<12);
- + *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<12);
- + *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<9);
- + *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<9);
- + *(volatile unsigned long*)(0xF0005040) |= ((0x1)<<10);
- + *(volatile unsigned long*)(0xF0005040) |= ((0x1)<<9);
- +
- + *(volatile unsigned long*)(0xF00057F0) &= ~((0x7)<<12);
- + *(volatile unsigned long*)(0xF00057F0) |= ((0x6)<<12);
- + *(volatile unsigned long*)(0xF0005030) |= ((0x1)<<1);
- +
- + *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<6);
- + *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<6);
- + *(volatile unsigned long*)(0xF0005040) &= ~((0x1)<<8);
- +
- + *(volatile unsigned long*)(0xF00058F0) &= ~((0x7)<<3);
- + *(volatile unsigned long*)(0xF00058F0) |= ((0x6)<<3);
- + *(volatile unsigned long*)(0xF0005070) |= ((0x1)<<14);
- +
- +
- +#else
- + *(volatile unsigned long*)(0xB0000034) |= 0x00020000;
- + *(volatile unsigned long*)(0xB0000034) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(0xB0000A00) &= 0x7FFFFFFF; //Rest I2S to default vaule
- + *(volatile unsigned long*)(0xB0000060) = 0x00000018;
- +
- +#if defined(CONFIG_RALINK_RT3883)
- + *(volatile unsigned long*)(0xB000002C) = 0x00003000;
- +#elif defined(CONFIG_ARCH_MT7623)
- +
- +#else
- + *(volatile unsigned long*)(0xB000002C) = 0x00000300;
- +#endif
- +#endif
- +#if defined(CONFIG_RALINK_MT7621)
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xc1104040;
- +
- + pTable = i2s_inclk_int;
- + data = pTable[index];
- + //*(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = data;
- + i2s_outw(RALINK_I2S_BASE+0x24, data);
- +
- + pTable = i2s_inclk_comp;
- + data = pTable[index];
- + //*(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = data;
- + i2s_outw(RALINK_I2S_BASE+0x20, (data|0x80000000));
- +#elif defined(CONFIG_RALINK_MT7628)
- + index =11; /* SR: 192k */
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xc1104040;
- +
- + pTable = i2s_inclk_int_16bit;
- + //pTable = i2s_inclk_int_24bit;
- + data = pTable[index];
- + //*(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = data;
- + i2s_outw(RALINK_I2S_BASE+0x24, data);
- +
- + pTable = i2s_inclk_comp_16bit;
- + //pTable = i2s_inclk_comp_24bit;
- + data = pTable[index];
- + //*(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = data;
- + i2s_outw(RALINK_I2S_BASE+0x20, (data|0x80000000));
- + mdelay(5);
- +#elif defined(CONFIG_ARCH_MT7623)
- + index = 11;
- + *(volatile unsigned long*)(I2S_I2SCFG1) = 0x80000000;
- + *(volatile unsigned long*)(I2S_I2SCFG) = 0xE1104040;
- + *(volatile unsigned long*)(ETHDMASYS_SYSCTL_BASE+0x30) |= 0x00020000;
- + *(volatile unsigned long*)(ETHDMASYS_SYSCTL_BASE+0x2c) |= 0x00000080;
- +
- + pTable = i2s_inclk_int_16bit;
- + //pTable = i2s_inclk_int_24bit;
- + data = pTable[index];
- + i2s_outw(I2S_DIVINT_CFG, data);
- +
- + pTable = i2s_inclk_comp_16bit;
- + //pTable = i2s_inclk_comp_24bit;
- + data = pTable[index];
- + i2s_outw(I2S_DIVCOMP_CFG, (data|0x80000000));
- + mdelay(5);
- +#else
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xC1104040;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = 0x00000006;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = 0x80000105;
- +#endif
- + {
- + int count = 0;
- + int k=0;
- + int enable_cnt=0;
- + unsigned long param[4];
- + unsigned long data;
- + //unsigned long data_tmp;
- + unsigned long ff_status;
- + //unsigned long* txbuffer;
- +#if 0
- + int j=0;
- + int temp = 0;
- +#endif
- +#if defined (INTERNAL_LOOPBACK_DEBUG)
- + int count2 = 0;
- +#endif
- + memset(param, 0, 4*sizeof(unsigned long) );
- + copy_from_user(param, (unsigned long*)arg, sizeof(long)*2);
- +#if 0
- + txbuffer = (unsigned long*)kcalloc(param[0], sizeof(unsigned long), GFP_KERNEL);
- + if(txbuffer == NULL)
- + return -1;
- +#endif
- +
- + //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C);
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + printk("ff status=[0x%08X]\n",(u32)ff_status);
- +
- +#if 0
- + for(i = 0; i < param[0]; i++)
- + {
- + if (i==0)
- + {
- + txbuffer[i] = 0x555A555A;
- + printk("%d: 0x%8lx\n", i, txbuffer[i]);
- + }
- + else
- + {
- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,14)
- + srandom32(jiffies);
- + txbuffer[i] = random32()%(0x555A555A)+1;
- + //printk("%d: 0x%8x\n", i, txbuffer[i]);
- + #else
- + //TODO:do we need to implement random32()
- + txbuffer[i] = 0x01010101;
- + #endif
- + }
- + }
- +#endif
- +
- + for( i = 0 ; i < param[0] ; i ++ )
- + {
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + #if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + if((ff_status&0xFF) > 0)
- + #else
- + if((ff_status&0x0F) > 0)
- + #endif
- + {
- + *(volatile unsigned long*)(I2S_TX_FIFO_WREG) = txbuffer[i];
- + mdelay(1);
- + }
- + else
- + {
- + mdelay(1);
- + printk("[%d]NO TX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status);
- + continue;
- + }
- +
- + //if(i >= 16)
- + {
- +
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + #if defined(CONFIG_RALINK_MT7628)
- + if(((ff_status>>8)&0xFF) > 0)
- + #else
- + if(((ff_status>>4)&0x0F) > 0)
- + #endif
- + {
- + data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG);
- + //data_tmp = *(volatile unsigned long*)(I2S_RX_FIFO_RREG);
- + //MSG("[0x%08X] vs [0x%08X]\n", (u32)data, (u32)data_tmp);
- + }
- + else
- + {
- + printk("*[%d]NO RX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status);
- + continue;
- + }
- +
- + if (data == txbuffer[0])
- + {
- + k = i;
- + enable_cnt = 1;
- + }
- + if (enable_cnt==1)
- + {
- + if(data!= txbuffer[i-k])
- + {
- + MSG("[%d][0x%08X] vs [0x%08X]\n", (i-k), (u32)data, (u32)txbuffer[i-k]);
- + }
- + else
- + {
- + //MSG("**[%d][0x%08X] vs [0x%08X]\n" ,(i-k), (u32)data , (u32)txbuffer[i-k]);
- + count++;
- + data=0;
- + }
- + }
- +
- + }
- + }
- +#if 0
- + temp = i-k;
- + for (j=0; j<k; j++)
- + {
- +
- + //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C);
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + #if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
- + if(((ff_status>>8)&0xFF) > 0)
- + #else
- + if(((ff_status>>4)&0x0F) > 0)
- + #endif
- + {
- + //data = *(volatile unsigned long*)(RALINK_I2S_BASE+0x14);
- + data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG);
- + }
- + else
- + {
- + printk("*NO RX FREE FIFO ST=[0x%08X]\n", (u32)ff_status);
- + continue;
- + }
- +
- + if(data!= txbuffer[temp+j])
- + {
- + MSG("[%d][0x%08X] vs [0x%08X]\n", (temp+j), (u32)data, (u32)txbuffer[temp+j]);
- + }
- + else
- + {
- + //MSG("&&[%d][0x%08X] vs [0x%08X]\n" ,(temp+j), (u32)data , (u32)txbuffer[temp+j]);
- + count++;
- + data=0;
- + }
- + if ((temp+j)==128)
- + {
- + //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C);
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + //printk("[%d]FIFO ST=[0x%08X]\n", (temp+j), (u32)ff_status);
- + }
- + }
- +#endif
- +
- +#if defined (INTERNAL_LOOPBACK_DEBUG)
- + for( i = 0 ; i < param[0] ; i ++ )
- + {
- + //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C);
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + #if defined(CONFIG_RALINK_MT7628)|| defined(CONFIG_ARCH_MT7623)
- + if((ff_status&0xFF) > 0)
- + #else
- + if((ff_status&0x0F) > 0)
- + #endif
- + {
- + //*(volatile unsigned long*)(RALINK_I2S_BASE+0x10) = txbuffer[i];
- + *(volatile unsigned long*)(I2S_TX_FIFO_WREG) = txbuffer[i];
- + mdelay(1);
- + }
- + else
- + {
- + mdelay(1);
- + printk("[%d]NO TX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status);
- + continue;
- + }
- +
- + //if(i >= 16)
- + {
- +
- + //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C);
- + ff_status = *(volatile unsigned long*)(I2S_FF_STATUS);
- + #if defined(CONFIG_RALINK_MT7628)|| defined(CONFIG_ARCH_MT7623)
- + if(((ff_status>>8)&0xFF) > 0)
- + #else
- + if(((ff_status>>4)&0x0F) > 0)
- + #endif
- + {
- + //data = *(volatile unsigned long*)(RALINK_I2S_BASE+0x14);
- + data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG);
- + }
- + else
- + {
- + printk("*[%d]NO RX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status);
- + continue;
- + }
- +
- + {
- + if(data!= txbuffer[i])
- + {
- + MSG("[%d][0x%08X] vs [0x%08X]\n", (i), (u32)data, (u32)txbuffer[i]);
- + }
- + else
- + {
- + MSG("**[%d][0x%08X] vs [0x%08X]\n" ,(i), (u32)data , (u32)txbuffer[i]);
- + count2++;
- + data=0;
- + }
- + }
- +
- + }
- + }
- + printk("Pattern match done count2=%d.\n", count2);
- +#endif
- + printk("Pattern match done count=%d.\n", count);
- +
- + }
- +#if defined(CONFIG_ARCH_MT7623)
- + *(volatile unsigned long*)(0xFB000034) |= 0x00020000;
- + *(volatile unsigned long*)(0xFB000034) &= 0xFFFDFFFF;
- + *(volatile unsigned long*)(ETHDMASYS_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule
- +#endif
- +
- +#if !defined(CONFIG_RALINK_RT3052)
- + break;
- +#endif
- + case I2S_DEBUG_EXLBK:
- + MSG("I2S_DEBUG_EXLBK\n");
- +#if !defined(CONFIG_ARCH_MT7623)
- + switch(arg)
- + {
- + case 8000:
- + index = 0;
- + break;
- + case 11025:
- + index = 1;
- + break;
- + case 12000:
- + index = 2;
- + break;
- + case 16000:
- + index = 3;
- + break;
- + case 22050:
- + index = 4;
- + break;
- + case 24000:
- + index = 5;
- + break;
- + case 32000:
- + index = 6;
- + break;
- + case 44100:
- + index = 7;
- + break;
- + case 48000:
- + index = 8;
- + break;
- + case 88200:
- + index = 9;
- + break;
- + case 96000:
- + index = 10;
- + break;
- + default:
- + index = 7;
- + }
- +#if defined(CONFIG_RALINK_RT3052)
- + break;
- +#endif
- +#if defined(CONFIG_RALINK_RT6855A)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) = 0x00008080;
- + //*(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300;
- +#else
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) = 0x00000018;
- +#if defined(CONFIG_RALINK_RT3883)
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x2C) = 0x00003000;
- +#else
- + *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x2C) = 0x00000300;
- +#endif
- +#endif
- +
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x40000000;
- + *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0x81104040;
- +#if defined(CONFIG_RALINK_MT7628)
- + pTable = i2s_inclk_int_16bit;
- +#else
- + pTable = i2s_inclk_int;
- +#endif
- + data = (volatile unsigned long)(pTable[index]);
- + i2s_outw(I2S_DIVINT_CFG, data);
- +#if defined(CONFIG_RALINK_MT7628)
- + pTable = i2s_inclk_comp_16bit;
- +#else
- + pTable = i2s_inclk_comp;
- +#endif
- + data = (volatile unsigned long)(pTable[index]);
- + data |= REGBIT(1, I2S_CLKDIV_EN);
- + i2s_outw(I2S_DIVCOMP_CFG, data);
- +
- + #if defined(CONFIG_I2S_MCLK_12MHZ)
- + pTable = i2s_codec_12Mhz;
- + #if defined(CONFIG_I2S_WM8960)
- + data = pTable[index];
- + #else
- + data = pTable[index]|0x01;
- + #endif
- + #else
- + pTable = i2s_codec_12p288Mhz;
- + data = pTable[index];
- + #endif
- +
- + #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_preinit();
- + #endif
- +
- +
- + #if defined (CONFIG_I2S_WM8960)
- + audiohw_postinit(1, 1, 1, 1, 0); // for codec apll enable, 16 bit word length
- + #elif defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_postinit(1, 1, 1, 0); // for 16 bit word length
- + #endif
- +
- +
- + #if defined (CONFIG_I2S_WM8960)
- + audiohw_set_frequency(data, 1); // for codec apll enable
- + #elif defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_set_frequency(data|0x1);
- + #endif
- +
- +
- + #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_set_lineout_vol(1, 100, 100);
- + audiohw_set_linein_vol(100, 100);
- + #endif
- +
- +
- + #if defined(CONFIG_I2S_TXRX)
- + //audiohw_loopback(data);
- + #endif
- + #if !defined(CONFIG_RALINK_RT3052)
- + break;
- + #endif
- +#endif
- + case I2S_DEBUG_CODECBYPASS:
- + #if defined(CONFIG_I2S_TXRX)
- + #if defined(CONFIG_RALINK_MT7628)
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x60);
- + //data &= ~(0x3<<4);
- + data &= ~(0x3<<6);
- + data &= ~(0x3<<16);
- + data &= ~(0x1<<14);
- + i2s_outw(RALINK_SYSCTL_BASE+0x60, data);
- +
- + data = i2s_inw(RALINK_SYSCTL_BASE+0x2c);
- + data &= ~(0x07<<9);
- + i2s_outw(RALINK_SYSCTL_BASE+0x2c, data);
- + #endif
- +
- + #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)
- + audiohw_bypass(); /* did not work */
- + #endif
- + #endif
- + break;
- + case I2S_DEBUG_FMT:
- + break;
- + case I2S_DEBUG_RESET:
- + break;
- +#if defined(CONFIG_I2S_WM8960)
- + case I2S_DEBUG_CODEC_EXLBK:
- + audiohw_codec_exlbk();
- + break;
- +#endif
- + default:
- + MSG("Not support this debug cmd [%d]\n", cmd);
- + break;
- + }
- +
- + return 0;
- +}
- --- a/sound/soc/codecs/wm8960.c
- +++ b/sound/soc/codecs/wm8960.c
- @@ -53,10 +53,10 @@
- * using 2 wire for device control, so we cache them instead.
- */
- static const struct reg_default wm8960_reg_defaults[] = {
- - { 0x0, 0x00a7 },
- - { 0x1, 0x00a7 },
- - { 0x2, 0x0000 },
- - { 0x3, 0x0000 },
- + { 0x0, 0x002b },
- + { 0x1, 0x002b },
- + { 0x2, 0x00ff },
- + { 0x3, 0x00ff },
- { 0x4, 0x0000 },
- { 0x5, 0x0008 },
- { 0x6, 0x0000 },
- @@ -88,8 +88,8 @@ static const struct reg_default wm8960_r
- { 0x25, 0x0050 },
- { 0x26, 0x0000 },
- { 0x27, 0x0000 },
- - { 0x28, 0x0000 },
- - { 0x29, 0x0000 },
- + { 0x28, 0x007b },
- + { 0x29, 0x007b },
- { 0x2a, 0x0040 },
- { 0x2b, 0x0000 },
- { 0x2c, 0x0000 },
- @@ -126,8 +126,7 @@ struct wm8960_priv {
- bool deemph;
- int playback_fs;
- };
- -
- -#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
- +static char init_mtk;
-
- /* enumerated controls */
- static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
- @@ -181,8 +180,8 @@ static int wm8960_get_deemph(struct snd_
- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
-
- - ucontrol->value.integer.value[0] = wm8960->deemph;
- - return 0;
- + //ucontrol->value.integer.value[0] = wm8960->deemph;
- + return wm8960->deemph;
- }
-
- static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
- @@ -200,6 +199,65 @@ static int wm8960_put_deemph(struct snd_
- return wm8960_set_deemph(codec);
- }
-
- +static void wm8960_reset(struct snd_soc_codec *codec)
- +{
- + snd_soc_write(codec, WM8960_RESET, 0);
- + init_mtk = false;
- +}
- +
- +static int wm8960_init(struct snd_soc_codec *codec)
- +{
- + u32 data;
- + // In
- + data = snd_soc_read(codec, WM8960_POWER1);
- + snd_soc_write(codec, WM8960_POWER1, data|WM8960_PWR1_ADCL|WM8960_PWR1_ADCR|WM8960_PWR1_AINL |WM8960_PWR1_AINR|WM8960_PWR1_MICB|WM8960_PWR1_VMIDSEL_5K|WM8960_PWR1_VREF);//0x19
- + data = snd_soc_read(codec, WM8960_ADDCTL1);
- + snd_soc_write(codec, WM8960_ADDCTL1, data|ADDITIONAL1_DATSEL(0x01));//0x17
- + snd_soc_write(codec, WM8960_LADC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xce));//0x15
- + snd_soc_write(codec, WM8960_RADC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xce));//0x16
- + snd_soc_write(codec, WM8960_LINPATH, 0x168);//0x20
- + snd_soc_write(codec, WM8960_RINPATH, 0x168);//0x21
- + snd_soc_write(codec, WM8960_POWER3, WM8960_PWR3_LMIC|WM8960_PWR3_RMIC|WM8960_PWR3_ROMIX|WM8960_PWR3_LOMIX);//0x2f
- +
- + // Out
- + data = snd_soc_read(codec, WM8960_POWER2);
- + snd_soc_write(codec, WM8960_POWER2, data|WM8960_PWR2_DACL|WM8960_PWR2_DACR|WM8960_PWR2_LOUT1|WM8960_PWR2_ROUT1|WM8960_PWR2_SPKL|WM8960_PWR2_SPKR);//0x1a
- + mdelay(10);
- + snd_soc_write(codec, WM8960_IFACE2, 0x40);
- + snd_soc_write(codec, WM8960_LDAC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xff));//0x0a
- + snd_soc_write(codec, WM8960_RDAC, RIGHTGAIN_RDVU|RIGHTGAIN_RDACVOL(0xff));//0x0b
- + snd_soc_write(codec, WM8960_LOUTMIX, 0x100);//0x22
- + snd_soc_write(codec, WM8960_ROUTMIX, 0x100);//0x25
- +
- + snd_soc_write(codec, WM8960_CLASSD1, 0xf7);//0x31
- + snd_soc_write(codec, WM8960_CLASSD3, 0xad);//0x33
- + snd_soc_write(codec, WM8960_DACCTL1, 0x000);//0x05
- +
- + snd_soc_write(codec, WM8960_LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(120));//0x02
- + snd_soc_write(codec, WM8960_ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(120));//0x03
- +
- + data = snd_soc_read(codec, WM8960_LINVOL);
- + data &= ~LINV_LINMUTE;
- + snd_soc_write(codec, WM8960_LINVOL, data|LINV_IPVU|LINV_LINVOL(96));//LINV(0x00)
- +
- + data = snd_soc_read(codec, WM8960_RINVOL);
- + data &= ~RINV_RINMUTE;
- + snd_soc_write(codec, WM8960_RINVOL, data|RINV_IPVU|RINV_RINVOL(96)); //LINV(0x01)
- +
- + init_mtk = true;
- + return 0;
- +}
- +
- +static int wm8960_close(struct snd_soc_codec *codec)
- +{
- + snd_soc_write(codec, WM8960_DACCTL1,0x8); //0x05->0x08
- + snd_soc_write(codec, WM8960_POWER1, 0x000); //0x19->0x000
- + mdelay(300);
- + snd_soc_write(codec, WM8960_POWER2, 0x000); //0x1a->0x000
- +
- + return 0;
- +}
- +
- static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
- static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
- static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
- @@ -542,6 +600,9 @@ static int wm8960_set_dai_fmt(struct snd
-
- /* set iface */
- snd_soc_write(codec, WM8960_IFACE1, iface);
- + if (!init_mtk)
- + wm8960_init(codec);
- +
- return 0;
- }
-
- @@ -623,11 +684,15 @@ static int wm8960_set_bias_level_out3(st
- break;
-
- case SND_SOC_BIAS_PREPARE:
- +#if 0
- /* Set VMID to 2x50k */
- snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
- +#endif
- break;
-
- case SND_SOC_BIAS_STANDBY:
- +#if 0
- +
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- regcache_sync(wm8960->regmap);
-
- @@ -650,9 +715,13 @@ static int wm8960_set_bias_level_out3(st
-
- /* Set VMID to 2x250k */
- snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x100);
- +#endif
- break;
-
- case SND_SOC_BIAS_OFF:
- +#if 0
- + wm8960_close(codec);
- +
- /* Enable anti-pop features */
- snd_soc_write(codec, WM8960_APOP1,
- WM8960_POBCTRL | WM8960_SOFT_ST |
- @@ -661,6 +730,7 @@ static int wm8960_set_bias_level_out3(st
- /* Disable VMID and VREF, let them discharge */
- snd_soc_write(codec, WM8960_POWER1, 0);
- msleep(600);
- +#endif
- break;
- }
-
- @@ -853,7 +923,6 @@ static int wm8960_set_dai_pll(struct snd
-
- if (pll_div.k) {
- reg |= 0x20;
- -
- snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff);
- snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff);
- snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff);
- @@ -962,7 +1031,7 @@ static int wm8960_probe(struct snd_soc_c
- {
- struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
- struct wm8960_data *pdata = dev_get_platdata(codec->dev);
- - int ret;
- + int ret = 0;
-
- wm8960->set_bias_level = wm8960_set_bias_level_out3;
-
- @@ -973,26 +1042,9 @@ static int wm8960_probe(struct snd_soc_c
- wm8960->set_bias_level = wm8960_set_bias_level_capless;
- }
-
- - ret = wm8960_reset(codec);
- - if (ret < 0) {
- - dev_err(codec->dev, "Failed to issue reset\n");
- - return ret;
- - }
- -
- - wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- -
- - /* Latch the update bits */
- - snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
- - snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
- -
- + wm8960_reset(codec);
- + //mdelay(400);
- +
- snd_soc_add_codec_controls(codec, wm8960_snd_controls,
- ARRAY_SIZE(wm8960_snd_controls));
- wm8960_add_widgets(codec);
- --- a/sound/soc/codecs/wm8960.h
- +++ b/sound/soc/codecs/wm8960.h
- @@ -110,4 +110,68 @@
- #define WM8960_OPCLK_DIV_5_5 (4 << 0)
- #define WM8960_OPCLK_DIV_6 (5 << 0)
-
- +/*
- + * WM8960 Power management
- + */
- +#define WM8960_PWR1_VMIDSEL_DISABLED (0 << 7)
- +#define WM8960_PWR1_VMIDSEL_50K (1 << 7)
- +#define WM8960_PWR1_VMIDSEL_250K (2 << 7)
- +#define WM8960_PWR1_VMIDSEL_5K (3 << 7)
- +#define WM8960_PWR1_VREF (1 << 6)
- +#define WM8960_PWR1_AINL (1 << 5)
- +#define WM8960_PWR1_AINR (1 << 4)
- +#define WM8960_PWR1_ADCL (1 << 3)
- +#define WM8960_PWR1_ADCR (1 << 2)
- +#define WM8960_PWR1_MICB (1 << 1)
- +#define WM8960_PWR1_DIGENB (1 << 0)
- +
- +#define WM8960_PWR2_DACL (1 << 8)
- +#define WM8960_PWR2_DACR (1 << 7)
- +//#define WM8960_PWR2_LOUT1 (1 << 6)
- +//#define WM8960_PWR2_ROUT1 (1 << 5)
- +#define WM8960_PWR2_SPKL (1 << 4)
- +#define WM8960_PWR2_SPKR (1 << 3)
- +//#define WM8960_PWR2_OUT3 (1 << 1)
- +#define WM8960_PWR2_PLL_EN (1 << 0)
- +
- +#define WM8960_PWR3_LMIC (1 << 5)
- +#define WM8960_PWR3_RMIC (1 << 4)
- +#define WM8960_PWR3_LOMIX (1 << 3)
- +#define WM8960_PWR3_ROMIX (1 << 2)
- +
- +#define LEFTGAIN 0x0a
- +#define LEFTGAIN_LDVU (1 << 8)
- +#define LEFTGAIN_LDACVOL(x) ((x) & 0xff)
- +
- +#define RIGHTGAIN 0x0b
- +#define RIGHTGAIN_RDVU (1 << 8)
- +#define RIGHTGAIN_RDACVOL(x) ((x) & 0xff)
- +
- +#define ADDITIONAL1_DATSEL(x) (((x) & 0x3) << 2)
- +
- +#define AINTFCE1_WL_32 (3 << 2)
- +#define AINTFCE1_WL_24 (2 << 2)
- +#define AINTFCE1_WL_20 (1 << 2)
- +#define AINTFCE1_WL_16 (0 << 2)
- +#define AINTFCE1_FORMAT_I2S (2 << 0)
- +
- +#define LOUT1_LO1VU (1 << 8)
- +#define LOUT1_LO1ZC (1 << 7)
- +#define LOUT1_LOUT1VOL(x) ((x) & 0x7f)
- +
- +#define ROUT1_RO1VU (1 << 8)
- +#define ROUT1_RO1ZC (1 << 7)
- +#define ROUT1_ROUT1VOL(x) ((x) & 0x7f)
- +
- +#define LINV_IPVU (1 << 8) /* FIXME */
- +
- +#define LINV_LINMUTE (1 << 7)
- +#define LINV_LIZC (1 << 6)
- +#define LINV_LINVOL(x) ((x) & 0x3f)
- +
- +#define RINV_IPVU (1 << 8) /* FIXME */
- +#define RINV_RINMUTE (1 << 7)
- +#define RINV_RIZC (1 << 6)
- +#define RINV_RINVOL(x) ((x) & 0x3f)
- +#define MBSEL (1 << 0)
- #endif
|